changeset 5884:1c1dee40e495 HEAD

Moved generic LDAP result iteration to db_ldap. It also supports now templates in values.
author Timo Sirainen <tss@iki.fi>
date Tue, 03 Jul 2007 05:35:31 +0300
parents 526d1a860b13
children f0685f6ec951
files src/auth/db-ldap.c src/auth/db-ldap.h src/auth/passdb-ldap.c src/auth/userdb-ldap.c
diffstat 4 files changed, 211 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/db-ldap.c	Tue Jul 03 04:43:45 2007 +0300
+++ b/src/auth/db-ldap.c	Tue Jul 03 05:35:31 2007 +0300
@@ -8,6 +8,7 @@
 #include "ioloop.h"
 #include "hash.h"
 #include "str.h"
+#include "var-expand.h"
 #include "settings.h"
 #include "userdb.h"
 #include "db-ldap.h"
@@ -41,6 +42,21 @@
 #  define LDAP_OPT_SUCCESS LDAP_SUCCESS
 #endif
 
+struct db_ldap_result_iterate_context {
+	struct ldap_connection *conn;
+	LDAPMessage *entry;
+	struct auth_request *auth_request;
+
+	struct hash_table *attr_map;
+	struct var_expand_table *var_table;
+
+	char *attr, **vals;
+	const char *name, *value, *template, *val_1_arr[2];
+	BerElement *ber;
+
+	string_t *var, *debug;
+};
+
 #define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
 #define DEF_INT(name) DEF_STRUCT_INT(name, ldap_settings)
 #define DEF_BOOL(name) DEF_STRUCT_BOOL(name, ldap_settings)
@@ -642,6 +658,23 @@
 	t_pop();
 }
 
+struct var_expand_table *
+db_ldap_value_get_var_expand_table(struct auth_request *auth_request)
+{
+	const struct var_expand_table *auth_table;
+	struct var_expand_table *table;
+	unsigned int count;
+
+	auth_table = auth_request_get_var_expand_table(auth_request, NULL);
+	for (count = 0; auth_table[count].key != '\0'; count++) ;
+	count++;
+
+	table = t_new(struct var_expand_table, count + 1);
+	table[0].key = '$';
+	memcpy(table + 1, auth_table, sizeof(*table) * count);
+	return table;
+}
+
 #define IS_LDAP_ESCAPED_CHAR(c) \
 	((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
 
@@ -670,6 +703,149 @@
 	return str_c(ret);
 }
 
+struct db_ldap_result_iterate_context *
+db_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
+			    struct auth_request *auth_request,
+			    struct hash_table *attr_map)
+{
+	struct db_ldap_result_iterate_context *ctx;
+
+	ctx = t_new(struct db_ldap_result_iterate_context, 1);
+	ctx->conn = conn;
+	ctx->entry = entry;
+	ctx->auth_request = auth_request;
+	ctx->attr_map = attr_map;
+
+	if (auth_request->auth->verbose_debug)
+		ctx->debug = t_str_new(256);
+
+	ctx->attr = ldap_first_attribute(conn->ld, entry, &ctx->ber);
+	return ctx;
+}
+
+static void
+db_ldap_result_iterate_finish(struct db_ldap_result_iterate_context *ctx)
+{
+	if (ctx->debug != NULL && str_len(ctx->debug) > 0) {
+		auth_request_log_debug(ctx->auth_request, "ldap",
+				       "result: %s", str_c(ctx->debug) + 1);
+	}
+
+	ber_free(ctx->ber, 0);
+}
+
+static void
+db_ldap_result_change_attr(struct db_ldap_result_iterate_context *ctx)
+{
+	ctx->name = hash_lookup(ctx->attr_map, ctx->attr);
+
+	if (ctx->debug != NULL) {
+		str_printfa(ctx->debug, " %s(%s)=", ctx->attr,
+			    ctx->name != NULL ? ctx->name : "?unknown?");
+	}
+
+	if (ctx->name == NULL || *ctx->name == '\0') {
+		ctx->value = NULL;
+		return;
+	}
+
+	if (strchr(ctx->name, '%') != NULL &&
+	    (ctx->template = strchr(ctx->name, '=')) != NULL) {
+		/* we want to use variables */
+		ctx->name = t_strdup_until(ctx->name, ctx->template);
+		ctx->template++;
+		if (ctx->var_table == NULL) {
+			ctx->var_table = db_ldap_value_get_var_expand_table(
+							ctx->auth_request);
+			ctx->var = t_str_new(256);
+		}
+	}
+
+	ctx->vals = ldap_get_values(ctx->conn->ld, ctx->entry,
+				    ctx->attr);
+	ctx->value = ctx->vals[0];
+}
+
+static void
+db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
+{
+	bool first = ctx->value == ctx->vals[0];
+
+	if (ctx->template != NULL) {
+		ctx->var_table[0].value = ctx->value;
+		str_truncate(ctx->var, 0);
+		var_expand(ctx->var, ctx->template, ctx->var_table);
+		ctx->value = str_c(ctx->var);
+	}
+
+	if (ctx->debug != NULL) {
+		if (!first)
+			str_append_c(ctx->debug, '/');
+		if (ctx->auth_request->auth->verbose_debug_passwords ||
+		    strcmp(ctx->name, "password") != 0)
+			str_append(ctx->debug, ctx->value);
+		else
+			str_append(ctx->debug, PASSWORD_HIDDEN_STR);
+	}
+}
+
+static bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
+{
+	while (ctx->attr != NULL) {
+		if (ctx->vals == NULL) {
+			/* a new attribute */
+			db_ldap_result_change_attr(ctx);
+		} else {
+			/* continuing existing attribute */
+			if (ctx->value != NULL)
+				ctx->value++;
+		}
+
+		if (ctx->value != NULL) {
+			db_ldap_result_return_value(ctx);
+			return TRUE;
+		}
+
+		ldap_value_free(ctx->vals); ctx->vals = NULL;
+		ldap_memfree(ctx->attr);
+		ctx->attr = ldap_next_attribute(ctx->conn->ld, ctx->entry,
+						ctx->ber);
+	}
+
+	db_ldap_result_iterate_finish(ctx);
+	return FALSE;
+}
+
+bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
+				 const char **name_r, const char **value_r)
+{
+	if (!db_ldap_result_int_next(ctx))
+		return FALSE;
+
+	*name_r = ctx->name;
+	*value_r = ctx->value;
+	return TRUE;
+}
+
+bool db_ldap_result_iterate_next_all(struct db_ldap_result_iterate_context *ctx,
+				     const char **name_r,
+				     const char *const **values_r)
+{
+	if (!db_ldap_result_int_next(ctx))
+		return FALSE;
+
+	if (ctx->template != NULL) {
+		/* we can use only one value with templates */
+		ctx->val_1_arr[0] = ctx->value;
+		*values_r = ctx->val_1_arr;
+	} else {
+		*values_r = (const char *const *)ctx->vals;
+	}
+	ctx->value = NULL;
+	*name_r = ctx->name;
+	return TRUE;
+}
+
 static const char *parse_setting(const char *key, const char *value,
 				 struct ldap_connection *conn)
 {
--- a/src/auth/db-ldap.h	Tue Jul 03 04:43:45 2007 +0300
+++ b/src/auth/db-ldap.h	Tue Jul 03 05:35:31 2007 +0300
@@ -107,8 +107,21 @@
 
 int db_ldap_connect(struct ldap_connection *conn);
 
+struct var_expand_table *
+db_ldap_value_get_var_expand_table(struct auth_request *auth_request);
+
 const char *ldap_escape(const char *str,
 			const struct auth_request *auth_request);
 const char *ldap_get_error(struct ldap_connection *conn);
 
+struct db_ldap_result_iterate_context *
+db_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
+			    struct auth_request *auth_request,
+			    struct hash_table *attr_map);
+bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
+				 const char **name_r, const char **value_r);
+bool db_ldap_result_iterate_next_all(struct db_ldap_result_iterate_context *ctx,
+				     const char **name_r,
+				     const char *const **values_r);
+
 #endif
--- a/src/auth/passdb-ldap.c	Tue Jul 03 04:43:45 2007 +0300
+++ b/src/auth/passdb-ldap.c	Tue Jul 03 05:35:31 2007 +0300
@@ -34,87 +34,6 @@
 	} callback;
 };
 
-struct ldap_query_save_context {
-	struct ldap_connection *conn;
-	struct auth_request *auth_request;
-	LDAPMessage *entry;
-
-	string_t *debug;
-};
-
-static void
-ldap_query_save_attr(struct ldap_query_save_context *ctx, const char *attr)
-{
-	struct auth *auth = ctx->auth_request->auth;
-	const char *name;
-	char **vals;
-	unsigned int i;
-
-	name = hash_lookup(ctx->conn->pass_attr_map, attr);
-
-	if (auth->verbose_debug) {
-		if (ctx->debug == NULL)
-			ctx->debug = t_str_new(256);
-		else
-			str_append_c(ctx->debug, ' ');
-		str_append(ctx->debug, attr);
-		str_printfa(ctx->debug, "(%s)=",
-			    name != NULL ? name : "?unknown?");
-	}
-
-	if (name == NULL)
-		return;
-
-	vals = ldap_get_values(ctx->conn->ld, ctx->entry, attr);
-	if (vals != NULL && *name != '\0') {
-		for (i = 0; vals[i] != NULL; i++) {
-			if (ctx->debug != NULL) {
-				if (i != 0)
-					str_append_c(ctx->debug, '/');
-				if (auth->verbose_debug_passwords ||
-				    strcmp(name, "password") != 0)
-					str_append(ctx->debug, vals[i]);
-				else {
-					str_append(ctx->debug,
-						   PASSWORD_HIDDEN_STR);
-				}
-			}
-			auth_request_set_field(ctx->auth_request, name, vals[i],
-					ctx->conn->set.default_pass_scheme);
-		}
-	}
-
-	ldap_value_free(vals);
-}
-
-static void
-ldap_query_save_result(struct ldap_connection *conn, LDAPMessage *entry,
-		       struct auth_request *auth_request)
-{
-	struct ldap_query_save_context ctx;
-	BerElement *ber;
-	char *attr;
-
-	memset(&ctx, 0, sizeof(ctx));
-	ctx.conn = conn;
-	ctx.auth_request = auth_request;
-	ctx.entry = entry;
-
-	attr = ldap_first_attribute(conn->ld, entry, &ber);
-	while (attr != NULL) {
-		ldap_query_save_attr(&ctx, attr);
-		ldap_memfree(attr);
-
-		attr = ldap_next_attribute(conn->ld, entry, ber);
-	}
-	ber_free(ber, 0);
-
-	if (ctx.debug != NULL) {
-		auth_request_log_debug(auth_request, "ldap",
-				       "result: %s", str_c(ctx.debug));
-	}
-}
-
 static LDAPMessage *
 handle_request_get_entry(struct ldap_connection *conn,
 			 struct auth_request *auth_request,
@@ -159,6 +78,21 @@
 	return NULL;
 }
 
+static void
+ldap_query_save_result(struct ldap_connection *conn,
+		       LDAPMessage *entry, struct auth_request *auth_request)
+{
+	struct db_ldap_result_iterate_context *ldap_iter;
+	const char *name, *value;
+
+	ldap_iter = db_ldap_result_iterate_init(conn, entry, auth_request,
+						conn->pass_attr_map);
+	while (db_ldap_result_iterate_next(ldap_iter, &name, &value)) {
+		auth_request_set_field(auth_request, name, value,
+				       conn->set.default_pass_scheme);
+	}
+}
+
 static void handle_request(struct ldap_connection *conn,
 			   struct ldap_request *request, LDAPMessage *res)
 {
--- a/src/auth/userdb-ldap.c	Tue Jul 03 04:43:45 2007 +0300
+++ b/src/auth/userdb-ldap.c	Tue Jul 03 05:35:31 2007 +0300
@@ -34,27 +34,15 @@
 ldap_query_get_result(struct ldap_connection *conn, LDAPMessage *entry,
 		      struct auth_request *auth_request)
 {
-	BerElement *ber;
-	const char *name;
-	char *attr, **vals;
-
-	auth_request_init_userdb_reply(auth_request);
-
-	attr = ldap_first_attribute(conn->ld, entry, &ber);
-	while (attr != NULL) {
-		name = hash_lookup(conn->user_attr_map, attr);
-		vals = ldap_get_values(conn->ld, entry, attr);
+	struct db_ldap_result_iterate_context *ldap_iter;
+	const char *name, *const *values;
 
-		if (name != NULL && *name != '\0' && vals != NULL) {
-			auth_request_set_userdb_field_values(auth_request,
-					name, (const char *const *)vals);
-		}
-		ldap_value_free(vals);
-		ldap_memfree(attr);
-
-		attr = ldap_next_attribute(conn->ld, entry, ber);
+	ldap_iter = db_ldap_result_iterate_init(conn, entry, auth_request,
+						conn->user_attr_map);
+	while (db_ldap_result_iterate_next_all(ldap_iter, &name, &values)) {
+		auth_request_set_userdb_field_values(auth_request,
+						     name, values);
 	}
-	ber_free(ber, 0);
 }
 
 static void handle_request(struct ldap_connection *conn,