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


--- 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;

Reply via email to