Updated to fedora-glibc-20050627T0850
[glibc.git] / glibc-compat / nss_nis / nis-pwd.c
blobe18c80d8acacd2b954c1ff57fa7a01a64c9ddd3e
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <nss.h>
21 #include <glibc-compat/include/pwd.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
29 #include "nss-nis.h"
31 /* Get the declaration of the parser function. */
32 #define ENTNAME pwent
33 #define STRUCTURE passwd
34 #define EXTERN_PARSER
35 #include "../nss_files/files-parse.c"
37 /* Protect global state against multiple changers */
38 __libc_lock_define_initialized (static, lock)
40 static bool_t new_start = 1;
41 static char *oldkey = NULL;
42 static int oldkeylen = 0;
44 enum nss_status
45 _nss_nis_setpwent (void)
47 __libc_lock_lock (lock);
49 new_start = 1;
50 if (oldkey != NULL)
52 free (oldkey);
53 oldkey = NULL;
54 oldkeylen = 0;
57 __libc_lock_unlock (lock);
59 return NSS_STATUS_SUCCESS;
62 enum nss_status
63 _nss_nis_endpwent (void)
65 __libc_lock_lock (lock);
67 new_start = 1;
68 if (oldkey != NULL)
70 free (oldkey);
71 oldkey = NULL;
72 oldkeylen = 0;
75 __libc_lock_unlock (lock);
77 return NSS_STATUS_SUCCESS;
80 static enum nss_status
81 internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen)
83 struct parser_data *data = (void *) buffer;
84 char *domain;
85 int parse_res;
87 if (yp_get_default_domain (&domain))
88 return NSS_STATUS_UNAVAIL;
90 /* Get the next entry until we found a correct one. */
93 enum nss_status retval;
94 char *result, *outkey, *result2, *p;
95 int len, keylen, len2;
96 size_t namelen;
98 if (new_start)
99 retval = yperr2nss (yp_first (domain, "passwd.byname",
100 &outkey, &keylen, &result, &len));
101 else
102 retval = yperr2nss ( yp_next (domain, "passwd.byname",
103 oldkey, oldkeylen,
104 &outkey, &keylen, &result, &len));
106 if (retval != NSS_STATUS_SUCCESS)
108 if (retval == NSS_STATUS_TRYAGAIN)
109 __set_errno (EAGAIN);
110 return retval;
113 /* Check for adjunct style secret passwords. They can be
114 recognized by a password starting with "##". */
115 p = strchr (result, ':');
116 if (p != NULL /* This better should be true in all cases. */
117 && p[1] == '#' && p[2] == '#'
118 && (namelen = p - result,
119 yp_match (domain, "passwd.adjunct.byname", result, namelen,
120 &result2, &len2)) == YPERR_SUCCESS)
122 /* We found a passwd.adjunct entry. Merge encrypted
123 password therein into original result. */
124 char *encrypted = strchr (result2, ':');
125 char *endp, *tmp;
126 size_t restlen;
128 if (encrypted == NULL
129 || (endp = strchr (++encrypted, ':')) == NULL
130 || (p = strchr (p + 1, ':')) == NULL)
132 /* Invalid format of the entry. This never should happen
133 unless the data from which the NIS table is generated is
134 wrong. We simply ignore it. */
135 free (result2);
136 goto non_adjunct;
139 restlen = len - (p - result);
140 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
142 free (result2);
143 free (result);
144 __set_errno (ERANGE);
145 return NSS_STATUS_TRYAGAIN;
148 memcpy (buffer, result, namelen);
149 tmp = buffer + namelen;
150 *tmp++ = ':';
151 memcpy (tmp, encrypted, endp - encrypted);
152 tmp += endp - encrypted;
153 memcpy (tmp, p, restlen + 1);
154 p = buffer;
156 free (result2);
158 else
160 non_adjunct:
161 if ((size_t) (len + 1) > buflen)
163 free (result);
164 __set_errno (ERANGE);
165 return NSS_STATUS_TRYAGAIN;
168 p = strncpy (buffer, result, len);
169 buffer[len] = '\0';
172 p = strncpy (buffer, result, len);
173 buffer[len] = '\0';
174 while (isspace (*p))
175 ++p;
176 free (result);
178 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen);
179 if (parse_res == -1 && errno == ERANGE)
180 return NSS_STATUS_TRYAGAIN;
182 free (oldkey);
183 oldkey = outkey;
184 oldkeylen = keylen;
185 new_start = 0;
187 while (!parse_res);
189 return NSS_STATUS_SUCCESS;
192 enum nss_status
193 _nss_nis_getpwent_r (struct passwd *result, char *buffer, size_t buflen)
195 int status;
197 __libc_lock_lock (lock);
199 status = internal_nis_getpwent_r (result, buffer, buflen);
201 __libc_lock_unlock (lock);
203 return status;
206 enum nss_status
207 _nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
208 char *buffer, size_t buflen)
210 struct parser_data *data = (void *) buffer;
211 enum nss_status retval;
212 char *domain, *result, *result2, *p;
213 int len, len2, parse_res;
214 size_t namelen;
216 if (name == NULL)
218 __set_errno (EINVAL);
219 return NSS_STATUS_UNAVAIL;
222 if (yp_get_default_domain (&domain))
223 return NSS_STATUS_UNAVAIL;
225 namelen = strlen (name);
227 retval = yperr2nss (yp_match (domain, "passwd.byname", name,
228 namelen, &result, &len));
230 if (retval != NSS_STATUS_SUCCESS)
232 if (retval == NSS_STATUS_TRYAGAIN)
233 __set_errno (EAGAIN);
234 return retval;
237 /* Check for adjunct style secret passwords. They can be recognized
238 by a password starting with "##". */
239 p = strchr (result, ':');
240 if (p != NULL /* This better should be true in all cases. */
241 && p[1] == '#' && p[2] == '#'
242 && (namelen = p - result,
243 yp_match (domain, "passwd.adjunct.byname", name, namelen,
244 &result2, &len2)) == YPERR_SUCCESS)
246 /* We found a passwd.adjunct entry. Merge encrypted password
247 therein into original result. */
248 char *encrypted = strchr (result2, ':');
249 char *endp, *tmp;
250 size_t restlen;
252 if (encrypted == NULL
253 || (endp = strchr (++encrypted, ':')) == NULL
254 || (p = strchr (p + 1, ':')) == NULL)
256 /* Invalid format of the entry. This never should happen
257 unless the data from which the NIS table is generated is
258 wrong. We simply ignore it. */
259 free (result2);
260 goto non_adjunct;
263 restlen = len - (p - result);
264 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
266 free (result2);
267 free (result);
268 __set_errno (ERANGE);
269 return NSS_STATUS_TRYAGAIN;
272 memcpy (buffer, name, namelen);
273 tmp = buffer + namelen;
274 *tmp++ = ':';
275 memcpy (tmp, encrypted, endp - encrypted);
276 tmp += endp - encrypted;
277 memcpy (tmp, p, restlen + 1);
278 p = buffer;
280 free (result2);
282 else
284 non_adjunct:
285 if ((size_t) (len + 1) > buflen)
287 free (result);
288 __set_errno (ERANGE);
289 return NSS_STATUS_TRYAGAIN;
292 p = strncpy (buffer, result, len);
293 buffer[len] = '\0';
296 while (isspace (*p))
297 ++p;
298 free (result);
300 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen);
302 if (parse_res == -1 && errno == ERANGE)
303 return NSS_STATUS_TRYAGAIN;
304 else if (parse_res == 0)
305 return NSS_STATUS_NOTFOUND;
307 return NSS_STATUS_SUCCESS;
310 enum nss_status
311 _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
312 char *buffer, size_t buflen)
314 struct parser_data *data = (void *) buffer;
315 enum nss_status retval;
316 char *domain, *result, *p, *result2;
317 int len, nlen, parse_res, len2;
318 char buf[32];
319 size_t namelen;
321 if (yp_get_default_domain (&domain))
322 return NSS_STATUS_UNAVAIL;
324 nlen = sprintf (buf, "%d", uid);
326 retval = yperr2nss (yp_match (domain, "passwd.byuid", buf,
327 nlen, &result, &len));
329 if (retval != NSS_STATUS_SUCCESS)
331 if (retval == NSS_STATUS_TRYAGAIN)
332 __set_errno (EAGAIN);
333 return retval;
336 /* Check for adjunct style secret passwords. They can be recognized
337 by a password starting with "##". */
338 p = strchr (result, ':');
339 if (p != NULL /* This better should be true in all cases. */
340 && p[1] == '#' && p[2] == '#'
341 && (namelen = p - result,
342 yp_match (domain, "passwd.adjunct.byname", result, namelen,
343 &result2, &len2)) == YPERR_SUCCESS)
345 /* We found a passwd.adjunct entry. Merge encrypted password
346 therein into original result. */
347 char *encrypted = strchr (result2, ':');
348 char *endp, *tmp;
349 size_t restlen;
351 if (encrypted == NULL
352 || (endp = strchr (++encrypted, ':')) == NULL
353 || (p = strchr (p + 1, ':')) == NULL)
355 /* Invalid format of the entry. This never should happen
356 unless the data from which the NIS table is generated is
357 wrong. We simply ignore it. */
358 free (result2);
359 goto non_adjunct;
362 restlen = len - (p - result);
363 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
365 free (result2);
366 free (result);
367 __set_errno (ERANGE);
368 return NSS_STATUS_TRYAGAIN;
371 memcpy (buffer, result, namelen);
372 tmp = buffer + namelen;
373 *tmp++ = ':';
374 memcpy (tmp, encrypted, endp - encrypted);
375 tmp += endp - encrypted;
376 memcpy (tmp, p, restlen + 1);
377 p = buffer;
379 free (result2);
381 else
383 non_adjunct:
384 if ((size_t) (len + 1) > buflen)
386 free (result);
387 __set_errno (ERANGE);
388 return NSS_STATUS_TRYAGAIN;
391 p = strncpy (buffer, result, len);
392 buffer[len] = '\0';
395 while (isspace (*p))
396 ++p;
397 free (result);
399 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen);
401 if (parse_res == -1 && errno == ERANGE)
402 return NSS_STATUS_TRYAGAIN;
403 else if (parse_res == 0)
404 return NSS_STATUS_NOTFOUND;
406 return NSS_STATUS_SUCCESS;