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;