[patch]saslauthd+ldap+virtual_domains

Kervin L. Pierre kervin at blueprint-tech.com
Mon Oct 14 15:05:17 EDT 2002


Hi,

attached is a patch to cyrus/saslauthd/lak.c to allow it to expand '%d' 
macro in ldap_search_base option to the domain context derived from the 
realm '%r'.

eg.

ldap_search_base: ou=people, %d
in saslauthd.conf

if realm is 'domain.tld', the ldap search base will expand to 
'ou=people,dc=domain,dc=tld'

Does imapd always provide the realm in a virtual server environment when 
authenticating users?  Is it safe to assume that the realm is 
'domain.tld' or more specifically the domain given to mkimap script?

Is this correct/incorrect/unnecessary?

--Kervin


-------------- next part --------------
--- lak.c.orig	Mon Oct 14 01:15:25 2002
+++ lak.c	Mon Oct 14 14:37:23 2002
@@ -68,11 +68,11 @@
 static int lak_config_getswitch(const char *, int );
 static int lak_config(const char *, LAK_CONF **);
 static int lak_escape(const char *, char **);
-static int lak_filter(LAK *, const char *, const char *, char **);
+static int lak_filter(LAK *, const char *, const char *, const char *, char **);
 static int lak_connect(LAK *);
 static int lak_bind(LAK *, char, const char *, const char *);
 static int lak_init(const char *, LAK **);
-static int lak_search(LAK *, const char *, const char **, LDAPMessage **);
+static int lak_search(LAK *, const char *, const char *, const char **, LDAPMessage **);
 static int lak_retrieve(LAK *, const char *, const char *, const char **, LAK_RESULT **);
 static int lak_auth_custom(LAK *, const char *, const char *, const char *);
 static int lak_auth_bind(LAK *, const char *, const char *, const char *);
@@ -327,45 +327,77 @@
  *   %% = %
  *   %u = user
  *   %r = realm
+ *   %d = realm as a domain context
  * Note: calling function must free memory.
  */
-static int lak_filter(LAK *lak, const char *username, const char *realm, char **result) 
+static int lak_filter(LAK *lak, const char *filter, const char *username, const char *realm, char **result) 
 {
-	char *buf; 
-	char *end, *ptr, *temp;
+	char *buf, *domain_str = NULL; 
+	char *temp;
+	const char *ptr, *end;
 	char *ebuf;
-	int rc;
+	int rc, i,j;
 
 	/* to permit multiple occurences of username and/or realm in filter */
 	/* and avoid memory overflow in filter build [eg: (|(uid=%u)(userid=%u)) ] */
-	int percents, realm_len, user_len, maxparamlength;
+	int percents, realm_len, user_len, domain_len, maxparamlength;
 	
-	if (lak->conf->filter == NULL) {
+	if (filter == NULL) {
 		syslog(LOG_WARNING|LOG_AUTH, "filter not setup");
 		return LAK_FAIL;
 	}
 
-	/* find the longest param of username and realm */
+	/* expand domain only if we have a realm */
+	if( realm!=NULL && strlen(realm)>3)
+	{
+		/* find the size of the domain string */
+		domain_len = 0;
+		for(i=0;i<strlen(realm);i++)
+			if(realm[i]=='.')
+				domain_len++;
+		/* strlen(",dc=") is equal to 4 */
+		/* strlen("dc=") is equal to 3 */
+		domain_len = domain_len*4 + strlen(realm) + 3;
+
+		domain_str=calloc(1,domain_len+1);
+		if(domain_str == NULL) {
+			syslog(LOG_ERR|LOG_AUTH, "Cannot allocate memory");
+			return LAK_NOMEM;
+		}
+
+		strncat(domain_str, "dc=", 3);
+		for(i=0,j=3;i<strlen(realm);i++) {
+			if(realm[i]=='.') {
+				strncat(&domain_str[j], ",dc=", 4);
+				j += 4;
+			}
+			else domain_str[j++] = realm[i];
+		}
+	}
+
+	/* find the longest param of username, realm or domain context*/
 	user_len=strlen(username);
 	realm_len=strlen(realm);
 	if( user_len > realm_len )
 	    maxparamlength = user_len;
 	else
 	    maxparamlength = realm_len;
+	if( maxparamlength < domain_len )
+       	    maxparamlength = domain_len;
 
 	/* find the number of occurences of percent sign in filter */
-	for( percents=0, buf=lak->conf->filter; *buf; buf++ ) {
-		if( *buf == '%' ) percents++;
+	for( i=0,percents=0; i<strlen(filter); i++ ) {
+		if( filter[i] == '%' ) percents++;
 	}
 
-	buf=malloc(strlen(lak->conf->filter) + (percents * maxparamlength) +1);
+	buf=malloc(strlen(filter) + (percents * maxparamlength) +1);
 	if(buf == NULL) {
 		syslog(LOG_ERR|LOG_AUTH, "Cannot allocate memory");
 		return LAK_NOMEM;
 	}
 	buf[0] = '\0';
 	
-	ptr=lak->conf->filter;
+	ptr=filter;
 	end = ptr + strlen(ptr);
 
 	while ((temp=strchr(ptr,'%'))!=NULL ) {
@@ -404,6 +436,18 @@
 					syslog(LOG_WARNING|LOG_AUTH, "Realm not available.");
 				}
 				break;
+			case 'd':
+				if (domain_str!=NULL) {
+					rc = lak_escape(domain_str, &ebuf);
+					if (rc == LAK_OK) {
+						strcat(buf,ebuf);
+						free(ebuf);
+					}
+				} else if (realm) {
+					/* complain only if we have a realm and no domain */
+					syslog(LOG_WARNING|LOG_AUTH, "Domain not available.");
+				}
+				break;
 			default:
 				break;
 		}
@@ -413,6 +457,8 @@
 		strcat(buf, ptr);
 
 	*result = buf;
+	if(domain_str)
+		free(domain_str);
 
 	return LAK_OK;
 }
@@ -610,7 +656,7 @@
 }
 
 
-static int lak_search(LAK *lak, const char *filter, const char **attrs, LDAPMessage **res)
+static int lak_search(LAK *lak, const char *search_base, const char *filter, const char **attrs, LDAPMessage **res)
 {
 	int rc = 0;
 	int retry = 1;
@@ -624,7 +670,7 @@
 		return LAK_FAIL;
 	}
 
-	rc = ldap_search_st(lak->ld, lak->conf->search_base, lak->conf->scope, filter, (char **) attrs, 0, &(lak->conf->timeout), res);
+	rc = ldap_search_st(lak->ld, search_base, lak->conf->scope, filter, (char **) attrs, 0, &(lak->conf->timeout), res);
 	switch (rc) {
 		case LDAP_SUCCESS:
 		case LDAP_SIZELIMIT_EXCEEDED:
@@ -661,6 +707,7 @@
 {
 	int rc = 0;
 	char *filter = NULL;
+	char *search_base = NULL;
 	LDAPMessage *res;
 	LDAPMessage *entry;
 	BerElement *ber;
@@ -668,12 +715,20 @@
     
     	*ret = NULL;
 
-	rc = lak_filter(lak, user, realm, &filter);
+	rc = lak_filter(lak, lak->conf->filter, user, realm, &filter);
 	if (rc != LAK_OK) {
+		syslog(LOG_WARNING|LOG_AUTH, "lak_filter failed for search filter.");
 		return LAK_FAIL;
 	}
 
-	rc = lak_search(lak, filter, attrs, &res);
+	/* expand the search base filter */
+	rc = lak_filter(lak, lak->conf->search_base, user, realm, &search_base);
+	if (rc != LAK_OK) {
+		syslog(LOG_WARNING|LOG_AUTH, "lak_filter failed for search base.");
+		return LAK_FAIL;
+	}
+
+	rc = lak_search(lak, search_base, filter, attrs, &res);
 	if (rc != LAK_OK) {
 		free(filter);
 		return LAK_FAIL;
@@ -749,18 +804,25 @@
 
 static int lak_auth_bind(LAK *lak, const char *user, const char *realm, const char *password) 
 {
-	char *filter;
+	char *filter, *search_base;
 	int rc;
 	char *dn;
 	LDAPMessage *res, *entry;
 
-	rc = lak_filter(lak, user, realm, &filter);
+	rc = lak_filter(lak, lak->conf->filter, user, realm, &filter);
+	if (rc != LAK_OK) {
+		syslog(LOG_WARNING|LOG_AUTH, "lak_filter failed for search filter.");
+		return LAK_FAIL;
+	}
+
+	/* expand the search base filter */
+	rc = lak_filter(lak, lak->conf->search_base, user, realm, &search_base);
 	if (rc != LAK_OK) {
-		syslog(LOG_WARNING|LOG_AUTH, "lak_filter failed.");
+		syslog(LOG_WARNING|LOG_AUTH, "lak_filter failed for search base.");
 		return LAK_FAIL;
 	}
 
-	rc = lak_search(lak, filter, NULL, &res);
+	rc = lak_search(lak, search_base, filter, NULL, &res);
 	if (rc != LAK_OK) {
 		free(filter);
 		return LAK_FAIL;


More information about the Info-cyrus mailing list