Update.
[glibc.git] / nis / nss_nis / nis-pwd.c
blob0a337bb9e7651ae04f0da110f1044a6e6af84f8d
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 <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/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,
82 int *errnop)
84 struct parser_data *data = (void *) buffer;
85 char *domain;
86 int parse_res;
88 if (yp_get_default_domain (&domain))
89 return NSS_STATUS_UNAVAIL;
91 /* Get the next entry until we found a correct one. */
94 enum nss_status retval;
95 char *result, *outkey, *result2, *p;
96 int len, keylen, len2;
97 size_t namelen;
99 if (new_start)
100 retval = yperr2nss (yp_first (domain, "passwd.byname",
101 &outkey, &keylen, &result, &len));
102 else
103 retval = yperr2nss ( yp_next (domain, "passwd.byname",
104 oldkey, oldkeylen,
105 &outkey, &keylen, &result, &len));
107 if (retval != NSS_STATUS_SUCCESS)
109 if (retval == NSS_STATUS_NOTFOUND)
110 *errnop = ENOENT;
111 else if (retval == NSS_STATUS_TRYAGAIN)
112 *errnop = errno;
113 return retval;
116 /* Check for adjunct style secret passwords. They can be
117 recognized by a password starting with "##". */
118 p = strchr (result, ':');
119 if (p != NULL /* This better should be true in all cases. */
120 && p[1] == '#' && p[2] == '#'
121 && (namelen = p - result,
122 yp_match (domain, "passwd.adjunct.byname", result, namelen,
123 &result2, &len2)) == YPERR_SUCCESS)
125 /* We found a passwd.adjunct entry. Merge encrypted
126 password therein into original result. */
127 char *encrypted = strchr (result2, ':');
128 char *endp;
129 size_t restlen;
131 if (encrypted == NULL
132 || (endp = strchr (++encrypted, ':')) == NULL
133 || (p = strchr (p + 1, ':')) == NULL)
135 /* Invalid format of the entry. This never should happen
136 unless the data from which the NIS table is generated is
137 wrong. We simply ignore it. */
138 free (result2);
139 goto non_adjunct;
142 restlen = len - (p - result);
143 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
145 free (result2);
146 free (result);
147 *errnop = ERANGE;
148 return NSS_STATUS_TRYAGAIN;
151 __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
152 ":", 1),
153 encrypted, endp - encrypted),
154 p, restlen + 1);
155 p = buffer;
157 free (result2);
159 else
161 non_adjunct:
162 if ((size_t) (len + 1) > buflen)
164 free (result);
165 *errnop = ERANGE;
166 return NSS_STATUS_TRYAGAIN;
169 p = strncpy (buffer, result, len);
170 buffer[len] = '\0';
173 while (isspace (*p))
174 ++p;
175 free (result);
177 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
178 if (parse_res == -1)
180 free (outkey);
181 *errnop = ERANGE;
182 return NSS_STATUS_TRYAGAIN;
185 free (oldkey);
186 oldkey = outkey;
187 oldkeylen = keylen;
188 new_start = 0;
190 while (parse_res < 1);
192 return NSS_STATUS_SUCCESS;
195 enum nss_status
196 _nss_nis_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
197 int *errnop)
199 int status;
201 __libc_lock_lock (lock);
203 status = internal_nis_getpwent_r (result, buffer, buflen, errnop);
205 __libc_lock_unlock (lock);
207 return status;
210 enum nss_status
211 _nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
212 char *buffer, size_t buflen, int *errnop)
214 struct parser_data *data = (void *) buffer;
215 enum nss_status retval;
216 char *domain, *result, *result2, *p;
217 int len, len2, parse_res;
218 size_t namelen;
220 if (name == NULL)
222 *errnop = EINVAL;
223 return NSS_STATUS_UNAVAIL;
226 if (yp_get_default_domain (&domain))
227 return NSS_STATUS_UNAVAIL;
229 namelen = strlen (name);
231 retval = yperr2nss (yp_match (domain, "passwd.byname", name,
232 namelen, &result, &len));
234 if (retval != NSS_STATUS_SUCCESS)
236 if (retval == NSS_STATUS_NOTFOUND)
237 *errnop = ENOENT;
238 else if (retval == NSS_STATUS_TRYAGAIN)
239 *errnop = errno;
240 return retval;
243 /* Check for adjunct style secret passwords. They can be recognized
244 by a password starting with "##". */
245 p = strchr (result, ':');
246 if (p != NULL /* This better should be true in all cases. */
247 && p[1] == '#' && p[2] == '#'
248 && yp_match (domain, "passwd.adjunct.byname", name, namelen,
249 &result2, &len2) == YPERR_SUCCESS)
251 /* We found a passwd.adjunct entry. Merge encrypted password
252 therein into original result. */
253 char *encrypted = strchr (result2, ':');
254 char *endp;
255 size_t restlen;
257 if (encrypted == NULL
258 || (endp = strchr (++encrypted, ':')) == NULL
259 || (p = strchr (p + 1, ':')) == NULL)
261 /* Invalid format of the entry. This never should happen
262 unless the data from which the NIS table is generated is
263 wrong. We simply ignore it. */
264 free (result2);
265 goto non_adjunct;
268 restlen = len - (p - result);
269 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
271 free (result2);
272 free (result);
273 *errnop = ERANGE;
274 return NSS_STATUS_TRYAGAIN;
277 __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, name, namelen),
278 ":", 1),
279 encrypted, endp - encrypted),
280 p, restlen + 1);
281 p = buffer;
283 free (result2);
285 else
287 non_adjunct:
288 if ((size_t) (len + 1) > buflen)
290 free (result);
291 *errnop = ERANGE;
292 return NSS_STATUS_TRYAGAIN;
295 p = strncpy (buffer, result, len);
296 buffer[len] = '\0';
299 while (isspace (*p))
300 ++p;
301 free (result);
303 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
304 if (parse_res < 1)
306 if (parse_res == -1)
307 return NSS_STATUS_TRYAGAIN;
308 else
310 *errnop = ENOENT;
311 return NSS_STATUS_NOTFOUND;
314 else
315 return NSS_STATUS_SUCCESS;
318 enum nss_status
319 _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
320 char *buffer, size_t buflen, int *errnop)
322 struct parser_data *data = (void *) buffer;
323 enum nss_status retval;
324 char *domain, *result, *p, *result2;
325 int len, nlen, parse_res, len2;
326 char buf[32];
327 size_t namelen;
329 if (yp_get_default_domain (&domain))
330 return NSS_STATUS_UNAVAIL;
332 nlen = sprintf (buf, "%d", uid);
334 retval = yperr2nss (yp_match (domain, "passwd.byuid", buf,
335 nlen, &result, &len));
337 if (retval != NSS_STATUS_SUCCESS)
339 if (retval == NSS_STATUS_NOTFOUND)
340 *errnop = ENOENT;
341 else if (retval == NSS_STATUS_TRYAGAIN)
342 *errnop = errno;
343 return retval;
346 /* Check for adjunct style secret passwords. They can be recognized
347 by a password starting with "##". */
348 p = strchr (result, ':');
349 if (p != NULL /* This better should be true in all cases. */
350 && p[1] == '#' && p[2] == '#'
351 && (namelen = p - result,
352 yp_match (domain, "passwd.adjunct.byname", result, namelen,
353 &result2, &len2)) == YPERR_SUCCESS)
355 /* We found a passwd.adjunct entry. Merge encrypted password
356 therein into original result. */
357 char *encrypted = strchr (result2, ':');
358 char *endp;
359 size_t restlen;
361 if (encrypted == NULL
362 || (endp = strchr (++encrypted, ':')) == NULL
363 || (p = strchr (p + 1, ':')) == NULL)
365 /* Invalid format of the entry. This never should happen
366 unless the data from which the NIS table is generated is
367 wrong. We simply ignore it. */
368 free (result2);
369 goto non_adjunct;
372 restlen = len - (p - result);
373 if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
375 free (result2);
376 free (result);
377 *errnop = ERANGE;
378 return NSS_STATUS_TRYAGAIN;
381 __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
382 ":", 1),
383 encrypted, endp - encrypted),
384 p, restlen + 1);
385 p = buffer;
387 free (result2);
389 else
391 non_adjunct:
392 if ((size_t) (len + 1) > buflen)
394 free (result);
395 *errnop = ERANGE;
396 return NSS_STATUS_TRYAGAIN;
399 p = strncpy (buffer, result, len);
400 buffer[len] = '\0';
403 while (isspace (*p))
404 ++p;
405 free (result);
407 parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop);
408 if (parse_res < 1)
410 if (parse_res == -1)
411 return NSS_STATUS_TRYAGAIN;
412 else
414 *errnop = ENOENT;
415 return NSS_STATUS_NOTFOUND;
418 else
419 return NSS_STATUS_SUCCESS;