1 /*
2 passwd.c - password entry lookup routines
3 Parts of this file were part of the nss_ldap library (as ldap-pwd.c)
4 which has been forked into the nss-pam-ldapd library.
5
6 Copyright (C) 1997-2005 Luke Howard
7 Copyright (C) 2006 West Consulting
8 Copyright (C) 2006-2017 Arthur de Jong
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301 USA
24 */
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <pthread.h>
34
35 #include "common.h"
36 #include "log.h"
37 #include "myldap.h"
38 #include "cfg.h"
39 #include "attmap.h"
40 #include "common/dict.h"
41 #include "compat/strndup.h"
42
43 /* ( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY
44 * DESC 'Abstraction of an account with POSIX attributes'
45 * MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
46 * MAY ( userPassword $ loginShell $ gecos $ description ) )
47 */
48
49 /* the search base for searches */
50 const char *passwd_bases[NSS_LDAP_CONFIG_MAX_BASES] = { NULL };
51
52 /* the search scope for searches */
53 int passwd_scope = LDAP_SCOPE_DEFAULT;
54
55 /* the basic search filter for searches */
56 const char *passwd_filter = "(objectClass=posixAccount)";
57
58 /* the attributes used in searches */
59 const char *attmap_passwd_uid = "uid";
60 const char *attmap_passwd_userPassword = "\"*\"";
61 const char *attmap_passwd_uidNumber = "uidNumber";
62 const char *attmap_passwd_gidNumber = "gidNumber";
63 const char *attmap_passwd_gecos = "\"${gecos:-$cn}\"";
64 const char *attmap_passwd_homeDirectory = "homeDirectory";
65 const char *attmap_passwd_loginShell = "loginShell";
66
67 /* special properties for objectSid-based searches
68 (these are already LDAP-escaped strings) */
69 static char *uidSid = NULL;
70 static char *gidSid = NULL;
71
72 /* default values for attributes */
73 static const char *default_passwd_userPassword = "*"; /* unmatchable */
74
75 /* Note that the resulting password value should be one of:
76 <empty> - no password set, allow login without password
77 * - often used to prevent logins
78 x - "valid" encrypted password that does not match any valid password
79 often used to indicate that the password is defined elsewhere
80 other - encrypted password, usually in crypt(3) format */
81
82 /* the attribute list to request with searches */
83 static const char **passwd_attrs = NULL;
84
85 /* create a search filter for searching a passwd entry
86 by name, return -1 on errors */
mkfilter_passwd_byname(const char * name,char * buffer,size_t buflen)87 static int mkfilter_passwd_byname(const char *name,
88 char *buffer, size_t buflen)
89 {
90 char safename[BUFLEN_SAFENAME];
91 /* escape attribute */
92 if (myldap_escape(name, safename, sizeof(safename)))
93 {
94 log_log(LOG_ERR, "mkfilter_passwd_byname(): safename buffer too small");
95 return -1;
96 }
97 /* build filter */
98 return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
99 passwd_filter, attmap_passwd_uid, safename);
100 }
101
102 /* create a search filter for searching a passwd entry
103 by uid, return -1 on errors */
mkfilter_passwd_byuid(uid_t uid,char * buffer,size_t buflen)104 static int mkfilter_passwd_byuid(uid_t uid, char *buffer, size_t buflen)
105 {
106 uid -= nslcd_cfg->nss_uid_offset;
107 if (uidSid != NULL)
108 {
109 return mysnprintf(buffer, buflen, "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))",
110 passwd_filter, attmap_passwd_uidNumber, uidSid,
111 (int)(uid & 0xff), (int)((uid >> 8) & 0xff),
112 (int)((uid >> 16) & 0xff), (int)((uid >> 24) & 0xff));
113 }
114 else
115 {
116 return mysnprintf(buffer, buflen, "(&%s(%s=%lu))",
117 passwd_filter, attmap_passwd_uidNumber, (unsigned long int)uid);
118 }
119 }
120
passwd_init(void)121 void passwd_init(void)
122 {
123 int i;
124 SET *set;
125 /* set up search bases */
126 if (passwd_bases[0] == NULL)
127 for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
128 passwd_bases[i] = nslcd_cfg->bases[i];
129 /* set up scope */
130 if (passwd_scope == LDAP_SCOPE_DEFAULT)
131 passwd_scope = nslcd_cfg->scope;
132 /* special case when uidNumber or gidNumber reference objectSid */
133 if (strncasecmp(attmap_passwd_uidNumber, "objectSid:", 10) == 0)
134 {
135 uidSid = sid2search(attmap_passwd_uidNumber + 10);
136 attmap_passwd_uidNumber = strndup(attmap_passwd_uidNumber, 9);
137 }
138 if (strncasecmp(attmap_passwd_gidNumber, "objectSid:", 10) == 0)
139 {
140 gidSid = sid2search(attmap_passwd_gidNumber + 10);
141 attmap_passwd_gidNumber = strndup(attmap_passwd_gidNumber, 9);
142 }
143 /* set up attribute list */
144 set = set_new();
145 attmap_add_attributes(set, "objectClass"); /* for testing shadowAccount */
146 attmap_add_attributes(set, attmap_passwd_uid);
147 attmap_add_attributes(set, attmap_passwd_userPassword);
148 attmap_add_attributes(set, attmap_passwd_uidNumber);
149 attmap_add_attributes(set, attmap_passwd_gidNumber);
150 attmap_add_attributes(set, attmap_passwd_gecos);
151 attmap_add_attributes(set, attmap_passwd_homeDirectory);
152 attmap_add_attributes(set, attmap_passwd_loginShell);
153 passwd_attrs = set_tolist(set);
154 if (passwd_attrs == NULL)
155 {
156 log_log(LOG_CRIT, "malloc() failed to allocate memory");
157 exit(EXIT_FAILURE);
158 }
159 set_free(set);
160 }
161
162 /* the cache that is used in dn2uid() */
163 static pthread_mutex_t dn2uid_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
164 static DICT *dn2uid_cache = NULL;
165 struct dn2uid_cache_entry {
166 time_t timestamp;
167 char *uid;
168 };
169
170 /* checks whether the entry has a valid uidNumber attribute
171 (>= nss_min_uid) */
entry_has_valid_uid(MYLDAP_ENTRY * entry)172 static int entry_has_valid_uid(MYLDAP_ENTRY *entry)
173 {
174 int i;
175 const char **values;
176 char *tmp;
177 uid_t uid;
178 /* if min_uid is not set any entry should do */
179 if (nslcd_cfg->nss_min_uid == 0)
180 return 1;
181 /* get all uidNumber attributes */
182 values = myldap_get_values_len(entry, attmap_passwd_uidNumber);
183 if ((values == NULL) || (values[0] == NULL))
184 {
185 log_log(LOG_WARNING, "%s: %s: missing",
186 myldap_get_dn(entry), attmap_passwd_uidNumber);
187 return 0;
188 }
189 /* check if there is a uidNumber attributes >= min_uid */
190 for (i = 0; values[i] != NULL; i++)
191 {
192 if (uidSid != NULL)
193 uid = (uid_t)binsid2id(values[i]);
194 else
195 {
196 errno = 0;
197 uid = strtouid(values[i], &tmp, 10);
198 if ((*(values[i]) == '\0') || (*tmp != '\0'))
199 {
200 log_log(LOG_WARNING, "%s: %s: non-numeric",
201 myldap_get_dn(entry), attmap_passwd_uidNumber);
202 continue;
203 }
204 else if ((errno != 0) || (strchr(values[i], '-') != NULL))
205 {
206 log_log(LOG_WARNING, "%s: %s: out of range",
207 myldap_get_dn(entry), attmap_passwd_uidNumber);
208 continue;
209 }
210 }
211 if (uid < nslcd_cfg->nss_min_uid)
212 {
213 log_log(LOG_DEBUG, "%s: %s: less than nss_min_uid",
214 myldap_get_dn(entry), attmap_passwd_uidNumber);
215 }
216 else
217 return 1;
218 }
219 /* nothing found */
220 return 0;
221 }
222
223 /* Perform an LDAP lookup to translate the DN into a uid.
224 This function either returns NULL or a strdup()ed string. */
lookup_dn2uid(MYLDAP_SESSION * session,const char * dn,int * rcp,char * buf,size_t buflen)225 char *lookup_dn2uid(MYLDAP_SESSION *session, const char *dn, int *rcp,
226 char *buf, size_t buflen)
227 {
228 MYLDAP_SEARCH *search;
229 MYLDAP_ENTRY *entry;
230 static const char *attrs[3];
231 int rc = LDAP_SUCCESS;
232 const char **values;
233 char *uid = NULL;
234 if (rcp == NULL)
235 rcp = &rc;
236 /* we have to look up the entry */
237 attrs[0] = attmap_passwd_uid;
238 attrs[1] = attmap_passwd_uidNumber;
239 attrs[2] = NULL;
240 search = myldap_search(session, dn, LDAP_SCOPE_BASE, passwd_filter, attrs, rcp);
241 if (search == NULL)
242 {
243 log_log(LOG_WARNING, "%s: lookup error: %s", dn, ldap_err2string(*rcp));
244 return NULL;
245 }
246 entry = myldap_get_entry(search, rcp);
247 if (entry == NULL)
248 {
249 if (*rcp != LDAP_SUCCESS)
250 log_log(LOG_WARNING, "%s: lookup error: %s", dn, ldap_err2string(*rcp));
251 return NULL;
252 }
253 /* check the uidNumber attribute if min_uid is set */
254 if (entry_has_valid_uid(entry))
255 {
256 /* get uid (just use first one) */
257 values = myldap_get_values(entry, attmap_passwd_uid);
258 /* check the result for presence and validity */
259 if ((values != NULL) && (values[0] != NULL) &&
260 isvalidname(values[0]) && (strlen(values[0]) < buflen))
261 {
262 strcpy(buf, values[0]);
263 uid = buf;
264 }
265 }
266 /* clean up and return */
267 myldap_search_close(search);
268 return uid;
269 }
270
271 /* Translate the DN into a user name. This function tries several approaches
272 at getting the user name, including looking in the DN for a uid attribute,
273 looking in the cache and falling back to looking up a uid attribute in a
274 LDAP query. */
dn2uid(MYLDAP_SESSION * session,const char * dn,char * buf,size_t buflen)275 char *dn2uid(MYLDAP_SESSION *session, const char *dn, char *buf, size_t buflen)
276 {
277 struct dn2uid_cache_entry *cacheentry = NULL;
278 char *uid;
279 /* check for empty string */
280 if ((dn == NULL) || (*dn == '\0'))
281 return NULL;
282 /* try to look up uid within DN string */
283 if (myldap_cpy_rdn_value(dn, attmap_passwd_uid, buf, buflen) != NULL)
284 {
285 /* check if it is valid */
286 if (!isvalidname(buf))
287 return NULL;
288 return buf;
289 }
290 /* if we don't use the cache, just lookup and return */
291 if ((nslcd_cfg->cache_dn2uid_positive == 0) && (nslcd_cfg->cache_dn2uid_negative == 0))
292 return lookup_dn2uid(session, dn, NULL, buf, buflen);
293 /* see if we have a cached entry */
294 pthread_mutex_lock(&dn2uid_cache_mutex);
295 if (dn2uid_cache == NULL)
296 dn2uid_cache = dict_new();
297 if ((dn2uid_cache != NULL) && ((cacheentry = dict_get(dn2uid_cache, dn)) != NULL))
298 {
299 if ((cacheentry->uid != NULL) && (strlen(cacheentry->uid) < buflen))
300 {
301 /* positive hit: if the cached entry is still valid, return that */
302 if ((nslcd_cfg->cache_dn2uid_positive > 0) &&
303 (time(NULL) < (cacheentry->timestamp + nslcd_cfg->cache_dn2uid_positive)))
304 {
305 strcpy(buf, cacheentry->uid);
306 pthread_mutex_unlock(&dn2uid_cache_mutex);
307 return buf;
308 }
309 }
310 else
311 {
312 /* negative hit: if the cached entry is still valid, return that */
313 if ((nslcd_cfg->cache_dn2uid_negative > 0) &&
314 (time(NULL) < (cacheentry->timestamp + nslcd_cfg->cache_dn2uid_negative)))
315 {
316 pthread_mutex_unlock(&dn2uid_cache_mutex);
317 return NULL;
318 }
319 }
320 }
321 pthread_mutex_unlock(&dn2uid_cache_mutex);
322 /* look up the uid using an LDAP query */
323 uid = lookup_dn2uid(session, dn, NULL, buf, buflen);
324 /* store the result in the cache */
325 pthread_mutex_lock(&dn2uid_cache_mutex);
326 /* try to get the entry from the cache here again because it could have
327 changed in the meantime */
328 cacheentry = dict_get(dn2uid_cache, dn);
329 if (cacheentry == NULL)
330 {
331 /* allocate a new entry in the cache */
332 cacheentry = (struct dn2uid_cache_entry *)malloc(sizeof(struct dn2uid_cache_entry));
333 if (cacheentry != NULL)
334 {
335 cacheentry->uid = NULL;
336 dict_put(dn2uid_cache, dn, cacheentry);
337 }
338 }
339 /* update the cache entry */
340 if (cacheentry != NULL)
341 {
342 cacheentry->timestamp = time(NULL);
343 /* copy the uid if needed */
344 if (cacheentry->uid == NULL)
345 cacheentry->uid = uid != NULL ? strdup(uid) : NULL;
346 else if ((uid == NULL) || (strcmp(cacheentry->uid, uid) != 0))
347 {
348 free(cacheentry->uid);
349 cacheentry->uid = uid != NULL ? strdup(uid) : NULL;
350 }
351 }
352 pthread_mutex_unlock(&dn2uid_cache_mutex);
353 /* copy the result into the buffer */
354 return uid;
355 }
356
uid2entry(MYLDAP_SESSION * session,const char * uid,int * rcp)357 MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session, const char *uid, int *rcp)
358 {
359 MYLDAP_SEARCH *search = NULL;
360 MYLDAP_ENTRY *entry = NULL;
361 const char *base;
362 int i;
363 static const char *attrs[3];
364 char filter[BUFLEN_FILTER];
365 /* if it isn't a valid username, just bail out now */
366 if (!isvalidname(uid))
367 {
368 if (rcp != NULL)
369 *rcp = LDAP_INVALID_SYNTAX;
370 return NULL;
371 }
372 /* set up attributes (we don't need much) */
373 attrs[0] = attmap_passwd_uid;
374 attrs[1] = attmap_passwd_uidNumber;
375 attrs[2] = NULL;
376 /* we have to look up the entry */
377 mkfilter_passwd_byname(uid, filter, sizeof(filter));
378 for (i = 0; (i < NSS_LDAP_CONFIG_MAX_BASES) && ((base = passwd_bases[i]) != NULL); i++)
379 {
380 search = myldap_search(session, base, passwd_scope, filter, attrs, rcp);
381 if (search == NULL)
382 {
383 if ((rcp != NULL) && (*rcp == LDAP_SUCCESS))
384 *rcp = LDAP_NO_SUCH_OBJECT;
385 return NULL;
386 }
387 entry = myldap_get_entry(search, rcp);
388 if ((entry != NULL) && (entry_has_valid_uid(entry)))
389 return entry;
390 }
391 if ((rcp != NULL) && (*rcp == LDAP_SUCCESS))
392 *rcp = LDAP_NO_SUCH_OBJECT;
393 return NULL;
394 }
395
uid2dn(MYLDAP_SESSION * session,const char * uid,char * buf,size_t buflen)396 char *uid2dn(MYLDAP_SESSION *session, const char *uid, char *buf, size_t buflen)
397 {
398 MYLDAP_ENTRY *entry;
399 /* look up the entry */
400 entry = uid2entry(session, uid, NULL);
401 if (entry == NULL)
402 return NULL;
403 /* get DN */
404 return myldap_cpy_dn(entry, buf, buflen);
405 }
406
407 #ifndef NSS_FLAVOUR_GLIBC
408 /* only check nsswitch.conf for glibc */
409 #define check_nsswitch_reload()
410 #define shadow_uses_ldap() (1)
411 #endif /* NSS_FLAVOUR_GLIBC */
412
413 /* the maximum number of uidNumber attributes per entry */
414 #define MAXUIDS_PER_ENTRY 5
415
write_passwd(TFILE * fp,MYLDAP_ENTRY * entry,const char * requser,const uid_t * requid,uid_t calleruid)416 static int write_passwd(TFILE *fp, MYLDAP_ENTRY *entry, const char *requser,
417 const uid_t *requid, uid_t calleruid)
418 {
419 int32_t tmpint32;
420 const char **tmpvalues;
421 char *tmp;
422 const char **usernames;
423 const char *passwd;
424 uid_t uids[MAXUIDS_PER_ENTRY];
425 int numuids;
426 char gidbuf[32];
427 gid_t gid;
428 char gecos[1024];
429 char homedir[256];
430 char shell[64];
431 char passbuffer[BUFLEN_PASSWORDHASH];
432 int i, j;
433 /* get the usernames for this entry */
434 usernames = myldap_get_values(entry, attmap_passwd_uid);
435 if ((usernames == NULL) || (usernames[0] == NULL))
436 {
437 log_log(LOG_WARNING, "%s: %s: missing",
438 myldap_get_dn(entry), attmap_passwd_uid);
439 return 0;
440 }
441 /* if we are using shadow maps and this entry looks like it would return
442 shadow information, make the passwd entry indicate it */
443 if (myldap_has_objectclass(entry, "shadowAccount") && nsswitch_shadow_uses_ldap())
444 {
445 passwd = "x";
446 }
447 else
448 {
449 passwd = get_userpassword(entry, attmap_passwd_userPassword,
450 passbuffer, sizeof(passbuffer));
451 if ((passwd == NULL) || (calleruid != 0))
452 passwd = default_passwd_userPassword;
453 }
454 /* get the uids for this entry */
455 if (requid != NULL)
456 {
457 uids[0] = *requid;
458 numuids = 1;
459 }
460 else
461 {
462 tmpvalues = myldap_get_values_len(entry, attmap_passwd_uidNumber);
463 if ((tmpvalues == NULL) || (tmpvalues[0] == NULL))
464 {
465 log_log(LOG_WARNING, "%s: %s: missing",
466 myldap_get_dn(entry), attmap_passwd_uidNumber);
467 return 0;
468 }
469 for (numuids = 0; (numuids < MAXUIDS_PER_ENTRY) && (tmpvalues[numuids] != NULL); numuids++)
470 {
471 if (uidSid != NULL)
472 uids[numuids] = (uid_t)binsid2id(tmpvalues[numuids]);
473 else
474 {
475 errno = 0;
476 uids[numuids] = strtouid(tmpvalues[numuids], &tmp, 10);
477 if ((*(tmpvalues[numuids]) == '\0') || (*tmp != '\0'))
478 {
479 log_log(LOG_WARNING, "%s: %s: non-numeric",
480 myldap_get_dn(entry), attmap_passwd_uidNumber);
481 return 0;
482 }
483 else if ((errno != 0) || (strchr(tmpvalues[numuids], '-') != NULL))
484 {
485 log_log(LOG_WARNING, "%s: %s: out of range",
486 myldap_get_dn(entry), attmap_passwd_uidNumber);
487 return 0;
488 }
489 }
490 uids[numuids] += nslcd_cfg->nss_uid_offset;
491 if (uids[numuids] < nslcd_cfg->nss_min_uid)
492 {
493 log_log(LOG_DEBUG, "%s: %s: less than nss_min_uid",
494 myldap_get_dn(entry), attmap_passwd_uidNumber);
495 }
496 }
497 }
498 /* get the gid for this entry */
499 if (gidSid != NULL)
500 {
501 tmpvalues = myldap_get_values_len(entry, attmap_passwd_gidNumber);
502 if ((tmpvalues == NULL) || (tmpvalues[0] == NULL))
503 {
504 log_log(LOG_WARNING, "%s: %s: missing",
505 myldap_get_dn(entry), attmap_passwd_gidNumber);
506 return 0;
507 }
508 gid = (gid_t)binsid2id(tmpvalues[0]);
509 }
510 else
511 {
512 attmap_get_value(entry, attmap_passwd_gidNumber, gidbuf, sizeof(gidbuf));
513 if (gidbuf[0] == '\0')
514 {
515 log_log(LOG_WARNING, "%s: %s: missing",
516 myldap_get_dn(entry), attmap_passwd_gidNumber);
517 return 0;
518 }
519 errno = 0;
520 gid = strtogid(gidbuf, &tmp, 10);
521 if ((gidbuf[0] == '\0') || (*tmp != '\0'))
522 {
523 log_log(LOG_WARNING, "%s: %s: non-numeric",
524 myldap_get_dn(entry), attmap_passwd_gidNumber);
525 return 0;
526 }
527 else if ((errno != 0) || (strchr(gidbuf, '-') != NULL))
528 {
529 log_log(LOG_WARNING, "%s: %s: out of range",
530 myldap_get_dn(entry), attmap_passwd_gidNumber);
531 return 0;
532 }
533 }
534 gid += nslcd_cfg->nss_gid_offset;
535 /* get the gecos for this entry */
536 attmap_get_value(entry, attmap_passwd_gecos, gecos, sizeof(gecos));
537 /* get the home directory for this entry */
538 attmap_get_value(entry, attmap_passwd_homeDirectory, homedir, sizeof(homedir));
539 if (homedir[0] == '\0')
540 log_log(LOG_WARNING, "%s: %s: missing",
541 myldap_get_dn(entry), attmap_passwd_homeDirectory);
542 /* get the shell for this entry */
543 attmap_get_value(entry, attmap_passwd_loginShell, shell, sizeof(shell));
544 /* write the entries */
545 for (i = 0; usernames[i] != NULL; i++)
546 {
547 if ((requser == NULL) || (STR_CMP(requser, usernames[i]) == 0))
548 {
549 if (!isvalidname(usernames[i]))
550 {
551 log_log(LOG_WARNING, "%s: %s: denied by validnames option",
552 myldap_get_dn(entry), attmap_passwd_uid);
553 }
554 else
555 {
556 for (j = 0; j < numuids; j++)
557 {
558 if (uids[j] >= nslcd_cfg->nss_min_uid)
559 {
560 WRITE_INT32(fp, NSLCD_RESULT_BEGIN);
561 WRITE_STRING(fp, usernames[i]);
562 WRITE_STRING(fp, passwd);
563 WRITE_INT32(fp, uids[j]);
564 WRITE_INT32(fp, gid);
565 WRITE_STRING(fp, gecos);
566 WRITE_STRING(fp, homedir);
567 WRITE_STRING(fp, shell);
568 }
569 }
570 }
571 }
572 }
573 return 0;
574 }
575
576 NSLCD_HANDLE_UID(
577 passwd, byname, NSLCD_ACTION_PASSWD_BYNAME,
578 char name[BUFLEN_NAME];
579 char filter[BUFLEN_FILTER];
580 READ_STRING(fp, name);
581 log_setrequest("passwd=\"%s\"", name);
582 if (!isvalidname(name))
583 {
584 log_log(LOG_WARNING, "request denied by validnames option");
585 return -1;
586 }
587 nsswitch_check_reload();,
588 mkfilter_passwd_byname(name, filter, sizeof(filter)),
589 write_passwd(fp, entry, name, NULL, calleruid)
590 )
591
592 NSLCD_HANDLE_UID(
593 passwd, byuid, NSLCD_ACTION_PASSWD_BYUID,
594 uid_t uid;
595 char filter[BUFLEN_FILTER];
596 READ_INT32(fp, uid);
597 log_setrequest("passwd=%lu", (unsigned long int)uid);
598 if (uid < nslcd_cfg->nss_min_uid)
599 {
600 log_log(LOG_DEBUG, "request ignored by nss_min_uid option");
601 /* return an empty result */
602 WRITE_INT32(fp, NSLCD_VERSION);
603 WRITE_INT32(fp, NSLCD_ACTION_PASSWD_BYUID);
604 WRITE_INT32(fp, NSLCD_RESULT_END);
605 return 0;
606 }
607 nsswitch_check_reload();,
608 mkfilter_passwd_byuid(uid, filter, sizeof(filter)),
609 write_passwd(fp, entry, NULL, &uid, calleruid)
610 )
611
612 NSLCD_HANDLE_UID(
613 passwd, all, NSLCD_ACTION_PASSWD_ALL,
614 const char *filter;
615 log_setrequest("passwd(all)");
616 nsswitch_check_reload();,
617 (filter = passwd_filter, 0),
618 write_passwd(fp, entry, NULL, NULL, calleruid)
619 )
620