diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-12-03 22:08:00 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-12-03 22:08:00 -0500 |
commit | 78ac111beb89f067376fdafda1f557ae227f1a98 (patch) | |
tree | 78591a32dd6382834cd9fc781d898aca90664d36 | |
parent | 7a38ced276835128fd93262d362e91932040839e (diff) |
mostly implement db_pam.c
-rw-r--r-- | nslcd/db_pam.c | 719 |
1 files changed, 80 insertions, 639 deletions
diff --git a/nslcd/db_pam.c b/nslcd/db_pam.c index 8deb74b..cb5c39e 100644 --- a/nslcd/db_pam.c +++ b/nslcd/db_pam.c @@ -20,6 +20,9 @@ 02110-1301 USA */ +#define _GNU_SOURCE /* for crypt_r(3) in crypt.h */ +#include <crypt.h> + #include "config.h" #include <stdio.h> @@ -28,7 +31,6 @@ #ifdef HAVE_STDINT_H #include <stdint.h> #endif /* HAVE_STDINT_H */ -#include <unistd.h> #include <time.h> #include "common.h" @@ -48,97 +50,6 @@ struct authz { 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, - int *authzrc, char *authzmsg, size_t authzmsgsz) -{ - MYLDAP_SESSION *session; - MYLDAP_SEARCH *search; - MYLDAP_ENTRY *entry; - static const char *attrs[2]; - int rc; - const char *msg; - /* set up a new connection */ - session = myldap_create_session(); - if (session == NULL) - return LDAP_UNAVAILABLE; - /* set up credentials for the session */ - if (myldap_set_credentials(session, userdn, password)) - { - myldap_session_close(session); - return LDAP_LOCAL_ERROR; - } - /* perform search for own object (just to do any kind of search) */ - attrs[0] = "dn"; - attrs[1] = NULL; - search = myldap_search(session, userdn, LDAP_SCOPE_BASE, - "(objectClass=*)", attrs, &rc); - if ((search == NULL) || (rc != LDAP_SUCCESS)) - { - if (rc == LDAP_SUCCESS) - rc = LDAP_LOCAL_ERROR; - log_log(LOG_WARNING, "%s: %s", userdn, ldap_err2string(rc)); - } - else - { - entry = myldap_get_entry(search, &rc); - if ((entry == NULL) || (rc != LDAP_SUCCESS)) - { - if (rc == LDAP_SUCCESS) - rc = LDAP_NO_RESULTS_RETURNED; - log_log(LOG_WARNING, "%s: %s", userdn, ldap_err2string(rc)); - } - } - /* get any policy response from the bind */ - myldap_get_policy_response(session, authzrc, &msg); - if ((msg != NULL) && (msg[0] != '\0')) - { - mysnprintf(authzmsg, authzmsgsz - 1, "%s", msg); - log_log(LOG_WARNING, "%s: %s", userdn, authzmsg); - } - /* close the session */ - myldap_session_close(session); - /* return results */ - return rc; -} - -/* update the username value from the entry if needed */ -static void update_username(MYLDAP_ENTRY *entry, char *username, - size_t username_len) -{ - const char **values; - const char *value; - /* get the "real" username */ - value = myldap_get_rdn_value(entry, attmap_passwd_uid); - if (value == NULL) - { - /* get the username from the uid attribute */ - values = myldap_get_values(entry, attmap_passwd_uid); - if ((values == NULL) || (values[0] == NULL)) - { - log_log(LOG_WARNING, "%s: %s: missing", - myldap_get_dn(entry), attmap_passwd_uid); - return; - } - value = values[0]; - } - /* check the username */ - if ((value == NULL) || !isvalidname(value) || strlen(value) >= username_len) - { - log_log(LOG_WARNING, "%s: %s: denied by validnames option", - myldap_get_dn(entry), attmap_passwd_uid); - return; - } - /* check if the username is different and update it if needed */ - if (strcmp(username, value) != 0) - { - log_log(LOG_INFO, "username changed from \"%s\" to \"%s\"", - username, value); - strcpy(username, value); - } -} - static int check_password(const char *password, const char *hash) { int ret; @@ -149,119 +60,23 @@ static int check_password(const char *password, const char *hash) return ret; } -static int check_shadow(MYLDAP_SESSION *session, const char *username, - char *authzmsg, size_t authzmsgsz, - int check_maxdays, int check_mindays) +static int check_password_age(MYLDAP_SESSION *session, const char *username, + char *authzmsg, size_t authzmsgsz, + int check_maxdays, int check_mindays) { - MYLDAP_ENTRY *entry = NULL; - long today, lastchangedate, mindays, maxdays, warndays, inactdays, expiredate; - unsigned long flag; - long daysleft, inactleft; - /* get the shadow entry */ - entry = shadow_uid2entry(session, username, NULL); - if (entry == NULL) - return NSLCD_PAM_SUCCESS; /* no shadow entry found, nothing to check */ - /* get today's date */ - today = (long)(time(NULL) / (60 * 60 * 24)); - /* get shadow information */ - get_shadow_properties(entry, &lastchangedate, &mindays, &maxdays, &warndays, - &inactdays, &expiredate, &flag); - /* check account expiry date */ - if ((expiredate != -1) && (today >= expiredate)) - { - daysleft = today - expiredate; - mysnprintf(authzmsg, authzmsgsz - 1, "account expired %ld days ago", - daysleft); - log_log(LOG_WARNING, "%s: %s: %s", - myldap_get_dn(entry), attmap_shadow_shadowExpire, authzmsg); - return NSLCD_PAM_ACCT_EXPIRED; - } - /* password expiration isn't interesting at this point because the user - may not have authenticated with a password and if he did that would be - checked in the authc phase */ - if (check_maxdays) - { - /* check lastchanged */ - if (lastchangedate == 0) - { - mysnprintf(authzmsg, authzmsgsz - 1, "need a new password"); - log_log(LOG_WARNING, "%s: %s: %s", - myldap_get_dn(entry), attmap_shadow_shadowLastChange, authzmsg); - return NSLCD_PAM_NEW_AUTHTOK_REQD; - } - else if (today < lastchangedate) - log_log(LOG_WARNING, "%s: %s: password changed in the future", - myldap_get_dn(entry), attmap_shadow_shadowLastChange); - else if (maxdays != -1) - { - /* check maxdays */ - daysleft = lastchangedate + maxdays - today; - if (daysleft == 0) - mysnprintf(authzmsg, authzmsgsz - 1, "password will expire today"); - else if (daysleft < 0) - mysnprintf(authzmsg, authzmsgsz - 1, "password expired %ld days ago", - -daysleft); - /* check inactdays */ - if ((daysleft <= 0) && (inactdays != -1)) - { - inactleft = lastchangedate + maxdays + inactdays - today; - if (inactleft == 0) - mysnprintf(authzmsg + strlen(authzmsg), authzmsgsz - strlen(authzmsg) - 1, - ", account will be locked today"); - else if (inactleft > 0) - mysnprintf(authzmsg + strlen(authzmsg), authzmsgsz - strlen(authzmsg) - 1, - ", account will be locked in %ld days", inactleft); - else - { - mysnprintf(authzmsg + strlen(authzmsg), authzmsgsz - strlen(authzmsg) - 1, - ", account locked %ld days ago", -inactleft); - log_log(LOG_WARNING, "%s: %s: %s", myldap_get_dn(entry), - attmap_shadow_shadowInactive, authzmsg); - return NSLCD_PAM_AUTHTOK_EXPIRED; - } - } - if (daysleft <= 0) - { - /* log previously built message */ - log_log(LOG_WARNING, "%s: %s: %s", - myldap_get_dn(entry), attmap_shadow_shadowMax, authzmsg); - return NSLCD_PAM_NEW_AUTHTOK_REQD; - } - /* check warndays */ - if ((warndays > 0) && (daysleft <= warndays)) - { - mysnprintf(authzmsg, authzmsgsz - 1, - "password will expire in %ld days", daysleft); - log_log(LOG_WARNING, "%s: %s: %s", - myldap_get_dn(entry), attmap_shadow_shadowWarning, authzmsg); - } - } - } - if (check_mindays) - { - daysleft = lastchangedate + mindays - today; - if ((mindays != -1) && (daysleft > 0)) - { - mysnprintf(authzmsg, authzmsgsz - 1, - "password cannot be changed for another %ld days", daysleft); - log_log(LOG_WARNING, "%s: %s: %s", - myldap_get_dn(entry), attmap_shadow_shadowMin, authzmsg); - return NSLCD_PAM_AUTHTOK_ERR; - } - } + /* hackers.git doesn't use aging features */ return NSLCD_PAM_SUCCESS; } /* check authentication credentials of the user */ -NSLCD_HANDLE_UID( - pam, authc, NSLCD_ACTION_PAM_AUTHC +NSLCD_HANDLE_UID(PAM, AUTHC ,/* decls */ - char username[BUFLEN_NAME], - service[BUFLEN_NAME], - ruser[BUFLEN_NAME], - rhost[BUFLEN_HOSTNAME], - tty[64], - password[BUFLEN_PASSWORD]; + 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); @@ -285,8 +100,6 @@ NSLCD_HANDLE_UID( struct passwd *user = NULL; struct authc *entry = &_entry; - *rcp = 0; - for (; i < session->cnt; i++) { if (strcmp(username, session->users[i].pw_name)==0) { @@ -301,15 +114,16 @@ NSLCD_HANDLE_UID( entry->authz_msg[0] = '\0'; /* try authentication */ - entry->authc_rc = check_password(password, hash) + /* TODO */ + /*entry->authc_rc = check_password(password, hash) ? NSLCD_PAM_SUCCESS - : NSLCD_PAM_AUTH_ERR; + : NSLCD_PAM_AUTH_ERR; */ entry->authz_rc = entry->authc_rc; - myldap_get_policy_response(session, &(entry->authz_rc), &(entry->authz_msg)) + /*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_shadow(session, username, entry->authz_msg, sizeof(entry->authz_msg), 1, 0); + entry->authz_rc = check_password_age(session, username, entry->authz_msg, sizeof(entry->authz_msg), 1, 0); return entry; ,/* write */ @@ -318,168 +132,19 @@ NSLCD_HANDLE_UID( WRITE_STRING(fp, username); WRITE_INT32( fp, entry->authz_rc); WRITE_STRING(fp, entry->authz_msg); + 0; ,/* cleanup */ memset(password, 0, sizeof(password)); -} - -static void autzsearch_var_add(DICT *dict, const char *name, - const char *value) -{ - size_t sz; - char *escaped_value; - /* allocate memory for escaped string */ - sz = ((strlen(value) + 8) * 120) / 100; - escaped_value = (char *)malloc(sz); - if (escaped_value == NULL) - { - log_log(LOG_CRIT, "autzsearch_var_add(): malloc() failed to allocate memory"); - return; - } - /* perform escaping of the value */ - if (myldap_escape(value, escaped_value, sz)) - { - log_log(LOG_ERR, "autzsearch_var_add(): escaped_value buffer too small"); - free(escaped_value); - return; - } - /* add to dict */ - dict_put(dict, name, escaped_value); -} - -static void autzsearch_vars_free(DICT *dict) -{ - int i; - const char **keys; - void *value; - /* go over all keys and free all the values - (they were allocated in autzsearch_var_add) */ - /* loop over dictionary contents */ - keys = dict_keys(dict); - for (i = 0; keys[i] != NULL; i++) - { - value = dict_get(dict, keys[i]); - if (value) - free(value); - } - free(keys); - /* after this values from the dict should obviously no longer be used */ -} - -static const char *autzsearch_var_get(const char *name, void *expander_attr) -{ - DICT *dict = (DICT *)expander_attr; - return (const char *)dict_get(dict, name); - /* TODO: if not set use entry to get attribute name (entry can be an - element in the dict) */ -} - -/* search all search bases using the provided filter */ -static int do_autzsearches(MYLDAP_SESSION *session, const char *filter) -{ - int i; - int rc; - const char *base; - static const char *attrs[2]; - MYLDAP_SEARCH *search; - MYLDAP_ENTRY *entry; - /* prepare the search */ - attrs[0] = "dn"; - attrs[1] = NULL; - /* perform a search for each search base */ - log_log(LOG_DEBUG, "trying pam_authz_search \"%s\"", filter); - for (i = 0; (base = nslcd_cfg->bases[i]) != NULL; i++) - { - /* do the LDAP search */ - search = myldap_search(session, base, LDAP_SCOPE_SUBTREE, filter, attrs, &rc); - if (search == NULL) - { - log_log(LOG_ERR, "pam_authz_search \"%s\" failed: %s", - filter, ldap_err2string(rc)); - return rc; - } - /* try to get an entry */ - entry = myldap_get_entry(search, &rc); - if (entry != NULL) - { - log_log(LOG_DEBUG, "pam_authz_search found \"%s\"", myldap_get_dn(entry)); - return LDAP_SUCCESS; - } - } - log_log(LOG_ERR, "pam_authz_search \"%s\" found no matches", filter); - if (rc == LDAP_SUCCESS) - rc = LDAP_NO_SUCH_OBJECT; - return rc; -} - -/* perform an authorisation search, returns an LDAP status code */ -static int try_autzsearch(MYLDAP_SESSION *session, const char *dn, - const char *username, const char *servicename, - const char *ruser, const char *rhost, - const char *tty) -{ - char hostname[BUFLEN_HOSTNAME]; - const char *fqdn; - DICT *dict = NULL; - char filter[BUFLEN_FILTER]; - int rc = LDAP_SUCCESS; - const char *res; - int i; - /* go over all pam_authz_search options */ - for (i = 0; (i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES) && (nslcd_cfg->pam_authz_searches[i] != NULL); i++) - { - if (dict == NULL) - { - /* build the dictionary with variables - NOTE: any variables added here also need to be added to - cfg.c:parse_pam_authz_search_statement() */ - dict = dict_new(); - autzsearch_var_add(dict, "username", username); - autzsearch_var_add(dict, "service", servicename); - autzsearch_var_add(dict, "ruser", ruser); - autzsearch_var_add(dict, "rhost", rhost); - autzsearch_var_add(dict, "tty", tty); - if (gethostname(hostname, sizeof(hostname)) == 0) - autzsearch_var_add(dict, "hostname", hostname); - if ((fqdn = getfqdn()) != NULL) - autzsearch_var_add(dict, "fqdn", fqdn); - autzsearch_var_add(dict, "dn", dn); - autzsearch_var_add(dict, "uid", username); - } - /* build the search filter */ - res = expr_parse(nslcd_cfg->pam_authz_searches[i], - filter, sizeof(filter), - autzsearch_var_get, (void *)dict); - if (res == NULL) - { - autzsearch_vars_free(dict); - dict_free(dict); - log_log(LOG_ERR, "invalid pam_authz_search \"%s\"", - nslcd_cfg->pam_authz_searches[i]); - return LDAP_LOCAL_ERROR; - } - /* perform the actual searches on all bases */ - rc = do_autzsearches(session, filter); - if (rc != LDAP_SUCCESS) - break; - } - /* we went over all pam_authz_search entries */ - if (dict != NULL) - { - autzsearch_vars_free(dict); - dict_free(dict); - } - return rc; -} +) /* check authorisation of the user */ -NSLCD_HANDLE( - pam, authz, NSLCD_ACTION_PAM_AUTHZ +NSLCD_HANDLE(PAM, AUTHZ ,/* decls */ - char username[BUFLEN_NAME], - service[BUFLEN_NAME], - ruser[BUFLEN_NAME], - rhost[BUFLEN_HOSTNAME], - tty[64]; + 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); @@ -491,14 +156,13 @@ NSLCD_HANDLE( 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; - *rcp = 0; - for (; i < session->cnt; i++) { if (strcmp(username, session->users[i].pw_name)==0) { @@ -511,39 +175,38 @@ NSLCD_HANDLE( return NULL; /* check authorisation search */ - int rc = try_autzsearch(session, myldap_get_dn(entry), - username, service, ruser, rhost, tty); + int rc = LDAP_SUCCESS; /* TODO */ if (rc != LDAP_SUCCESS) { - entry->authz_rc = NSLCD_PAM_PERM_DENIED); + 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_shadow(session, username, entry->authz_msg, sizeof(entry->authz_msg), 0, 0); + 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 */ -} +) -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], - sessionid[25]; +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"; - unsigned int i; - /* read request parameters */ + size_t i; + ,/* read */ READ_STRING(fp, username); READ_STRING(fp, service); READ_STRING(fp, ruser); @@ -557,279 +220,57 @@ int nslcd_pam_sess_o(TFILE *fp, MYLDAP_SESSION UNUSED(*session)) 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); - /* write the response header */ - WRITE_INT32(fp, NSLCD_VERSION); - WRITE_INT32(fp, NSLCD_ACTION_PAM_SESS_O); - /* write response */ + ,/* 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); - WRITE_INT32(fp, NSLCD_RESULT_END); - return 0; -} + 0; + ,/* cleanup */ +) -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], - sessionid[64]; - /* read request parameters */ +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 call */ log_setrequest("sess_c=\"%s\"", username); log_log(LOG_DEBUG, "nslcd_pam_sess_c(\"%s\",\"%s\",%s)", username, service, sessionid); - /* write the response header */ - WRITE_INT32(fp, NSLCD_VERSION); - WRITE_INT32(fp, NSLCD_ACTION_PAM_SESS_C); - /* write response */ - WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, NSLCD_RESULT_END); - return 0; -} - -extern const char *shadow_filter; - -/* try to update the shadowLastChange attribute of the entry if possible */ -static int update_lastchange(MYLDAP_SESSION *session, const char *userdn) -{ - MYLDAP_SEARCH *search; - MYLDAP_ENTRY *entry; - static const char *attrs[3]; - const char *attr; - int rc; - const char **values; - LDAPMod mod, *mods[2]; - char buffer[64], *strvals[2]; - /* find the name of the attribute to use */ - if ((attmap_shadow_shadowLastChange == NULL) || (attmap_shadow_shadowLastChange[0] == '\0')) - return LDAP_LOCAL_ERROR; /* attribute not mapped at all */ - else if (strcmp(attmap_shadow_shadowLastChange, "\"${shadowLastChange:--1}\"") == 0) - attr = "shadowLastChange"; - else if (attmap_shadow_shadowLastChange[0] == '\"') - return LDAP_LOCAL_ERROR; /* other expressions not supported for now */ - else - attr = attmap_shadow_shadowLastChange; - /* set up the attributes we need */ - attrs[0] = attmap_shadow_uid; - attrs[1] = attr; - attrs[2] = NULL; - /* find the entry to see if the attribute is present */ - search = myldap_search(session, userdn, LDAP_SCOPE_BASE, shadow_filter, attrs, &rc); - if (search == NULL) - return rc; - entry = myldap_get_entry(search, &rc); - if (entry == NULL) - return rc; - values = myldap_get_values(entry, attr); - if ((values == NULL) || (values[0] == NULL) || (values[0][0] == '\0')) - return LDAP_NO_SUCH_ATTRIBUTE; - /* build the value for the new attribute */ - if (strcasecmp(attr, "pwdLastSet") == 0) - { - /* for AD we use another timestamp */ - if (mysnprintf(buffer, sizeof(buffer), "%ld000000000", - ((long int)time(NULL) / 100L + (134774L * 864L)))) - return LDAP_LOCAL_ERROR; - } - else - { - /* time in days since Jan 1, 1970 */ - if (mysnprintf(buffer, sizeof(buffer), "%ld", - ((long int)(time(NULL) / (long int)(60 * 60 * 24))))) - return LDAP_LOCAL_ERROR; - } - /* update the shadowLastChange attribute */ - strvals[0] = buffer; - strvals[1] = NULL; - mod.mod_op = LDAP_MOD_REPLACE; - mod.mod_type = (char *)attr; - mod.mod_values = strvals; - mods[0] = &mod; - mods[1] = NULL; - rc = myldap_modify(session, userdn, mods); - if (rc != LDAP_SUCCESS) - log_log(LOG_WARNING, "%s: %s: modification failed: %s", - userdn, attr, ldap_err2string(rc)); - else - log_log(LOG_DEBUG, "%s: %s: modification succeeded", userdn, attr); - return rc; -} - -/* perform an LDAP password modification, returns an LDAP status code */ -static int try_pwmod(MYLDAP_SESSION *oldsession, - const char *binddn, const char *userdn, - const char *oldpassword, const char *newpassword, - char *authzmsg, size_t authzmsg_len) -{ - MYLDAP_SESSION *session; - char buffer[BUFLEN_MESSAGE]; - int rc; - /* set up a new connection */ - session = myldap_create_session(); - if (session == NULL) - return LDAP_UNAVAILABLE; - /* set up credentials for the session */ - if (myldap_set_credentials(session, binddn, oldpassword)) - { - myldap_session_close(session); - return LDAP_LOCAL_ERROR; - } - /* perform search for own object (just to do any kind of search) */ - if ((lookup_dn2uid(session, userdn, &rc, buffer, sizeof(buffer)) != NULL) && - (rc == LDAP_SUCCESS)) - { - /* if doing password modification as admin, don't pass old password along */ - if ((nslcd_cfg->rootpwmoddn != NULL) && - (strcmp(binddn, nslcd_cfg->rootpwmoddn) == 0)) - oldpassword = NULL; - /* perform password modification */ - rc = myldap_passwd(session, userdn, oldpassword, newpassword); - if (rc == LDAP_SUCCESS) - { - /* try to update the shadowLastChange attribute */ - if (update_lastchange(session, userdn) != LDAP_SUCCESS) - /* retry with the normal session */ - (void)update_lastchange(oldsession, userdn); - } - else - { - /* get a diagnostic or error message */ - if ((myldap_error_message(session, rc, buffer, sizeof(buffer)) == LDAP_SUCCESS) && - (buffer[0] != '\0')) - mysnprintf(authzmsg, authzmsg_len - 1, "password change failed: %s", - buffer); - } - } - /* close the session */ - myldap_session_close(session); - /* return */ - return rc; -} - -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]; - int asroot; - char oldpassword[BUFLEN_PASSWORD]; - char newpassword[BUFLEN_PASSWORD]; - const char *binddn = NULL; /* the user performing the modification */ - MYLDAP_ENTRY *entry; - char authzmsg[BUFLEN_MESSAGE]; - authzmsg[0] = '\0'; - /* read request parameters */ - READ_STRING(fp, username); - READ_STRING(fp, service); - READ_STRING(fp, ruser); - READ_STRING(fp, rhost); - READ_STRING(fp, tty); - READ_INT32(fp, asroot); - READ_STRING(fp, oldpassword); - READ_STRING(fp, newpassword); - /* log call */ - log_setrequest("pwmod=\"%s\"", username); - log_log(LOG_DEBUG, "nslcd_pam_pwmod(\"%s\",%s,\"%s\",\"%s\",\"%s\")", - username, asroot ? "asroot" : "asuser", service, - *oldpassword ? "***" : "", *newpassword ? "***" : ""); - /* write the response header */ - WRITE_INT32(fp, NSLCD_VERSION); - WRITE_INT32(fp, NSLCD_ACTION_PAM_PWMOD); - /* validate request */ - 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(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return -1; - } - /* check if pam_password_prohibit_message is set */ - if (nslcd_cfg->pam_password_prohibit_message != NULL) - { - log_log(LOG_NOTICE, "password change prohibited"); - WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, NSLCD_PAM_PERM_DENIED); - WRITE_STRING(fp, nslcd_cfg->pam_password_prohibit_message); - WRITE_INT32(fp, NSLCD_RESULT_END); - memset(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return 0; - } - /* check if the the user passed the rootpwmoddn */ - if (asroot) - { - binddn = nslcd_cfg->rootpwmoddn; - /* check if rootpwmodpw should be used */ - if ((*oldpassword == '\0') && (calleruid == 0) && - (nslcd_cfg->rootpwmodpw != NULL)) - { - if (strlen(nslcd_cfg->rootpwmodpw) >= sizeof(oldpassword)) - { - log_log(LOG_ERR, "nslcd_pam_pwmod(): rootpwmodpw will not fit in oldpassword"); - memset(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return -1; - } - strcpy(oldpassword, nslcd_cfg->rootpwmodpw); - } - } - else + ,/* check */ + ,/* search */ + void, + if (*rcp != 0) /* first time through, set success=0 (no errors), return non-NULL */ { - binddn = myldap_get_dn(entry); - /* check whether shadow properties allow password change */ - rc = check_shadow(session, username, authzmsg, sizeof(authzmsg), 0, 1); - if (rc != NSLCD_PAM_SUCCESS) - { - WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, rc); - WRITE_STRING(fp, authzmsg); - WRITE_INT32(fp, NSLCD_RESULT_END); - memset(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return 0; - } + return (void*)1; + *rcp = 0; } - /* perform password modification */ - rc = try_pwmod(session, binddn, myldap_get_dn(entry), oldpassword, newpassword, - authzmsg, sizeof(authzmsg)); - if (rc != LDAP_SUCCESS) + else /* second time through, exit by returning NULL */ { - if (authzmsg[0] == '\0') - mysnprintf(authzmsg, sizeof(authzmsg) - 1, "password change failed: %s", - ldap_err2string(rc)); - WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, NSLCD_PAM_PERM_DENIED); - WRITE_STRING(fp, authzmsg); - WRITE_INT32(fp, NSLCD_RESULT_END); - memset(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return 0; + return NULL; } - /* write response */ - log_log(LOG_NOTICE, "password changed for %s", myldap_get_dn(entry)); + ,/* write */ WRITE_INT32(fp, NSLCD_RESULT_BEGIN); - WRITE_INT32(fp, NSLCD_PAM_SUCCESS); - WRITE_STRING(fp, ""); - WRITE_INT32(fp, NSLCD_RESULT_END); - memset(oldpassword, 0, sizeof(oldpassword)); - memset(newpassword, 0, sizeof(newpassword)); - return 0; -} + 0; + ,/* cleanup */ +) |