/* pam.c - pam processing routines Copyright (C) 2009 Howard Chu Copyright (C) 2009-2014 Arthur de Jong 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 */ #define _GNU_SOURCE /* for crypt_r(3) in crypt.h */ #include #include "config.h" #include #include #include #ifdef HAVE_STDINT_H #include #endif /* HAVE_STDINT_H */ #include #include "common.h" #include "log.h" #include "cfg.h" #include "common/dict.h" #include "common/expr.h" struct authc { int authc_rc; int authz_rc; char authz_msg[BUFLEN_MESSAGE]; }; struct authz { int authz_rc; char authz_msg[BUFLEN_MESSAGE]; }; static int check_password(const char *password, const char *hash) { int ret; struct crypt_data data; data.initialized = 0; ret = (strcmp(crypt_r(password, hash, &data), hash) == 0); memset(&data, 0, sizeof(data)); return ret; } static int check_password_age(MYLDAP_SESSION *session, const char *username, char *authzmsg, size_t authzmsgsz, int check_maxdays, int check_mindays) { /* hackers.git doesn't use aging features */ return NSLCD_PAM_SUCCESS; } /* check authentication credentials of the user */ NSLCD_HANDLE_UID(PAM, AUTHC ,/* decls */ char username[BUFLEN_NAME]; char service[BUFLEN_NAME]; char ruser[BUFLEN_NAME]; char rhost[BUFLEN_HOSTNAME]; char tty[64]; char password[BUFLEN_PASSWORD]; struct authc _entry; ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); READ_STRING(fp, rhost); READ_STRING(fp, tty); READ_STRING(fp, password); log_setrequest("authc=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_authc(\"%s\",\"%s\",\"%s\")", username, service, *password ? "***" : ""); ,/* check */ if (!isvalidname(username)) { log_log(LOG_WARNING, "request denied by validnames option"); return -1; } ,/* search(int *rcp) */ struct authc, static size_t i = 0; struct passwd *user = NULL; struct authc *entry = &_entry; for (; i < session->cnt; i++) { if (strcmp(username, session->users[i].pw_name)==0) { *rcp = 0; i = session->cnt; user = &(session->users[i]); } } if (user == NULL) return NULL; entry->authz_msg[0] = '\0'; /* try authentication */ /* TODO */ /*entry->authc_rc = check_password(password, hash) ? NSLCD_PAM_SUCCESS : NSLCD_PAM_AUTH_ERR; */ entry->authz_rc = entry->authc_rc; /*myldap_get_policy_response(session, &(entry->authz_rc), &(entry->authz_msg))*/ /* perform shadow attribute checks */ if (entry->authz_rc == NSLCD_PAM_SUCCESS) entry->authz_rc = check_password_age(session, username, entry->authz_msg, sizeof(entry->authz_msg), 1, 0); return entry; ,/* write */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); WRITE_INT32( fp, entry->authc_rc); WRITE_STRING(fp, username); WRITE_INT32( fp, entry->authz_rc); WRITE_STRING(fp, entry->authz_msg); 0; ,/* cleanup */ memset(password, 0, sizeof(password)); ) /* check authorisation of the user */ NSLCD_HANDLE(PAM, AUTHZ ,/* decls */ char username[BUFLEN_NAME]; char service[BUFLEN_NAME]; char ruser[BUFLEN_NAME]; char rhost[BUFLEN_HOSTNAME]; char tty[64]; struct authz _entry; ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); READ_STRING(fp, rhost); READ_STRING(fp, tty); /* log call */ log_setrequest("authz=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_authz(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", username, service, ruser, rhost, tty); ,/* check */ ,/* search(int *rcp) */ struct authz, static size_t i = 0; struct passwd *user = NULL; struct authz *entry = &_entry; for (; i < session->cnt; i++) { if (strcmp(username, session->users[i].pw_name)==0) { *rcp = 0; i = session->cnt; user = &(session->users[i]); } } if (user == NULL) return NULL; /* check authorisation search */ int rc = LDAP_SUCCESS; /* TODO */ if (rc != LDAP_SUCCESS) { entry->authz_rc = NSLCD_PAM_PERM_DENIED; strcpy(entry->authz_msg, "LDAP authorisation check failed"); return entry; } /* perform shadow attribute checks */ entry->authz_rc = check_password_age(session, username, entry->authz_msg, sizeof(entry->authz_msg), 0, 0); ,/* write response */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); WRITE_INT32( fp, entry->authz_rc); WRITE_STRING(fp, entry->authz_msg); 0; ,/* cleanup */ ) NSLCD_HANDLE(PAM, SESS_O ,/* decls */ char username[BUFLEN_NAME]; char service[BUFLEN_NAME]; char ruser[BUFLEN_NAME]; char rhost[BUFLEN_HOSTNAME]; char tty[64]; char sessionid[25]; static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "01234567890"; size_t i; ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); READ_STRING(fp, rhost); READ_STRING(fp, tty); /* generate pseudo-random session id */ for (i = 0; i < (sizeof(sessionid) - 1); i++) sessionid[i] = alphabet[rand() % (sizeof(alphabet) - 1)]; sessionid[i] = '\0'; /* log call */ log_setrequest("sess_o=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_sess_o(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"): %s", username, service, tty, rhost, ruser, sessionid); ,/* check */ ,/* search */ void, if (*rcp != 0) /* first time through, set success=0 (no errors), return non-NULL */ { return (void*)1; *rcp = 0; } else /* second time through, exit by returning NULL */ { return NULL; } ,/* write */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); WRITE_STRING(fp, sessionid); 0; ,/* cleanup */ ) NSLCD_HANDLE(PAM, SESS_C ,/* decls */ char username[BUFLEN_NAME]; char service[BUFLEN_NAME]; char ruser[BUFLEN_NAME]; char rhost[BUFLEN_HOSTNAME]; char tty[64]; char sessionid[64]; ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); READ_STRING(fp, rhost); READ_STRING(fp, tty); READ_STRING(fp, sessionid); log_setrequest("sess_c=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_sess_c(\"%s\",\"%s\",%s)", username, service, sessionid); ,/* check */ ,/* search */ void, if (*rcp != 0) /* first time through, set success=0 (no errors), return non-NULL */ { return (void*)1; *rcp = 0; } else /* second time through, exit by returning NULL */ { return NULL; } ,/* write */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); 0; ,/* cleanup */ )