[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