summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2010-12-26 17:09:47 +0000
committerArthur de Jong <arthur@arthurdejong.org>2010-12-26 17:09:47 +0000
commit8eb43e411882e26257c07c32949028bf76e187ec (patch)
treee1196633aa337527f4997af57287b773f3770524
parent1a379549c64ecbdb56c834e935223c991700da7d (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.h3
-rw-r--r--nslcd/myldap.c12
-rw-r--r--nslcd/myldap.h5
-rw-r--r--nslcd/pam.c5
-rw-r--r--nslcd/shadow.c66
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;