diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-26 17:09:47 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-26 17:09:47 +0000 |
commit | 8eb43e411882e26257c07c32949028bf76e187ec (patch) | |
tree | e1196633aa337527f4997af57287b773f3770524 | |
parent | 1a379549c64ecbdb56c834e935223c991700da7d (diff) |
try to update the shadowLastChange attribute of a user on password change (the update is only tried if the attribute is present to begin with)
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1345 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | nslcd/common.h | 3 | ||||
-rw-r--r-- | nslcd/myldap.c | 12 | ||||
-rw-r--r-- | nslcd/myldap.h | 5 | ||||
-rw-r--r-- | nslcd/pam.c | 5 | ||||
-rw-r--r-- | nslcd/shadow.c | 66 |
5 files changed, 90 insertions, 1 deletions
diff --git a/nslcd/common.h b/nslcd/common.h index 90e9b10..f3a3288 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -94,6 +94,9 @@ MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid,int *rcp); /* transforms the uid into a DN by doing an LDAP lookup */ MUST_USE char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen); +/* try to update the shadowLastChange attribute of the entry if possible */ +int update_lastchange(MYLDAP_SESSION *session,const char *userdn); + /* these are the functions for initialising the database specific modules */ void alias_init(void); diff --git a/nslcd/myldap.c b/nslcd/myldap.c index fb0f617..a1acb21 100644 --- a/nslcd/myldap.c +++ b/nslcd/myldap.c @@ -1705,3 +1705,15 @@ int myldap_passwd( } return rc; } + +int myldap_modify(MYLDAP_SESSION *session,const char *dn,LDAPMod *mods[]) +{ + int rc; + if (!is_valid_session(session)||(dn==NULL)) + { + log_log(LOG_ERR,"myldap_passwd(): invalid parameter passed"); + errno=EINVAL; + return LDAP_OTHER; + } + return ldap_modify_ext_s(session->ld,dn,mods,NULL,NULL); +} diff --git a/nslcd/myldap.h b/nslcd/myldap.h index f7df4a3..e0fe688 100644 --- a/nslcd/myldap.h +++ b/nslcd/myldap.h @@ -139,9 +139,12 @@ MUST_USE int myldap_escape(const char *src,char *buffer,size_t buflen); /* Set the debug level globally. Returns an LDAP status code. */ int myldap_set_debuglevel(int i); -/* Perform an EXOP password modification call. */ +/* Perform an EXOP password modification call. Returns an LDAP status code. */ int myldap_passwd( MYLDAP_SESSION *session, const char *userdn,const char *oldpassword,const char *newpasswd); +/* Perform an LDAP modification request. Returns an LDAP status code. */ +int myldap_modify(MYLDAP_SESSION *session,const char *dn,LDAPMod *mods[]); + #endif /* not NSLCD__MYLDAP_H */ diff --git a/nslcd/pam.c b/nslcd/pam.c index f6d3877..5c1d0a8 100644 --- a/nslcd/pam.c +++ b/nslcd/pam.c @@ -457,6 +457,11 @@ static int try_pwmod(const char *binddn,const char *userdn, oldpassword=NULL; /* perform password modification */ rc=myldap_passwd(session,userdn,oldpassword,newpassword); + if (rc==LDAP_SUCCESS) + { + /* try to update the shadowLastChange attribute */ + (void)update_lastchange(session,userdn); + } } /* close the session */ myldap_session_close(session); diff --git a/nslcd/shadow.c b/nslcd/shadow.c index a5c4a6d..55013d7 100644 --- a/nslcd/shadow.c +++ b/nslcd/shadow.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include "common.h" #include "log.h" @@ -169,6 +170,71 @@ static long to_date(const char *date,const char *attr) tmpvalue=""; \ var=to_date(tmpvalue,attmap_shadow_##att); +/* try to update the shadowLastChange attribute of the entry if possible */ +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[80],*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 set 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,"modification of %s attribute of %s failed: %s", + attr,userdn,ldap_err2string(rc)); + else + log_log(LOG_DEBUG,"modification of %s attribute of %s succeeded", + attr,userdn); + return rc; +} + static int write_shadow(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser) { int32_t tmpint32; |