]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 1996-2015 Free Software Foundation, Inc. |
6259ec0d | 2 | This file is part of the GNU C Library. |
b85697f6 | 3 | Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. |
6259ec0d UD |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
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. | |
6259ec0d UD |
9 | |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
6259ec0d | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
6259ec0d | 18 | |
6259ec0d UD |
19 | #include <ctype.h> |
20 | #include <errno.h> | |
4eaa9bb4 UD |
21 | #include <grp.h> |
22 | #include <nss.h> | |
6259ec0d | 23 | #include <string.h> |
5107cf1d | 24 | #include <bits/libc-lock.h> |
6259ec0d UD |
25 | #include <rpcsvc/yp.h> |
26 | #include <rpcsvc/ypclnt.h> | |
27 | ||
28 | #include "nss-nis.h" | |
4eaa9bb4 | 29 | #include <libnsl.h> |
6259ec0d | 30 | |
7e3be507 UD |
31 | /* Get the declaration of the parser function. */ |
32 | #define ENTNAME grent | |
33 | #define STRUCTURE group | |
34 | #define EXTERN_PARSER | |
cf29ffbe | 35 | #include <nss/nss_files/files-parse.c> |
7e3be507 | 36 | |
6259ec0d UD |
37 | /* Protect global state against multiple changers */ |
38 | __libc_lock_define_initialized (static, lock) | |
39 | ||
40 | static bool_t new_start = 1; | |
fc9f33e3 UD |
41 | static char *oldkey; |
42 | static int oldkeylen; | |
4eaa9bb4 UD |
43 | static intern_t intern; |
44 | ||
45 | ||
4eaa9bb4 UD |
46 | static void |
47 | internal_nis_endgrent (void) | |
48 | { | |
6259ec0d UD |
49 | new_start = 1; |
50 | if (oldkey != NULL) | |
51 | { | |
52 | free (oldkey); | |
53 | oldkey = NULL; | |
54 | oldkeylen = 0; | |
55 | } | |
56 | ||
1a9e411e | 57 | struct response_t *curr = intern.start; |
4eaa9bb4 UD |
58 | |
59 | while (curr != NULL) | |
60 | { | |
61 | struct response_t *last = curr; | |
62 | curr = curr->next; | |
63 | free (last); | |
64 | } | |
65 | ||
66 | intern.next = intern.start = NULL; | |
67 | } | |
68 | ||
69 | ||
70 | enum nss_status | |
71 | _nss_nis_endgrent (void) | |
72 | { | |
73 | __libc_lock_lock (lock); | |
74 | ||
75 | internal_nis_endgrent (); | |
76 | ||
6259ec0d UD |
77 | __libc_lock_unlock (lock); |
78 | ||
79 | return NSS_STATUS_SUCCESS; | |
80 | } | |
4eaa9bb4 UD |
81 | |
82 | ||
83 | enum nss_status | |
84 | internal_nis_setgrent (void) | |
85 | { | |
86 | /* We have to read all the data now. */ | |
87 | char *domain; | |
a1ffb40e | 88 | if (__glibc_unlikely (yp_get_default_domain (&domain))) |
4eaa9bb4 UD |
89 | return NSS_STATUS_UNAVAIL; |
90 | ||
91 | struct ypall_callback ypcb; | |
92 | ||
e0d4e91d UD |
93 | ypcb.foreach = _nis_saveit; |
94 | ypcb.data = (char *) &intern; | |
4eaa9bb4 UD |
95 | enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb)); |
96 | ||
97 | ||
98 | /* Mark the last buffer as full. */ | |
99 | if (intern.next != NULL) | |
100 | intern.next->size = intern.offset; | |
101 | ||
102 | intern.next = intern.start; | |
103 | intern.offset = 0; | |
104 | ||
105 | return status; | |
106 | } | |
107 | ||
108 | ||
109 | enum nss_status | |
110 | _nss_nis_setgrent (int stayopen) | |
111 | { | |
112 | enum nss_status result = NSS_STATUS_SUCCESS; | |
113 | ||
114 | __libc_lock_lock (lock); | |
115 | ||
116 | internal_nis_endgrent (); | |
117 | ||
118 | if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) | |
119 | result = internal_nis_setgrent (); | |
120 | ||
121 | __libc_lock_unlock (lock); | |
122 | ||
123 | return result; | |
124 | } | |
125 | ||
6259ec0d UD |
126 | |
127 | static enum nss_status | |
d71b808a UD |
128 | internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen, |
129 | int *errnop) | |
6259ec0d | 130 | { |
4eaa9bb4 UD |
131 | /* If we read the entire database at setpwent time we just iterate |
132 | over the data we have in memory. */ | |
133 | bool batch_read = intern.start != NULL; | |
134 | ||
135 | char *domain = NULL; | |
136 | if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0)) | |
6259ec0d UD |
137 | return NSS_STATUS_UNAVAIL; |
138 | ||
139 | /* Get the next entry until we found a correct one. */ | |
ab9a9ff8 | 140 | int parse_res; |
6259ec0d UD |
141 | do |
142 | { | |
ab9a9ff8 UD |
143 | char *result; |
144 | char *outkey; | |
145 | int len; | |
146 | int keylen; | |
0ecb606c | 147 | |
4eaa9bb4 UD |
148 | if (batch_read) |
149 | { | |
150 | struct response_t *bucket; | |
151 | ||
152 | handle_batch_read: | |
153 | bucket = intern.next; | |
154 | ||
a1ffb40e | 155 | if (__glibc_unlikely (intern.offset >= bucket->size)) |
4eaa9bb4 UD |
156 | { |
157 | if (bucket->next == NULL) | |
158 | return NSS_STATUS_NOTFOUND; | |
159 | ||
160 | /* We look at all the content in the current bucket. Go on | |
161 | to the next. */ | |
162 | bucket = intern.next = bucket->next; | |
163 | intern.offset = 0; | |
164 | } | |
165 | ||
166 | for (result = &bucket->mem[intern.offset]; isspace (*result); | |
167 | ++result) | |
168 | ++intern.offset; | |
169 | ||
170 | len = strlen (result); | |
171 | } | |
0ecb606c | 172 | else |
4eaa9bb4 UD |
173 | { |
174 | int yperr; | |
0ecb606c | 175 | |
4eaa9bb4 UD |
176 | if (new_start) |
177 | { | |
178 | /* Maybe we should read the database in one piece. */ | |
179 | if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) | |
180 | && internal_nis_setgrent () == NSS_STATUS_SUCCESS | |
181 | && intern.start != NULL) | |
182 | { | |
183 | batch_read = true; | |
184 | goto handle_batch_read; | |
185 | } | |
ab9a9ff8 | 186 | |
4eaa9bb4 UD |
187 | yperr = yp_first (domain, "group.byname", &outkey, &keylen, |
188 | &result, &len); | |
189 | } | |
190 | else | |
191 | yperr = yp_next (domain, "group.byname", oldkey, oldkeylen, | |
192 | &outkey, &keylen, &result, &len); | |
193 | ||
a1ffb40e | 194 | if (__glibc_unlikely (yperr != YPERR_SUCCESS)) |
4eaa9bb4 UD |
195 | { |
196 | enum nss_status retval = yperr2nss (yperr); | |
197 | ||
198 | if (retval == NSS_STATUS_TRYAGAIN) | |
199 | *errnop = errno; | |
200 | return retval; | |
201 | } | |
202 | } | |
a334319f | 203 | |
a1ffb40e | 204 | if (__glibc_unlikely ((size_t) (len + 1) > buflen)) |
1a9e411e | 205 | { |
c240c3a5 JL |
206 | if (!batch_read) |
207 | free (result); | |
1a9e411e JL |
208 | *errnop = ERANGE; |
209 | return NSS_STATUS_TRYAGAIN; | |
210 | } | |
6259ec0d | 211 | |
ab9a9ff8 | 212 | char *p = strncpy (buffer, result, len); |
6259ec0d UD |
213 | buffer[len] = '\0'; |
214 | while (isspace (*p)) | |
1a9e411e | 215 | ++p; |
4eaa9bb4 UD |
216 | if (!batch_read) |
217 | free (result); | |
6259ec0d | 218 | |
ab9a9ff8 UD |
219 | parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, |
220 | errnop); | |
a1ffb40e | 221 | if (__glibc_unlikely (parse_res == -1)) |
60c96635 | 222 | { |
d4b661e5 UD |
223 | if (!batch_read) |
224 | free (outkey); | |
d71b808a | 225 | *errnop = ERANGE; |
60c96635 UD |
226 | return NSS_STATUS_TRYAGAIN; |
227 | } | |
6259ec0d | 228 | |
4eaa9bb4 UD |
229 | if (batch_read) |
230 | intern.offset += len + 1; | |
231 | else | |
232 | { | |
233 | free (oldkey); | |
234 | oldkey = outkey; | |
235 | oldkeylen = keylen; | |
236 | new_start = 0; | |
237 | } | |
6259ec0d | 238 | } |
26dee9c4 | 239 | while (parse_res < 1); |
6259ec0d UD |
240 | |
241 | return NSS_STATUS_SUCCESS; | |
242 | } | |
243 | ||
244 | enum nss_status | |
d71b808a UD |
245 | _nss_nis_getgrent_r (struct group *result, char *buffer, size_t buflen, |
246 | int *errnop) | |
6259ec0d UD |
247 | { |
248 | int status; | |
249 | ||
250 | __libc_lock_lock (lock); | |
251 | ||
d71b808a | 252 | status = internal_nis_getgrent_r (result, buffer, buflen, errnop); |
6259ec0d UD |
253 | |
254 | __libc_lock_unlock (lock); | |
255 | ||
256 | return status; | |
257 | } | |
258 | ||
259 | enum nss_status | |
260 | _nss_nis_getgrnam_r (const char *name, struct group *grp, | |
d71b808a | 261 | char *buffer, size_t buflen, int *errnop) |
6259ec0d | 262 | { |
6259ec0d UD |
263 | if (name == NULL) |
264 | { | |
ac9f45cf | 265 | *errnop = EINVAL; |
6259ec0d UD |
266 | return NSS_STATUS_UNAVAIL; |
267 | } | |
268 | ||
ab9a9ff8 | 269 | char *domain; |
a1ffb40e | 270 | if (__glibc_unlikely (yp_get_default_domain (&domain))) |
6259ec0d UD |
271 | return NSS_STATUS_UNAVAIL; |
272 | ||
ab9a9ff8 UD |
273 | char *result; |
274 | int len; | |
275 | int yperr = yp_match (domain, "group.byname", name, strlen (name), &result, | |
276 | &len); | |
6259ec0d | 277 | |
a1ffb40e | 278 | if (__glibc_unlikely (yperr != YPERR_SUCCESS)) |
6259ec0d | 279 | { |
ab9a9ff8 UD |
280 | enum nss_status retval = yperr2nss (yperr); |
281 | ||
0b3b45f9 | 282 | if (retval == NSS_STATUS_TRYAGAIN) |
1a9e411e | 283 | *errnop = errno; |
6259ec0d UD |
284 | return retval; |
285 | } | |
286 | ||
a1ffb40e | 287 | if (__glibc_unlikely ((size_t) (len + 1) > buflen)) |
6259ec0d UD |
288 | { |
289 | free (result); | |
d71b808a | 290 | *errnop = ERANGE; |
6259ec0d UD |
291 | return NSS_STATUS_TRYAGAIN; |
292 | } | |
293 | ||
ab9a9ff8 | 294 | char *p = strncpy (buffer, result, len); |
6259ec0d UD |
295 | buffer[len] = '\0'; |
296 | while (isspace (*p)) | |
297 | ++p; | |
298 | free (result); | |
299 | ||
ab9a9ff8 UD |
300 | int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, |
301 | errnop); | |
302 | if (__builtin_expect (parse_res < 1, 0)) | |
ac9f45cf UD |
303 | { |
304 | if (parse_res == -1) | |
305 | return NSS_STATUS_TRYAGAIN; | |
306 | else | |
34816665 | 307 | return NSS_STATUS_NOTFOUND; |
ac9f45cf UD |
308 | } |
309 | return NSS_STATUS_SUCCESS; | |
6259ec0d UD |
310 | } |
311 | ||
312 | enum nss_status | |
313 | _nss_nis_getgrgid_r (gid_t gid, struct group *grp, | |
d71b808a | 314 | char *buffer, size_t buflen, int *errnop) |
6259ec0d | 315 | { |
ab9a9ff8 | 316 | char *domain; |
a1ffb40e | 317 | if (__glibc_unlikely (yp_get_default_domain (&domain))) |
6259ec0d UD |
318 | return NSS_STATUS_UNAVAIL; |
319 | ||
ab9a9ff8 UD |
320 | char buf[32]; |
321 | int nlen = sprintf (buf, "%lu", (unsigned long int) gid); | |
6259ec0d | 322 | |
ab9a9ff8 UD |
323 | char *result; |
324 | int len; | |
325 | int yperr = yp_match (domain, "group.bygid", buf, nlen, &result, &len); | |
6259ec0d | 326 | |
a1ffb40e | 327 | if (__glibc_unlikely (yperr != YPERR_SUCCESS)) |
6259ec0d | 328 | { |
ab9a9ff8 UD |
329 | enum nss_status retval = yperr2nss (yperr); |
330 | ||
34816665 | 331 | if (retval == NSS_STATUS_TRYAGAIN) |
1a9e411e | 332 | *errnop = errno; |
6259ec0d UD |
333 | return retval; |
334 | } | |
335 | ||
a1ffb40e | 336 | if (__glibc_unlikely ((size_t) (len + 1) > buflen)) |
6259ec0d UD |
337 | { |
338 | free (result); | |
d71b808a | 339 | *errnop = ERANGE; |
6259ec0d UD |
340 | return NSS_STATUS_TRYAGAIN; |
341 | } | |
342 | ||
ab9a9ff8 | 343 | char *p = strncpy (buffer, result, len); |
6259ec0d UD |
344 | buffer[len] = '\0'; |
345 | while (isspace (*p)) | |
346 | ++p; | |
347 | free (result); | |
348 | ||
ab9a9ff8 UD |
349 | int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, |
350 | errnop); | |
a1ffb40e | 351 | if (__glibc_unlikely (parse_res < 1)) |
ac9f45cf UD |
352 | { |
353 | if (parse_res == -1) | |
354 | return NSS_STATUS_TRYAGAIN; | |
355 | else | |
34816665 | 356 | return NSS_STATUS_NOTFOUND; |
ac9f45cf UD |
357 | } |
358 | return NSS_STATUS_SUCCESS; | |
6259ec0d | 359 | } |