Blob Blame History Raw
diff --git a/lib/imapoptions b/lib/imapoptions
index 464de37..98e0341 100644
--- a/lib/imapoptions
+++ b/lib/imapoptions
@@ -483,6 +483,9 @@ Blank lines and lines beginning with ``#'' are ignored.
 { "ldap_mech", NULL, STRING }
 /* SASL mechanism for LDAP authentication */
 
+{ "ldap_user_attribute", NULL, STRING }
+/* Specify LDAP attribute to use as canonical user id */
+
 { "ldap_member_attribute", NULL, STRING }
 /* See ldap_member_method. */
 
diff --git a/ptclient/ldap.c b/ptclient/ldap.c
index 7bd8664..b3507d1 100644
--- a/ptclient/ldap.c
+++ b/ptclient/ldap.c
@@ -158,6 +158,7 @@ typedef struct _ptsm {
     const char   *tls_cert;
     const char   *tls_key;
     int    member_method;
+    const char   *user_attribute;
     const char   *member_attribute;
     const char   *member_filter;
     const char   *member_base;
@@ -508,6 +509,8 @@ static void myinit(void)
     ptsm->member_base = config_getstring(IMAPOPT_LDAP_MEMBER_BASE);
     ptsm->member_attribute = (config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE) ?
         config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE) : config_getstring(IMAPOPT_LDAP_MEMBER_ATTRIBUTE));
+    ptsm->user_attribute = (config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE) ?
+        config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE) : config_getstring(IMAPOPT_LDAP_USER_ATTRIBUTE));
     p = config_getstring(IMAPOPT_LDAP_GROUP_SCOPE);
     if (!strcasecmp(p, "one")) {
         ptsm->group_scope = LDAP_SCOPE_ONELEVEL;
@@ -790,7 +793,7 @@ static int ptsmodule_get_dn(
     char *authzid;
 #endif
     char *base = NULL, *filter = NULL;
-    char *attrs[] = {NULL};
+    char *attrs[] = {LDAP_NO_ATTRS,NULL}; //do not return all attrs!
     LDAPMessage *res;
     LDAPMessage *entry;
     char *attr, **vals;
@@ -887,8 +890,9 @@ static int ptsmodule_make_authstate_attribute(
     LDAPMessage *res = NULL;
     LDAPMessage *entry = NULL;
     char **vals = NULL;
+    char **rdn = NULL;
     int rc;
-    char *attrs[] = {(char *)ptsm->member_attribute,NULL};
+    char *attrs[] = {(char *)ptsm->member_attribute,(char *)ptsm->user_attribute,NULL};
 
     rc = ptsmodule_connect();
     if (rc != PTSM_OK) {
@@ -915,37 +919,69 @@ static int ptsmodule_make_authstate_attribute(
     }
 
     if ((entry = ldap_first_entry(ptsm->ld, res)) != NULL) {
-	int i, numvals;
-
-	vals = ldap_get_values(ptsm->ld, entry, (char *)ptsm->member_attribute);
-	if (vals != NULL) {
-	    numvals = ldap_count_values( vals );
-
-	    *dsize = sizeof(struct auth_state) +
-		     (numvals * sizeof(struct auth_ident));
-	    *newstate = xmalloc(*dsize);
-	    if (*newstate == NULL) {
-		*reply = "no memory";
-		rc = PTSM_FAIL;
-		goto done;
-	    }
-	    (*newstate)->ngroups = numvals;
-
-	    for (i = 0; i < numvals; i++) {
-		int j;
-		strcpy((*newstate)->groups[i].id, "group:");
-		for(j =0; j < strlen(vals[i]); j++) {
-		  if(Uisupper(vals[i][j]))
-		    vals[i][j]=tolower(vals[i][j]);
-		}
-		strlcat((*newstate)->groups[i].id, vals[i], 
-		    sizeof((*newstate)->groups[i].id));
-		(*newstate)->groups[i].hash = strhash((*newstate)->groups[i].id);
-	    }
-
-	    ldap_value_free(vals);
-	    vals = NULL;
-	}
+    int i, numvals;
+
+    vals = ldap_get_values(ptsm->ld, entry, (char *)ptsm->member_attribute);
+    if (vals != NULL) {
+        numvals = ldap_count_values( vals );
+
+        *dsize = sizeof(struct auth_state) +
+             (numvals * sizeof(struct auth_ident));
+        *newstate = xmalloc(*dsize);
+        if (*newstate == NULL) {
+            *reply = "no memory";
+            rc = PTSM_FAIL;
+            goto done;
+        }
+
+        (*newstate)->ngroups = numvals;
+        (*newstate)->userid.id[0] = '\0';
+        for (i = 0; i < numvals; i++) {
+            int j;
+            strcpy((*newstate)->groups[i].id, "group:");
+            rdn = ldap_explode_rdn(vals[i],1);
+            for (j = 0; j < strlen(rdn[0]); j++) {
+              if (Uisupper(rdn[0][j]))
+                  rdn[0][j]=tolower(rdn[0][j]);
+            }
+            strlcat((*newstate)->groups[i].id, rdn[0],
+                sizeof((*newstate)->groups[i].id));
+            (*newstate)->groups[i].hash = strhash((*newstate)->groups[i].id);
+        }
+
+        ldap_value_free(rdn);
+        ldap_value_free(vals);
+        vals = NULL;
+    }
+
+    if ((char *)ptsm->user_attribute) {
+        vals = ldap_get_values(ptsm->ld, entry, (char *)ptsm->user_attribute);
+        if (vals != NULL) {
+            numvals = ldap_count_values( vals );
+
+                if (numvals==1) {
+                    if(!*newstate) {
+                        *dsize = sizeof(struct auth_state);
+                        *newstate = xmalloc(*dsize);
+
+                        if (*newstate == NULL) {
+                            *reply = "no memory";
+                            rc = PTSM_FAIL;
+                            goto done;
+                        }
+
+                        (*newstate)->ngroups = 0;
+                    }
+
+                    size=strlen(vals[0]);
+                    strcpy((*newstate)->userid.id, ptsmodule_canonifyid(vals[0],size));
+                    (*newstate)->userid.hash = strhash((*newstate)->userid.id);
+                }
+
+                ldap_value_free(vals);
+                vals = NULL;
+            }
+        }
     }
 
     if(!*newstate) {
@@ -957,11 +993,14 @@ static int ptsmodule_make_authstate_attribute(
             goto done;
         }
         (*newstate)->ngroups = 0;
+        (*newstate)->userid.id[0] = '\0';
     }
-    
+
     /* fill in the rest of our new state structure */
-    strcpy((*newstate)->userid.id, canon_id);
-    (*newstate)->userid.hash = strhash(canon_id);
+    if ((*newstate)->userid.id[0]=='\0') {
+        strcpy((*newstate)->userid.id, canon_id);
+        (*newstate)->userid.hash = strhash(canon_id);
+    }
     (*newstate)->mark = time(0);
 
     rc = PTSM_OK;