elf: Add #include <sys/param.h> for MAX usage.
[glibc.git] / nscd / nscd_netgroup.c
blob7e51dd3d941e383ab97bc0f70dd4dda65c340e0b
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/>. */
18 #include <alloca.h>
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <string.h>
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
33 handling. */
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;
40 free (p);
45 int
46 __nscd_setnetgrent (const char *group, struct __netgrent *datap)
48 int gc_cycle;
49 int nretries = 0;
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);
57 retry:;
58 char *respdata = NULL;
59 int retval = -1;
60 netgroup_response_header netgroup_resp;
62 if (mapped != NO_MAPPING)
64 struct datahead *found = __nscd_cache_search (GETNETGRENT, group,
65 group_len, mapped,
66 sizeof netgroup_resp);
67 if (found != NULL)
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)
75 retval = -2;
76 goto out;
81 int sock = -1;
82 if (respdata == NULL)
84 sock = __nscd_open_socket (group, group_len, GETNETGRENT,
85 &netgroup_resp, sizeof (netgroup_resp));
86 if (sock == -1)
88 /* nscd not running or wrong version. */
89 __nss_not_use_nscd_netgroup = 1;
90 goto out;
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)
105 goto out_close;
107 if ((size_t) __readall (sock, respdata, datalen) != datalen)
109 free (respdata);
110 goto out_close;
114 datap->data = respdata;
115 datap->data_size = datalen;
116 datap->cursor = respdata;
117 datap->first = 1;
118 datap->nip = (nss_action_list) -1l;
119 datap->known_groups = NULL;
120 datap->needed_groups = NULL;
122 retval = 1;
124 else
126 if (__glibc_unlikely (netgroup_resp.found == -1))
128 /* The daemon does not cache this database. */
129 __nss_not_use_nscd_netgroup = 1;
130 goto out_close;
133 /* Set errno to 0 to indicate no error, just no found record. */
134 __set_errno (0);
135 /* Even though we have not found anything, the result is zero. */
136 retval = 0;
139 out_close:
140 if (sock != -1)
141 __close_nocancel_nostatus (sock);
142 out:
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);
153 mapped = NO_MAPPING;
156 if (retval != -1)
157 goto retry;
160 return retval;
165 __nscd_innetgr (const char *netgroup, const char *host, const char *user,
166 const char *domain)
168 size_t key_len = (strlen (netgroup) + strlen (host ?: "")
169 + strlen (user ?: "") + strlen (domain ?: "") + 7);
170 char *key;
171 bool use_alloca = __libc_use_alloca (key_len);
172 if (use_alloca)
173 key = alloca (key_len);
174 else
176 key = malloc (key_len);
177 if (key == NULL)
178 return -1;
180 char *wp = stpcpy (key, netgroup) + 1;
181 if (host != NULL)
183 *wp++ = '\1';
184 wp = stpcpy (wp, host) + 1;
186 else
187 *wp++ = '\0';
188 if (user != NULL)
190 *wp++ = '\1';
191 wp = stpcpy (wp, user) + 1;
193 else
194 *wp++ = '\0';
195 if (domain != NULL)
197 *wp++ = '\1';
198 wp = stpcpy (wp, domain) + 1;
200 else
201 *wp++ = '\0';
202 key_len = wp - key;
204 /* If the mapping is available, try to search there instead of
205 communicating with the nscd. */
206 int gc_cycle;
207 int nretries = 0;
208 struct mapped_database *mapped;
209 mapped = __nscd_get_map_ref (GETFDNETGR, "netgroup", &map_handle, &gc_cycle);
211 retry:;
212 int retval = -1;
213 innetgroup_response_header innetgroup_resp;
214 int sock = -1;
216 if (mapped != NO_MAPPING)
218 struct datahead *found = __nscd_cache_search (INNETGR, key,
219 key_len, mapped,
220 sizeof innetgroup_resp);
221 if (found != NULL)
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)
228 retval = -2;
229 goto out;
232 goto found_entry;
236 sock = __nscd_open_socket (key, key_len, INNETGR,
237 &innetgroup_resp, sizeof (innetgroup_resp));
238 if (sock == -1)
240 /* nscd not running or wrong version. */
241 __nss_not_use_nscd_netgroup = 1;
242 goto out;
245 found_entry:
246 if (innetgroup_resp.found == 1)
247 retval = innetgroup_resp.result;
248 else
250 if (__glibc_unlikely (innetgroup_resp.found == -1))
252 /* The daemon does not cache this database. */
253 __nss_not_use_nscd_netgroup = 1;
254 goto out_close;
257 /* Set errno to 0 to indicate no error, just no found record. */
258 __set_errno (0);
259 /* Even though we have not found anything, the result is zero. */
260 retval = 0;
263 out_close:
264 if (sock != -1)
265 __close_nocancel_nostatus (sock);
266 out:
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);
277 mapped = NO_MAPPING;
280 if (retval != -1)
281 goto retry;
284 if (! use_alloca)
285 free (key);
287 return retval;