summaryrefslogtreecommitdiff
path: root/nslcd
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2014-12-03 22:08:00 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2014-12-03 22:08:00 -0500
commit78ac111beb89f067376fdafda1f557ae227f1a98 (patch)
tree78591a32dd6382834cd9fc781d898aca90664d36 /nslcd
parent7a38ced276835128fd93262d362e91932040839e (diff)
mostly implement db_pam.c
Diffstat (limited to 'nslcd')
-rw-r--r--nslcd/db_pam.c719
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 */
+)