1 /* Copyright (C) 2011-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
23 #include <not-cancel.h>
25 #include "nscd-client.h"
26 #include "nscd_proto.h"
28 int __nss_not_use_nscd_netgroup
;
31 libc_locked_map_ptr (static, map_handle
);
32 /* Note that we only free the structure if necessary. The memory
33 mapping is not removed since it is not visible to the malloc
35 libc_freeres_fn (pw_map_free
)
37 if (map_handle
.mapped
!= NO_MAPPING
)
39 void *p
= map_handle
.mapped
;
40 map_handle
.mapped
= NO_MAPPING
;
47 __nscd_setnetgrent (const char *group
, struct __netgrent
*datap
)
51 size_t group_len
= strlen (group
) + 1;
53 /* If the mapping is available, try to search there instead of
54 communicating with the nscd. */
55 struct mapped_database
*mapped
;
56 mapped
= __nscd_get_map_ref (GETFDNETGR
, "netgroup", &map_handle
, &gc_cycle
);
59 char *respdata
= NULL
;
61 netgroup_response_header netgroup_resp
;
63 if (mapped
!= NO_MAPPING
)
65 struct datahead
*found
= __nscd_cache_search (GETNETGRENT
, group
,
67 sizeof netgroup_resp
);
70 respdata
= (char *) (&found
->data
[0].netgroupdata
+ 1);
71 netgroup_resp
= found
->data
[0].netgroupdata
;
72 /* Now check if we can trust pw_resp fields. If GC is
73 in progress, it can contain anything. */
74 if (mapped
->head
->gc_cycle
!= gc_cycle
)
85 sock
= __nscd_open_socket (group
, group_len
, GETNETGRENT
,
86 &netgroup_resp
, sizeof (netgroup_resp
));
89 /* nscd not running or wrong version. */
90 __nss_not_use_nscd_netgroup
= 1;
95 if (netgroup_resp
.found
== 1)
97 size_t datalen
= netgroup_resp
.result_len
;
99 /* If we do not have to read the data here it comes from the
100 mapped data and does not have to be freed. */
101 if (respdata
== NULL
)
103 /* The data will come via the socket. */
104 respdata
= malloc (datalen
);
105 if (respdata
== NULL
)
108 if ((size_t) __readall (sock
, respdata
, datalen
) != datalen
)
115 datap
->data
= respdata
;
116 datap
->data_size
= datalen
;
117 datap
->cursor
= respdata
;
119 datap
->nip
= (service_user
*) -1l;
120 datap
->known_groups
= NULL
;
121 datap
->needed_groups
= NULL
;
127 if (__glibc_unlikely (netgroup_resp
.found
== -1))
129 /* The daemon does not cache this database. */
130 __nss_not_use_nscd_netgroup
= 1;
134 /* Set errno to 0 to indicate no error, just no found record. */
136 /* Even though we have not found anything, the result is zero. */
142 __close_nocancel_nostatus (sock
);
144 if (__nscd_drop_map_ref (mapped
, &gc_cycle
) != 0)
146 /* When we come here this means there has been a GC cycle while we
147 were looking for the data. This means the data might have been
148 inconsistent. Retry if possible. */
149 if ((gc_cycle
& 1) != 0 || ++nretries
== 5 || retval
== -1)
151 /* nscd is just running gc now. Disable using the mapping. */
152 if (atomic_decrement_val (&mapped
->counter
) == 0)
153 __nscd_unmap (mapped
);
166 __nscd_innetgr (const char *netgroup
, const char *host
, const char *user
,
169 size_t key_len
= (strlen (netgroup
) + strlen (host
?: "")
170 + strlen (user
?: "") + strlen (domain
?: "") + 7);
172 bool use_alloca
= __libc_use_alloca (key_len
);
174 key
= alloca (key_len
);
177 key
= malloc (key_len
);
181 char *wp
= stpcpy (key
, netgroup
) + 1;
185 wp
= stpcpy (wp
, host
) + 1;
192 wp
= stpcpy (wp
, user
) + 1;
199 wp
= stpcpy (wp
, domain
) + 1;
205 /* If the mapping is available, try to search there instead of
206 communicating with the nscd. */
209 struct mapped_database
*mapped
;
210 mapped
= __nscd_get_map_ref (GETFDNETGR
, "netgroup", &map_handle
, &gc_cycle
);
214 innetgroup_response_header innetgroup_resp
;
217 if (mapped
!= NO_MAPPING
)
219 struct datahead
*found
= __nscd_cache_search (INNETGR
, key
,
221 sizeof innetgroup_resp
);
224 innetgroup_resp
= found
->data
[0].innetgroupdata
;
225 /* Now check if we can trust pw_resp fields. If GC is
226 in progress, it can contain anything. */
227 if (mapped
->head
->gc_cycle
!= gc_cycle
)
237 sock
= __nscd_open_socket (key
, key_len
, INNETGR
,
238 &innetgroup_resp
, sizeof (innetgroup_resp
));
241 /* nscd not running or wrong version. */
242 __nss_not_use_nscd_netgroup
= 1;
247 if (innetgroup_resp
.found
== 1)
248 retval
= innetgroup_resp
.result
;
251 if (__glibc_unlikely (innetgroup_resp
.found
== -1))
253 /* The daemon does not cache this database. */
254 __nss_not_use_nscd_netgroup
= 1;
258 /* Set errno to 0 to indicate no error, just no found record. */
260 /* Even though we have not found anything, the result is zero. */
266 __close_nocancel_nostatus (sock
);
268 if (__nscd_drop_map_ref (mapped
, &gc_cycle
) != 0)
270 /* When we come here this means there has been a GC cycle while we
271 were looking for the data. This means the data might have been
272 inconsistent. Retry if possible. */
273 if ((gc_cycle
& 1) != 0 || ++nretries
== 5 || retval
== -1)
275 /* nscd is just running gc now. Disable using the mapping. */
276 if (atomic_decrement_val (&mapped
->counter
) == 0)
277 __nscd_unmap (mapped
);