/* passwd.c - password entry lookup routines Parts of this file were part of the nss_ldap library (as ldap-pwd.c) which has been forked into the nss-pam-ldapd library. Copyright (C) 1997-2005 Luke Howard Copyright (C) 2006 West Consulting Copyright (C) 2006-2014 Arthur de Jong Copyright (C) 2014 Luke Shumaker This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include "common.h" #include "log.h" #include "cfg.h" #include "common/dict.h" #include "compat/strndup.h" #ifndef NSS_FLAVOUR_GLIBC /* only check nsswitch.conf for glibc */ #define check_nsswitch_reload() #define shadow_uses_nslcd() (1) #endif /* NSS_FLAVOUR_GLIBC */ /* Note that the resulting password value should be one of: - no password set, allow login without password ! - used to prevent logins x - "valid" encrypted password that does not match any valid password often used to indicate that the password is defined elsewhere other - encrypted password, in crypt(3) format */ static int write_passwd(TFILE *fp, struct passwd *entry, uid_t calleruid) { const char *passwd; /* if we are using shadow maps and this entry looks like it would return shadow information, make the passwd entry indicate it */ if (nsswitch_shadow_uses_nslcd()) { passwd = "x"; } else { passwd = entry->pw_passwd; if ((passwd == NULL) || (calleruid != 0)) passwd = "!"; } WRITE_STRING(fp, entry->pw_name ); WRITE_STRING(fp, passwd ); WRITE_INT32( fp, entry->pw_uid ); WRITE_INT32( fp, entry->pw_gid ); WRITE_STRING(fp, entry->pw_gecos); WRITE_STRING(fp, entry->pw_dir ); WRITE_STRING(fp, entry->pw_shell); return 0; } NSLCD_HANDLE_UID(PASSWD, BYNAME ,/* request data */ struct { char name[BUFLEN_NAME]; } ,/* search data */ struct { int cnt; } ,/* entry type */ struct passwd ,/* int read(TFILE *fp, *req) */ READ_STRING(fp, req->name); log_setrequest("passwd=\"%s\"", req->name); return 0; ,/* check(*req) */ if (!isvalidname(req->name)) { log_log(LOG_WARNING, "request denied by validnames option"); return -1; } nsswitch_check_reload(); return 0; ,/* search(*session, *req, *searchdat, *entry) */ *entry = NULL; if (searchdat->cnt++ != 0) return 0; for (size_t i = 0; i < session->cnt; i++) { if (session->users[i].pw_uid != UID_INVALID && STR_CMP(req->name, session->users[i].pw_name)==0) { *entry = &(session->users[i]); if ((*entry)->pw_uid < nslcd_cfg->nss_min_uid) { *entry = NULL; return -1; } break; } } return 0; ,/* int write(TFILE *fp, tentry *entry) */ return write_passwd(fp, entry, calleruid); ,/* cleanup */ ) NSLCD_HANDLE_UID(PASSWD, BYUID ,/* request data */ struct { uid_t uid; } ,/* search data */ struct { int cnt; } ,/* entry type */ struct passwd ,/* int read(TFILe *fp) */ READ_INT32(fp, req->uid); log_setrequest("passwd=%lu", (unsigned long int)(req->uid)); return 0; ,/* check */ nsswitch_check_reload(); return 0; ,/* search(*session, *req, *searchdat, *entry) */ *entry = NULL; if (req->uid < nslcd_cfg->nss_min_uid || searchdat->cnt++ != 0) return 0; for (size_t i = 0; i < session->cnt; i++) { if (req->uid == session->users[i].pw_uid) { *entry = &(session->users[i]); break; } } return 0; ,/* int write(TFILe *fp, *entry) */ return write_passwd(fp, entry, calleruid); ,/* cleanup */ ) NSLCD_HANDLE_UID(PASSWD, ALL ,/* request data */ int ,/* search data */ struct { size_t i; } ,/* entry type */ struct passwd ,/* int read(TFILE *fp, *req) */ log_setrequest("passwd(all)"); return 0; ,/* check */ nsswitch_check_reload(); return 0; ,/* search(*session, *req, *searchdat, *entry) */ *entry = NULL; for (; searchdat->i < session->cnt; searchdat->i++) { if (session->users[searchdat->i].pw_uid != UID_INVALID && session->users[searchdat->i].pw_uid >= nslcd_cfg->nss_min_uid) { *entry = &(session->users[searchdat->i]); searchdat->i++; return 0; } } return 0; ,/* int write(TFILE *fp, tentry *entry) */ return write_passwd(fp, entry, calleruid); ,/* cleanup */ )