diff options
Diffstat (limited to 'nslcd/db_pam.c')
-rw-r--r-- | nslcd/db_pam.c | 258 |
1 files changed, 124 insertions, 134 deletions
diff --git a/nslcd/db_pam.c b/nslcd/db_pam.c index 0eff71b..f47b331 100644 --- a/nslcd/db_pam.c +++ b/nslcd/db_pam.c @@ -39,6 +39,17 @@ #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]; +}; + /* set up a connection and try to bind with the specified DN and password, returns an LDAP result code */ static int try_bind(const char *userdn, const char *password, @@ -94,32 +105,6 @@ static int try_bind(const char *userdn, const char *password, return rc; } -/* ensure that both userdn and username are filled in from the entry, - returns an LDAP result code */ -static MYLDAP_ENTRY *validate_user(MYLDAP_SESSION *session, - char *username, int *rcp) -{ - int rc; - MYLDAP_ENTRY *entry = NULL; - /* check username for validity */ - if (!isvalidname(username)) - { - log_log(LOG_WARNING, "request denied by validnames option"); - *rcp = LDAP_NO_SUCH_OBJECT; - return NULL; - } - /* get the user entry based on the username */ - entry = uid2entry(session, username, &rc); - if (entry == NULL) - { - if (rc == LDAP_SUCCESS) - rc = LDAP_NO_SUCH_OBJECT; - log_log(LOG_DEBUG, "\"%s\": user not found: %s", username, ldap_err2string(rc)); - *rcp = rc; - } - return entry; -} - /* update the username value from the entry if needed */ static void update_username(MYLDAP_ENTRY *entry, char *username, size_t username_len) @@ -156,6 +141,16 @@ static void update_username(MYLDAP_ENTRY *entry, char *username, } } +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_shadow(MYLDAP_SESSION *session, const char *username, char *authzmsg, size_t authzmsgsz, int check_maxdays, int check_mindays) @@ -260,95 +255,73 @@ static int check_shadow(MYLDAP_SESSION *session, const char *username, } /* check authentication credentials of the user */ -int nslcd_pam_authc(TFILE *fp, MYLDAP_SESSION *session, uid_t calleruid) -{ - int32_t tmpint32; - int rc; - char username[BUFLEN_NAME], service[BUFLEN_NAME], ruser[BUFLEN_NAME], rhost[BUFLEN_HOSTNAME], tty[64]; - char password[BUFLEN_PASSWORD]; - const char *userdn; - MYLDAP_ENTRY *entry; - int authzrc = NSLCD_PAM_SUCCESS; - char authzmsg[BUFLEN_MESSAGE]; - authzmsg[0] = '\0'; - /* read request parameters */ +NSLCD_HANDLE_UID( + pam, authc, NSLCD_ACTION_PAM_AUTHC + ,/* decls */ + char username[BUFLEN_NAME], + service[BUFLEN_NAME], + ruser[BUFLEN_NAME], + rhost[BUFLEN_HOSTNAME], + tty[64], + 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 call */ log_setrequest("authc=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_authc(\"%s\",\"%s\",\"%s\")", username, service, *password ? "***" : ""); - /* write the response header */ - WRITE_INT32(fp, NSLCD_VERSION); - WRITE_INT32(fp, NSLCD_ACTION_PAM_AUTHC); - /* if the username is blank and rootpwmoddn is configured, try to - authenticate as administrator, otherwise validate request as usual */ - if (*username == '\0') + ,/* check */ + if (!isvalidname(username)) { - if (nslcd_cfg->rootpwmoddn == NULL) - { - log_log(LOG_NOTICE, "rootpwmoddn not configured"); - /* we break the protocol */ - memset(password, 0, sizeof(password)); - return -1; - } - userdn = nslcd_cfg->rootpwmoddn; - /* if the caller is root we will allow the use of the rootpwmodpw option */ - if ((*password == '\0') && (calleruid == 0) && (nslcd_cfg->rootpwmodpw != NULL)) - { - if (strlen(nslcd_cfg->rootpwmodpw) >= sizeof(password)) - { - log_log(LOG_ERR, "nslcd_pam_authc(): rootpwmodpw will not fit in password"); - memset(password, 0, sizeof(password)); - return -1; - } - strcpy(password, nslcd_cfg->rootpwmodpw); - } + log_log(LOG_WARNING, "request denied by validnames option"); + return -1; } - else + ,/* search(int *rcp) */ + struct authc, + static size_t i = 0; + struct passwd *user = NULL; + struct authc *entry = &_entry; + + *rcp = 0; + + for (; i < session->cnt; i++) { - /* try normal authentication, lookup the user entry */ - entry = validate_user(session, username, &rc); - if (entry == NULL) - { - /* for user not found we just say no result */ - if (rc == LDAP_NO_SUCH_OBJECT) - { - WRITE_INT32(fp, NSLCD_RESULT_END); - } - memset(password, 0, sizeof(password)); - return -1; + if (strcmp(username, session->users[i].pw_name)==0) { + *rcp = 0; + i = session->cnt; + user = &(session->users[i]); } - userdn = myldap_get_dn(entry); - update_username(entry, username, sizeof(username)); } + if (user == NULL) + return NULL; + + entry->authz_msg[0] = '\0'; + /* try authentication */ - rc = try_bind(userdn, password, &authzrc, authzmsg, sizeof(authzmsg)); - if (rc == LDAP_SUCCESS) - log_log(LOG_DEBUG, "bind successful"); - /* map result code */ - switch (rc) - { - case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break; - case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break; - default: rc = NSLCD_PAM_AUTH_ERR; - } + 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 ((*username != '\0') && (authzrc == NSLCD_PAM_SUCCESS)) - authzrc = check_shadow(session, username, authzmsg, sizeof(authzmsg), 1, 0); - /* write response */ + if (entry->authz_rc == NSLCD_PAM_SUCCESS) + entry->authz_rc = check_shadow(session, username, entry->authz_msg, sizeof(entry->authz_msg), 1, 0); + + return entry; + ,/* write */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, rc); + WRITE_INT32( fp, entry->authc_rc); WRITE_STRING(fp, username); - WRITE_INT32(fp, authzrc); - WRITE_STRING(fp, authzmsg); - WRITE_INT32(fp, NSLCD_RESULT_END); + WRITE_INT32( fp, entry->authz_rc); + WRITE_STRING(fp, entry->authz_msg); + ,/* cleanup */ memset(password, 0, sizeof(password)); - return 0; } static void autzsearch_var_add(DICT *dict, const char *name, @@ -501,15 +474,16 @@ static int try_autzsearch(MYLDAP_SESSION *session, const char *dn, } /* check authorisation of the user */ -int nslcd_pam_authz(TFILE *fp, MYLDAP_SESSION *session) -{ - int32_t tmpint32; - int rc; - char username[BUFLEN_NAME], service[BUFLEN_NAME], ruser[BUFLEN_NAME], rhost[BUFLEN_HOSTNAME], tty[64]; - MYLDAP_ENTRY *entry; - char authzmsg[BUFLEN_MESSAGE]; - authzmsg[0] = '\0'; - /* read request parameters */ +NSLCD_HANDLE( + pam, authz, NSLCD_ACTION_PAM_AUTHZ + ,/* decls */ + char username[BUFLEN_NAME], + service[BUFLEN_NAME], + ruser[BUFLEN_NAME], + rhost[BUFLEN_HOSTNAME], + tty[64]; + struct authz _entry; + ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); @@ -519,46 +493,54 @@ int nslcd_pam_authz(TFILE *fp, MYLDAP_SESSION *session) log_setrequest("authz=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_authz(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", username, service, ruser, rhost, tty); - /* write the response header */ - WRITE_INT32(fp, NSLCD_VERSION); - WRITE_INT32(fp, NSLCD_ACTION_PAM_AUTHZ); - /* validate request */ - entry = validate_user(session, username, &rc); - if (entry == NULL) + ,/* search(int *rcp) */ + struct authz, + static size_t i = 0; + struct passwd *user = NULL; + struct authz *entry = &_entry; + + *rcp = 0; + + for (; i < session->cnt; i++) { - /* for user not found we just say no result */ - if (rc == LDAP_NO_SUCH_OBJECT) - { - WRITE_INT32(fp, NSLCD_RESULT_END); + if (strcmp(username, session->users[i].pw_name)==0) { + *rcp = 0; + i = session->cnt; + user = &(session->users[i]); } - return -1; } + if (user == NULL) + return NULL; + /* check authorisation search */ - rc = try_autzsearch(session, myldap_get_dn(entry), username, service, ruser, - rhost, tty); + int rc = try_autzsearch(session, myldap_get_dn(entry), + username, service, ruser, rhost, tty); if (rc != LDAP_SUCCESS) { - WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, NSLCD_PAM_PERM_DENIED); - WRITE_STRING(fp, "LDAP authorisation check failed"); - WRITE_INT32(fp, NSLCD_RESULT_END); - return 0; + entry->authz_rc = NSLCD_PAM_PERM_DENIED); + strcpy(entry->authz_msg, "LDAP authorisation check failed"); + return entry; } + /* perform shadow attribute checks */ - rc = check_shadow(session, username, authzmsg, sizeof(authzmsg), 0, 0); - /* write response */ + entry->authz_rc = check_shadow(session, username, entry->authz_msg, sizeof(entry->authz_msg), 0, 0); + + ,/* write response */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, rc); - WRITE_STRING(fp, authzmsg); - WRITE_INT32(fp, NSLCD_RESULT_END); - return 0; + WRITE_INT32( fp, entry->authz_rc); + WRITE_STRING(fp, entry->authz_msg); + ,/* cleanup */ } int nslcd_pam_sess_o(TFILE *fp, MYLDAP_SESSION UNUSED(*session)) { int32_t tmpint32; - char username[BUFLEN_NAME], service[BUFLEN_NAME], ruser[BUFLEN_NAME], rhost[BUFLEN_HOSTNAME], tty[64]; - char sessionid[25]; + char username[BUFLEN_NAME], + service[BUFLEN_NAME], + ruser[BUFLEN_NAME], + rhost[BUFLEN_HOSTNAME], + tty[64], + sessionid[25]; static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "01234567890"; @@ -590,8 +572,12 @@ int nslcd_pam_sess_o(TFILE *fp, MYLDAP_SESSION UNUSED(*session)) int nslcd_pam_sess_c(TFILE *fp, MYLDAP_SESSION UNUSED(*session)) { int32_t tmpint32; - char username[BUFLEN_NAME], service[BUFLEN_NAME], ruser[BUFLEN_NAME], rhost[BUFLEN_HOSTNAME], tty[64]; - char sessionid[64]; + char username[BUFLEN_NAME], + service[BUFLEN_NAME], + ruser[BUFLEN_NAME], + rhost[BUFLEN_HOSTNAME], + tty[64], + sessionid[64]; /* read request parameters */ READ_STRING(fp, username); READ_STRING(fp, service); @@ -735,7 +721,11 @@ int nslcd_pam_pwmod(TFILE *fp, MYLDAP_SESSION *session, uid_t calleruid) { int32_t tmpint32; int rc; - char username[BUFLEN_NAME], service[BUFLEN_NAME], ruser[BUFLEN_NAME], rhost[BUFLEN_HOSTNAME], tty[64]; + char username[BUFLEN_NAME], + service[BUFLEN_NAME], + ruser[BUFLEN_NAME], + rhost[BUFLEN_HOSTNAME], + tty[64]; int asroot; char oldpassword[BUFLEN_PASSWORD]; char newpassword[BUFLEN_PASSWORD]; |