1 /* Copyright (C) 2011-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
22 #include <not-cancel.h>
24 #include "nscd-client.h"
25 #include "nscd_proto.h"
27 int __nss_not_use_nscd_netgroup
;
30 libc_locked_map_ptr (static, map_handle
);
31 /* Note that we only free the structure if necessary. The memory
32 mapping is not removed since it is not visible to the malloc
34 libc_freeres_fn (pw_map_free
)
36 if (map_handle
.mapped
!= NO_MAPPING
)
38 void *p
= map_handle
.mapped
;
39 map_handle
.mapped
= NO_MAPPING
;
46 __nscd_setnetgrent (const char *group
, struct __netgrent
*datap
)
50 size_t group_len
= strlen (group
) + 1;
52 /* If the mapping is available, try to search there instead of
53 communicating with the nscd. */
54 struct mapped_database
*mapped
;
55 mapped
= __nscd_get_map_ref (GETFDNETGR
, "netgroup", &map_handle
, &gc_cycle
);
58 char *respdata
= NULL
;
60 netgroup_response_header netgroup_resp
;
62 if (mapped
!= NO_MAPPING
)
64 struct datahead
*found
= __nscd_cache_search (GETNETGRENT
, group
,
66 sizeof netgroup_resp
);
69 respdata
= (char *) (&found
->data
[0].netgroupdata
+ 1);
70 netgroup_resp
= found
->data
[0].netgroupdata
;
71 /* Now check if we can trust pw_resp fields. If GC is
72 in progress, it can contain anything. */
73 if (mapped
->head
->gc_cycle
!= gc_cycle
)
84 sock
= __nscd_open_socket (group
, group_len
, GETNETGRENT
,
85 &netgroup_resp
, sizeof (netgroup_resp
));
88 /* nscd not running or wrong version. */
89 __nss_not_use_nscd_netgroup
= 1;
94 if (netgroup_resp
.found
== 1)
96 size_t datalen
= netgroup_resp
.result_len
;
98 /* If we do not have to read the data here it comes from the
99 mapped data and does not have to be freed. */
100 if (respdata
== NULL
)
102 /* The data will come via the socket. */
103 respdata
= malloc (datalen
);
104 if (respdata
== NULL
)
107 if ((size_t) __readall (sock
, respdata
, datalen
) != datalen
)
114 datap
->data
= respdata
;
115 datap
->data_size
= datalen
;
116 datap
->cursor
= respdata
;
118 datap
->nip
= (nss_action_list
) -1l;
119 datap
->known_groups
= NULL
;
120 datap
->needed_groups
= NULL
;
126 if (__glibc_unlikely (netgroup_resp
.found
== -1))
128 /* The daemon does not cache this database. */
129 __nss_not_use_nscd_netgroup
= 1;
133 /* Set errno to 0 to indicate no error, just no found record. */
135 /* Even though we have not found anything, the result is zero. */
141 __close_nocancel_nostatus (sock
);
143 if (__nscd_drop_map_ref (mapped
, &gc_cycle
) != 0)
145 /* When we come here this means there has been a GC cycle while we
146 were looking for the data. This means the data might have been
147 inconsistent. Retry if possible. */
148 if ((gc_cycle
& 1) != 0 || ++nretries
== 5 || retval
== -1)
150 /* nscd is just running gc now. Disable using the mapping. */
151 if (atomic_decrement_val (&mapped
->counter
) == 0)
152 __nscd_unmap (mapped
);
165 __nscd_innetgr (const char *netgroup
, const char *host
, const char *user
,
168 size_t key_len
= (strlen (netgroup
) + strlen (host
?: "")
169 + strlen (user
?: "") + strlen (domain
?: "") + 7);
171 bool use_alloca
= __libc_use_alloca (key_len
);
173 key
= alloca (key_len
);
176 key
= malloc (key_len
);
180 char *wp
= stpcpy (key
, netgroup
) + 1;
184 wp
= stpcpy (wp
, host
) + 1;
191 wp
= stpcpy (wp
, user
) + 1;
198 wp
= stpcpy (wp
, domain
) + 1;
204 /* If the mapping is available, try to search there instead of
205 communicating with the nscd. */
208 struct mapped_database
*mapped
;
209 mapped
= __nscd_get_map_ref (GETFDNETGR
, "netgroup", &map_handle
, &gc_cycle
);
213 innetgroup_response_header innetgroup_resp
;
216 if (mapped
!= NO_MAPPING
)
218 struct datahead
*found
= __nscd_cache_search (INNETGR
, key
,
220 sizeof innetgroup_resp
);
223 innetgroup_resp
= found
->data
[0].innetgroupdata
;
224 /* Now check if we can trust pw_resp fields. If GC is
225 in progress, it can contain anything. */
226 if (mapped
->head
->gc_cycle
!= gc_cycle
)
236 sock
= __nscd_open_socket (key
, key_len
, INNETGR
,
237 &innetgroup_resp
, sizeof (innetgroup_resp
));
240 /* nscd not running or wrong version. */
241 __nss_not_use_nscd_netgroup
= 1;
246 if (innetgroup_resp
.found
== 1)
247 retval
= innetgroup_resp
.result
;
250 if (__glibc_unlikely (innetgroup_resp
.found
== -1))
252 /* The daemon does not cache this database. */
253 __nss_not_use_nscd_netgroup
= 1;
257 /* Set errno to 0 to indicate no error, just no found record. */
259 /* Even though we have not found anything, the result is zero. */
265 __close_nocancel_nostatus (sock
);
267 if (__nscd_drop_map_ref (mapped
, &gc_cycle
) != 0)
269 /* When we come here this means there has been a GC cycle while we
270 were looking for the data. This means the data might have been
271 inconsistent. Retry if possible. */
272 if ((gc_cycle
& 1) != 0 || ++nretries
== 5 || retval
== -1)
274 /* nscd is just running gc now. Disable using the mapping. */
275 if (atomic_decrement_val (&mapped
->counter
) == 0)
276 __nscd_unmap (mapped
);