auth_ldap realm specific configuration

John Newbigin <[email protected]>
Newsgroups gmane.comp.security.cyrus.sasl
Message-ID <[email protected]>
Hi,

Attached is my patch which implements multiple realm support for 
saslauthd ldap. I have updated it to work with cyrus-sasl-2.1.26.

It also adds error checking & logging to the ldap config file parser.

John.

-- 
John Newbigin | ITS Senior Analyst / Programmer
Faculty of Information and Communication Technologies
ITS | Swinburne University of Technology | Melbourne, Australia
O: EN306 | T: +61 3 9214 8185 | M: +61 410 569 362
E: [email protected]
W: http://www.ict.swin.edu.au/staff/jnewbigin
cyrus-sasl-2.1.26-ldap-multiple-realm.patch (text/x-patch, 7.7 KB)
diff -r -u cyrus-sasl-2.1.26.orig/saslauthd/lak.c cyrus-sasl-2.1.26/saslauthd/lak.c
--- cyrus-sasl-2.1.26.orig/saslauthd/lak.c	2012-10-13 01:05:48.000000000 +1100
+++ cyrus-sasl-2.1.26/saslauthd/lak.c	2013-01-16 12:02:39.936208639 +1100
@@ -77,7 +77,8 @@
 	void *rock;
 } LAK_PASSWORD_SCHEME;
 
-static int lak_config_read(LAK_CONF *, const char *);
+static int lak_config_read(LAK_CONF *, const char *, const char *);
+static void lak_config_error(const int, const char *, const char *);
 static int lak_config_int(const char *);
 static int lak_config_switch(const char *);
 static void lak_config_free(LAK_CONF *);
@@ -137,14 +138,28 @@
 #define ISSET(x)  ((x != NULL) && (*(x) != '\0'))
 #define EMPTY(x)  ((x == NULL) || (*(x) == '\0'))
 
+static void lak_config_error(
+	const int lineno,
+	const char *key, 
+	const char *value)
+{
+   	syslog(LOG_ERR|LOG_AUTH,
+	   "Error in saslauthd config file on line %d: %s is not a valid value for %s",
+	   lineno,
+	   value,
+	   key);
+}
+
 static int lak_config_read(
 	LAK_CONF *conf,
-	const char *configfile)
+	const char *configfile,
+	const char *configrealm)
 {
 	FILE *infile;
 	int lineno = 0;
 	char buf[4096];
 	char *p, *key;
+	int in_realm = 1;
 
 	infile = fopen(configfile, "r");
 	if (!infile) {
@@ -170,6 +185,11 @@
 			p++;
 		}
 		if (*p != ':') {
+			syslog(LOG_ERR|LOG_AUTH,
+				"Error in saslauthd config file on line %d: %s does not have a value",
+				lineno,
+				key);
+
 			fclose(infile);
 			return LAK_FAIL;
 		}
@@ -180,11 +200,28 @@
 			p++;
 
 		if (!*p) {
+			syslog(LOG_ERR|LOG_AUTH,
+				"Error in saslauthd config file on line %d: %s does not have a value",
+				lineno,
+				key);
+
 			fclose(infile);
 			return LAK_FAIL;
 		}
 
-		if (!strcasecmp(key, "ldap_servers"))
+		if (!strcasecmp(key, "realm")) {
+			if(!strcasecmp(p, configrealm)) {
+				in_realm = 1;
+			} else {
+				in_realm = 0;
+			}
+		}
+		if(!in_realm)
+			continue;
+
+		if (!strcasecmp(key, "realm")) {
+			
+		} else if (!strcasecmp(key, "ldap_servers"))
 			strlcpy(conf->servers, p, LAK_URL_LEN);
 
 		else if (!strcasecmp(key, "ldap_bind_dn"))
@@ -223,12 +260,22 @@
 				conf->group_scope = LDAP_SCOPE_ONELEVEL;
 			} else if (!strcasecmp(p, "base")) {
 				conf->group_scope = LDAP_SCOPE_BASE;
+			} else if (!strcasecmp(p, "sub")) {
+				conf->group_scope = LDAP_SCOPE_SUB;
+			} else {
+				lak_config_error(lineno, key, p);
+				fclose(infile);
+				return LAK_FAIL;
 			}
 		} else if (!strcasecmp(key, "ldap_group_match_method")) {
 			if (!strcasecmp(p, "filter")) {
 				conf->group_match_method = LAK_GROUP_MATCH_METHOD_FILTER;
 			} else if (!strcasecmp(p, "attr")) {
 				conf->group_match_method = LAK_GROUP_MATCH_METHOD_ATTR;
+			} else {
+				lak_config_error(lineno, key, p);
+				fclose(infile);
+				return LAK_FAIL;
 			}
 		} else if (!strcasecmp(key, "ldap_default_realm") ||
 		         !strcasecmp(key, "ldap_default_domain"))
@@ -239,6 +286,12 @@
 				conf->auth_method = LAK_AUTH_METHOD_CUSTOM;
 			} else if (!strcasecmp(p, "fastbind")) {
 				conf->auth_method = LAK_AUTH_METHOD_FASTBIND;
+			} else if (!strcasecmp(p, "bind")) {
+				conf->auth_method = LAK_AUTH_METHOD_BIND;
+			} else {
+				lak_config_error(lineno, key, p);
+				fclose(infile);
+				return LAK_FAIL;
 			}
 		} else if (!strcasecmp(key, "ldap_timeout")) {
 			conf->timeout.tv_sec = lak_config_int(p);
@@ -258,6 +311,10 @@
 				conf->deref = LDAP_DEREF_ALWAYS;
 			} else if (!strcasecmp(p, "never")) {
 				conf->deref = LDAP_DEREF_NEVER;
+			} else {
+				lak_config_error(lineno, key, p);
+				fclose(infile);
+				return LAK_FAIL;
 			}
 		} else if (!strcasecmp(key, "ldap_referrals")) {
 			conf->referrals = lak_config_switch(p);
@@ -270,6 +327,12 @@
 				conf->scope = LDAP_SCOPE_ONELEVEL;
 			} else if (!strcasecmp(p, "base")) {
 				conf->scope = LDAP_SCOPE_BASE;
+			} else if (!strcasecmp(p, "sub")) {
+				conf->scope = LDAP_SCOPE_SUB;
+			} else {
+				lak_config_error(lineno, key, p);
+				fclose(infile);
+				return LAK_FAIL;
 			}
 		} else if (!strcasecmp(key, "ldap_use_sasl")) {
 			conf->use_sasl = lak_config_switch(p);
@@ -316,6 +379,14 @@
 
 		else if (!strcasecmp(key, "ldap_debug"))
 			conf->debug = lak_config_int(p);
+		else {
+	    	syslog(LOG_ERR|LOG_AUTH,
+			   "Error in saslauthd config file on line %d: Unknown key %s",
+			   lineno,
+			   key);
+			fclose(infile);
+			return LAK_FAIL;
+		}
 	}
 
 	if (conf->version != LDAP_VERSION3 && 
@@ -396,7 +467,7 @@
 
 	strlcpy(conf->path, configfile, LAK_PATH_LEN);
 
-	rc = lak_config_read(conf, conf->path);
+	rc = lak_config_read(conf, conf->path, "");
 	if (rc != LAK_OK) {
 		lak_config_free(conf);
 		return rc;
@@ -1533,8 +1604,21 @@
 	if (EMPTY(user))
 		return LAK_FAIL;
 
-	if (EMPTY(realm))
+	if (EMPTY(realm)) {
 		realm = lak->conf->default_realm;
+	}
+
+
+	if(strcmp(lak->realm, realm) != 0) {
+		syslog(LOG_DEBUG|LOG_AUTH, "lak_authenticate for realm %s", realm);
+		strlcpy(lak->realm, realm, LAK_BUF_LEN);
+		lak_unbind(lak);
+		rc = lak_config_read(lak->conf, lak->conf->path, realm);
+		if (rc != LAK_OK) {
+			syslog(LOG_ERR|LOG_AUTH, "lak_authenticate error reading config for realm %s", realm);
+			return LAK_FAIL;
+		}
+	}
 
 	for (i = 0; authenticator[i].method != -1; i++) {
 		if (authenticator[i].method == lak->conf->auth_method) {
Only in cyrus-sasl-2.1.26/saslauthd: lak.c.orig
diff -r -u cyrus-sasl-2.1.26.orig/saslauthd/lak.h cyrus-sasl-2.1.26/saslauthd/lak.h
--- cyrus-sasl-2.1.26.orig/saslauthd/lak.h	2012-01-28 10:31:36.000000000 +1100
+++ cyrus-sasl-2.1.26/saslauthd/lak.h	2013-01-16 12:02:39.940327523 +1100
@@ -122,6 +122,7 @@
     char      status;
     LAK_USER *user;
     LAK_CONF *conf;
+    char realm[LAK_BUF_LEN];
 } LAK;
 
 typedef struct lak_result {
diff -r -u cyrus-sasl-2.1.26.orig/saslauthd/LDAP_SASLAUTHD cyrus-sasl-2.1.26/saslauthd/LDAP_SASLAUTHD
--- cyrus-sasl-2.1.26.orig/saslauthd/LDAP_SASLAUTHD	2012-01-28 10:31:36.000000000 +1100
+++ cyrus-sasl-2.1.26/saslauthd/LDAP_SASLAUTHD	2013-01-16 12:02:53.497208688 +1100
@@ -8,11 +8,11 @@
 2. Start saslauthd with ldap
 3. Testing
 4. Parameters
-5. Examples
-6. Notes
-7. Todo
-8. Feedback
+5. Notes
+6. Todo
+7. Feedback
 8. Author
+9. Realm specific parameters
 
 
 1. BUILD SASLAUTHD WITH LDAP SUPPORT
@@ -291,3 +291,44 @@
 ---------
 
 Igor Brezac <[email protected]>.
+
+
+9. REALM SPECIFIC PARAMETERS
+----------------------------
+
+This feature was added by John Newbigin <[email protected]>
+
+If you wish to use the supplied realm for more than just a search filter
+you can use a new configuration parameter called realm to identify the
+values that apply for that realm.
+
+In you config file, first list gloabl options which apply to all realms.
+
+Then for each realm which needs specific options, add
+realm: <realm_name>
+and then the parameters which apply.
+
+For example, if you have an OID and eDirectory which use different servers
+and search options you could do this:
+
+ldap_timeout: 10
+
+realm: oid
+ldap_servers: ldap://oidserver.company.com/
+ldap_auth_method: fastbind
+ldap_filter: cn=%u,cn=Users,dc=company,dc=com
+ldap_scope: one
+ldap_search_base: cn=Users,dc=company,dc=com
+
+realm: edirectory
+ldap_servers: ldap://ndsserver.company.com/
+ldap_filter: (cn=%u)
+# sub is the default and with the new error checking
+# it can't be specified like this
+#ldap_scope: sub
+ldap_search_base: o=company
+
+I have also added error checking when reading the config file. Invalid lines,
+unknown keys and unknown enumerated values are now rejected and an error logged.
+If your config file has errors which you never knew about you must now fix them.
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.