summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2009-05-29 20:45:24 +0000
committerArthur de Jong <arthur@arthurdejong.org>2009-05-29 20:45:24 +0000
commitf3cb132262e62c97e0a63e2052a5490c5c418918 (patch)
tree84483505114b2b5849af9c37a1d8453167bb75a7
parent0f632a6a86d0bafe0219919af2aeceb1fdc9c047 (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.h3
-rw-r--r--nslcd/myldap.c13
-rw-r--r--nslcd/myldap.h3
-rw-r--r--nslcd/pam.c58
-rw-r--r--nslcd/passwd.c27
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 */