diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2009-05-29 20:45:24 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2009-05-29 20:45:24 +0000 |
commit | f3cb132262e62c97e0a63e2052a5490c5c418918 (patch) | |
tree | 84483505114b2b5849af9c37a1d8453167bb75a7 | |
parent | 0f632a6a86d0bafe0219919af2aeceb1fdc9c047 (diff) |
normalize username with PAM authentication and some reorganisation to make that easier
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@901 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | nslcd/common.h | 3 | ||||
-rw-r--r-- | nslcd/myldap.c | 13 | ||||
-rw-r--r-- | nslcd/myldap.h | 3 | ||||
-rw-r--r-- | nslcd/pam.c | 58 | ||||
-rw-r--r-- | nslcd/passwd.c | 27 |
5 files changed, 69 insertions, 35 deletions
diff --git a/nslcd/common.h b/nslcd/common.h index 0fcf7f7..1086f5d 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -86,6 +86,9 @@ MUST_USE char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn,int *rcp); /* transforms the DN info a uid doing an LDAP lookup if needed */ MUST_USE char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen); +/* use the user id to lookup an LDAP entry */ +MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid); + /* 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); diff --git a/nslcd/myldap.c b/nslcd/myldap.c index 2afb8af..74dc822 100644 --- a/nslcd/myldap.c +++ b/nslcd/myldap.c @@ -1206,6 +1206,19 @@ const char *myldap_get_dn(MYLDAP_ENTRY *entry) return entry->dn; } +char *myldap_cpy_dn(MYLDAP_ENTRY *entry,char *buf,size_t buflen) +{ + const char *dn; + /* get the dn */ + dn=myldap_get_dn(entry); + /* copy into buffer */ + if (strlen(dn)<buflen) + strcpy(buf,dn); + else + buf=NULL; + return buf; +} + /* Return a buffer that is an a list of strings that can be freed with a single call to free(). This function frees the set. */ static char **set2values(SET *set) diff --git a/nslcd/myldap.h b/nslcd/myldap.h index c990e86..a83a86a 100644 --- a/nslcd/myldap.h +++ b/nslcd/myldap.h @@ -104,6 +104,9 @@ MUST_USE MYLDAP_ENTRY *myldap_get_entry(MYLDAP_SEARCH *search,int *rcp); "unknown" is returned). */ MUST_USE const char *myldap_get_dn(MYLDAP_ENTRY *entry); +/* Just like myldap_get_dn() but copies the result into the buffer. */ +char *myldap_cpy_dn(MYLDAP_ENTRY *entry,char *buf,size_t buflen); + /* Get the attribute values from a certain entry as a NULL terminated list. May return NULL or an empty array. */ MUST_USE const char **myldap_get_values(MYLDAP_ENTRY *entry,const char *attr); diff --git a/nslcd/pam.c b/nslcd/pam.c index 72a7b71..ea4a6ea 100644 --- a/nslcd/pam.c +++ b/nslcd/pam.c @@ -33,6 +33,7 @@ #include "log.h" #include "myldap.h" #include "cfg.h" +#include "attmap.h" /* set up a connection and try to bind with the specified DN and password returns a NSLCD_PAM_* error code */ @@ -67,6 +68,35 @@ static int try_bind(const char *userdn,const char *password) } } +/* Ensure that both userdn and username are set and are valid. This returns + */ +static int validate_entry(MYLDAP_ENTRY *entry,char *userdn,size_t userdnsz, + char *username,size_t usernamesz) +{ + const char *value; + /* get the DN */ + myldap_cpy_dn(entry,userdn,userdnsz); + if (strcasecmp(userdn,"unknown")==0) + { + log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): user has no DN",username); + return -1; + } + /* get the "real" username */ + value=myldap_get_rdn_value(entry,attmap_passwd_uid); + if ((value==NULL)||!isvalidname(value)||strlen(value)>=usernamesz) + { + log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): DN %s has invalid username",username,userdn); + return -1; + } + /* compare */ + if (strcmp(username,value)!=0) + { + log_log(LOG_INFO,"username changed from \"%s\" to \"%s\"",username,value); + strcpy(username,value); + } + return 0; +} + /* check authentication credentials of the user */ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session) { @@ -76,6 +106,7 @@ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session) char userdn[256]; char servicename[64]; char password[64]; + MYLDAP_ENTRY *entry=NULL; /* read request parameters */ READ_STRING(fp,username); READ_STRING(fp,userdn); @@ -90,30 +121,21 @@ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session) if (!isvalidname(username)) { log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): invalid user name",username); - /* write a response message anyway */ - /* TODO: maybe just write NSLCD_RESULT_END to indicate failure */ - WRITE_INT32(fp,NSLCD_RESULT_BEGIN); - WRITE_STRING(fp,username); - WRITE_STRING(fp,userdn); - WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authc */ - WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */ - WRITE_STRING(fp,"invalid username"); /* authzmsg */ WRITE_INT32(fp,NSLCD_RESULT_END); return -1; } if (userdn[0]=='\0') { - /* perform username to DN translation */ - if (uid2dn(session,username,userdn,sizeof(userdn))==NULL) + /* get the user entry */ + entry=uid2entry(session,username); + if (entry==NULL) { log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): user not found",username); - /* return error to client */ - WRITE_INT32(fp,NSLCD_RESULT_BEGIN); - WRITE_STRING(fp,username); - WRITE_STRING(fp,userdn); - WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authc */ - WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */ - WRITE_STRING(fp,"unknown username"); /* authzmsg */ + WRITE_INT32(fp,NSLCD_RESULT_END); + return -1; + } + if (validate_entry(entry,userdn,sizeof(userdn),username,sizeof(username))) + { WRITE_INT32(fp,NSLCD_RESULT_END); return -1; } @@ -122,7 +144,7 @@ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session) rc=try_bind(userdn,password); /* write response */ WRITE_INT32(fp,NSLCD_RESULT_BEGIN); - WRITE_STRING(fp,username); /* TODO: get canonical name */ + WRITE_STRING(fp,username); WRITE_STRING(fp,userdn); WRITE_INT32(fp,rc); /* authc */ WRITE_INT32(fp,rc); /* authz */ diff --git a/nslcd/passwd.c b/nslcd/passwd.c index 2b80de3..068ba9c 100644 --- a/nslcd/passwd.c +++ b/nslcd/passwd.c @@ -246,13 +246,11 @@ char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen) return buf; } -char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen) +MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid) { MYLDAP_SEARCH *search; - MYLDAP_ENTRY *entry; static const char *attrs[1]; int rc; - const char *dn; char filter[1024]; /* if it isn't a valid username, just bail out now */ if (!isvalidname(uid)) @@ -266,23 +264,18 @@ char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen) search=myldap_search(session,passwd_base,passwd_scope,filter,attrs); if (search==NULL) return NULL; - entry=myldap_get_entry(search,&rc); + return myldap_get_entry(search,&rc); +} + +char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen) +{ + MYLDAP_ENTRY *entry; + /* look up the entry */ + entry=uid2entry(session,uid); if (entry==NULL) return NULL; /* get DN */ - dn=myldap_get_dn(entry); - if (strcasecmp(dn,"unknown")==0) - { - myldap_search_close(search); - return NULL; - } - /* copy into buffer */ - if (strlen(dn)<buflen) - strcpy(buf,dn); - else - buf=NULL; - myldap_search_close(search); - return buf; + return myldap_cpy_dn(entry,buf,buflen); } /* the maximum number of uidNumber attributes per entry */ |