changeset 18765:bb1522e10108

auth: Added %{passdb:field} and %{userdb:field} variables The field expands to either the passdb or userdb extra field. You can also use %{passdb:field:defaultvalue} where if field doesn't exist, it's expanded to defaultvalue. Note that an empty value means that the field still exists and it's not expanded to defaultvalue.
author Timo Sirainen <tss@iki.fi>
date Fri, 29 May 2015 21:39:33 +0300
parents fa891f697005
children 8973a5837b48
files src/auth/Makefile.am src/auth/auth-request-var-expand.c src/auth/auth-request-var-expand.h src/auth/auth-request.c src/auth/db-checkpassword.c src/auth/db-passwd-file.c src/auth/passdb-imap.c src/auth/passdb-ldap.c src/auth/passdb-pam.c src/auth/passdb-passwd-file.c src/auth/passdb-sql.c src/auth/passdb-static.c src/auth/passdb-template.c src/auth/test-auth-request-var-expand.c src/auth/userdb-dict.c src/auth/userdb-ldap.c src/auth/userdb-passwd-file.c src/auth/userdb-sql.c src/auth/userdb-template.c
diffstat 19 files changed, 188 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/Makefile.am	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/Makefile.am	Fri May 29 21:39:33 2015 +0300
@@ -211,7 +211,7 @@
 test_auth_cache_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
 
 test_auth_request_var_expand_SOURCES = test-auth-request-var-expand.c
-test_auth_request_var_expand_LDADD = auth-request-var-expand.o $(test_libs)
+test_auth_request_var_expand_LDADD = auth-request-var-expand.o auth-fields.o $(test_libs)
 test_auth_request_var_expand_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
 
 test_db_dict_SOURCES = test-db-dict.c
--- a/src/auth/auth-request-var-expand.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/auth-request-var-expand.c	Fri May 29 21:39:33 2015 +0300
@@ -1,9 +1,15 @@
 /* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
 
 #include "auth-common.h"
+#include "str.h"
 #include "strescape.h"
 #include "auth-request.h"
 
+struct auth_request_var_expand_ctx {
+	struct auth_request *auth_request;
+	auth_request_escape_func_t *escape_func;
+};
+
 const struct var_expand_table
 auth_request_var_expand_static_tab[AUTH_REQUEST_VAR_TAB_COUNT+1] = {
 	{ 'u', NULL, "user" },
@@ -160,3 +166,80 @@
 	return auth_request_get_var_expand_table_full(auth_request, escape_func,
 						      &count);
 }
+
+static const char *field_get_default(const char *data)
+{
+	const char *p;
+
+	p = strchr(data, ':');
+	if (p == NULL)
+		return "";
+	else {
+		/* default value given */
+		return p+1;
+	}
+}
+
+static const char *
+auth_request_var_expand_func_passdb(const char *data, void *context)
+{
+	struct auth_request_var_expand_ctx *ctx = context;
+	const char *field_name = t_strcut(data, ':');
+	const char *value;
+
+	value = auth_fields_find(ctx->auth_request->extra_fields, field_name);
+	return ctx->escape_func(value != NULL ? value : field_get_default(data),
+				ctx->auth_request);
+}
+
+static const char *
+auth_request_var_expand_func_userdb(const char *data, void *context)
+{
+	struct auth_request_var_expand_ctx *ctx = context;
+	const char *field_name = t_strcut(data, ':');
+	const char *value;
+
+	value = ctx->auth_request->userdb_reply == NULL ? NULL :
+		auth_fields_find(ctx->auth_request->userdb_reply, field_name);
+	return ctx->escape_func(value != NULL ? value : field_get_default(data),
+				ctx->auth_request);
+}
+
+const struct var_expand_func_table auth_request_var_funcs_table[] = {
+	{ "passdb", auth_request_var_expand_func_passdb },
+	{ "userdb", auth_request_var_expand_func_userdb },
+	{ NULL, NULL }
+};
+
+void auth_request_var_expand(string_t *dest, const char *str,
+			     struct auth_request *auth_request,
+			     auth_request_escape_func_t *escape_func)
+{
+	auth_request_var_expand_with_table(dest, str, auth_request,
+		auth_request_get_var_expand_table(auth_request, escape_func),
+		escape_func);
+}
+
+void auth_request_var_expand_with_table(string_t *dest, const char *str,
+					struct auth_request *auth_request,
+					const struct var_expand_table *table,
+					auth_request_escape_func_t *escape_func)
+{
+	struct auth_request_var_expand_ctx ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.auth_request = auth_request;
+	ctx.escape_func = escape_func;
+	var_expand_with_funcs(dest, str, table,
+			      auth_request_var_funcs_table, &ctx);
+}
+
+const char *
+t_auth_request_var_expand(const char *str,
+			  struct auth_request *auth_request,
+			  auth_request_escape_func_t *escape_func)
+{
+	string_t *dest = t_str_new(128);
+	auth_request_var_expand(dest, str, auth_request, escape_func);
+	return str_c(dest);
+}
--- a/src/auth/auth-request-var-expand.h	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/auth-request-var-expand.h	Fri May 29 21:39:33 2015 +0300
@@ -20,6 +20,19 @@
 auth_request_get_var_expand_table_full(const struct auth_request *auth_request,
 				       auth_request_escape_func_t *escape_func,
 				       unsigned int *count) ATTR_NULL(2);
+
+void auth_request_var_expand(string_t *dest, const char *str,
+			     struct auth_request *auth_request,
+			     auth_request_escape_func_t *escape_func);
+void auth_request_var_expand_with_table(string_t *dest, const char *str,
+					struct auth_request *auth_request,
+					const struct var_expand_table *table,
+					auth_request_escape_func_t *escape_func);
+const char *
+t_auth_request_var_expand(const char *str,
+			  struct auth_request *auth_request,
+			  auth_request_escape_func_t *escape_func);
+
 const char *auth_request_str_escape(const char *string,
 				    const struct auth_request *request);
 
--- a/src/auth/auth-request.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/auth-request.c	Fri May 29 21:39:33 2015 +0300
@@ -1201,7 +1201,6 @@
 		/* username format given, put it through variable expansion.
 		   we'll have to temporarily replace request->user to get
 		   %u to be the wanted username */
-		const struct var_expand_table *table;
 		char *old_username;
 		string_t *dest;
 
@@ -1209,8 +1208,7 @@
 		request->user = user;
 
 		dest = t_str_new(256);
-		table = auth_request_get_var_expand_table(request, NULL);
-		var_expand(dest, set->username_format, table);
+		auth_request_var_expand(dest, set->username_format, request, NULL);
 		user = p_strdup(request->pool, str_c(dest));
 
 		request->user = old_username;
@@ -1569,8 +1567,7 @@
 	struct stat st;
 
 	path = t_str_new(256);
-	var_expand(path, path_template,
-		   auth_request_get_var_expand_table(request, NULL));
+	auth_request_var_expand(path, path_template, request, NULL);
 	if (stat(str_c(path), &st) < 0) {
 		auth_request_log_error(request, AUTH_SUBSYS_DB,
 				       "stat(%s) failed: %m", str_c(path));
--- a/src/auth/db-checkpassword.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/db-checkpassword.c	Fri May 29 21:39:33 2015 +0300
@@ -15,7 +15,6 @@
 #include "safe-memset.h"
 #include "strescape.h"
 #include "child-wait.h"
-#include "var-expand.h"
 #include "db-checkpassword.h"
 
 #include <stdlib.h>
@@ -298,8 +297,7 @@
 	string_t *str;
 
 	str = t_str_new(256);
-	var_expand(str, args,
-		   auth_request_get_var_expand_table(request, NULL));
+	auth_request_var_expand(str, args, request, NULL);
 	return t_strconcat(str_c(str), " ", checkpassword_reply_path, NULL);
 }
 
--- a/src/auth/db-passwd-file.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/db-passwd-file.c	Fri May 29 21:39:33 2015 +0300
@@ -13,7 +13,6 @@
 #include "hash.h"
 #include "str.h"
 #include "eacces-error.h"
-#include "var-expand.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -431,15 +430,13 @@
 {
 	struct passwd_file *pw;
 	struct passwd_user *pu;
-	const struct var_expand_table *table;
 	string_t *username, *dest;
 
 	if (!db->vars)
 		pw = db->default_file;
 	else {
-		table = auth_request_get_var_expand_table(request, path_fix);
 		dest = t_str_new(256);
-		var_expand(dest, db->path, table);
+		auth_request_var_expand(dest, db->path, request, path_fix);
 
 		pw = hash_table_lookup(db->files, str_c(dest));
 		if (pw == NULL) {
@@ -454,9 +451,8 @@
 	}
 
 	username = t_str_new(256);
-	table = auth_request_get_var_expand_table(request,
-						  auth_request_str_escape);
-	var_expand(username, username_format, table);
+	auth_request_var_expand(username, username_format, request,
+				auth_request_str_escape);
 
 	auth_request_log_debug(request, AUTH_SUBSYS_DB,
 			       "lookup: user=%s file=%s",
--- a/src/auth/passdb-imap.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-imap.c	Fri May 29 21:39:33 2015 +0300
@@ -3,7 +3,6 @@
 #include "auth-common.h"
 #include "passdb.h"
 #include "str.h"
-#include "var-expand.h"
 #include "imap-resp-code.h"
 #include "imapc-client.h"
 
@@ -77,7 +76,6 @@
 		(struct imap_passdb_module *)_module;
 	struct imap_auth_request *request;
 	struct imapc_client_settings set;
-	const struct var_expand_table *table;
 	string_t *str;
 
 	set = module->set;
@@ -90,12 +88,11 @@
 
 	if (module->set_have_vars) {
 		str = t_str_new(128);
-		table = auth_request_get_var_expand_table(auth_request, NULL);
-		var_expand(str, set.username, table);
+		auth_request_var_expand(str, set.username, auth_request, NULL);
 		set.username = t_strdup(str_c(str));
 
 		str_truncate(str, 0);
-		var_expand(str, set.host, table);
+		auth_request_var_expand(str, set.host, auth_request, NULL);
 		set.host = t_strdup(str_c(str));
 	}
 	auth_request_log_debug(auth_request, AUTH_SUBSYS_DB,
--- a/src/auth/passdb-ldap.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-ldap.c	Fri May 29 21:39:33 2015 +0300
@@ -8,7 +8,6 @@
 #include "ioloop.h"
 #include "array.h"
 #include "str.h"
-#include "var-expand.h"
 #include "password-scheme.h"
 #include "auth-cache.h"
 #include "db-ldap.h"
@@ -289,20 +288,19 @@
 		(struct ldap_passdb_module *)_module;
 	struct ldap_connection *conn = module->conn;
 	struct ldap_request_search *srequest = &request->request.search;
-	const struct var_expand_table *vars;
 	const char **attr_names = (const char **)conn->pass_attr_names;
 	string_t *str;
 
 	request->require_password = require_password;
 	srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
-	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
 
 	str = t_str_new(512);
-	var_expand(str, conn->set.base, vars);
+	auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
 	srequest->base = p_strdup(auth_request->pool, str_c(str));
 
 	str_truncate(str, 0);
-	var_expand(str, conn->set.pass_filter, vars);
+	auth_request_var_expand(str, conn->set.pass_filter,
+				auth_request, ldap_escape);
 	srequest->filter = p_strdup(auth_request->pool, str_c(str));
 	srequest->attr_map = &conn->pass_attr_map;
 	srequest->attributes = conn->pass_attr_names;
@@ -325,18 +323,17 @@
 		(struct ldap_passdb_module *)_module;
 	struct ldap_connection *conn = module->conn;
 	struct ldap_request_search *srequest = &request->request.search;
-	const struct var_expand_table *vars;
 	string_t *str;
 
 	srequest->request.type = LDAP_REQUEST_TYPE_SEARCH;
-	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
 
 	str = t_str_new(512);
-	var_expand(str, conn->set.base, vars);
+	auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
 	srequest->base = p_strdup(auth_request->pool, str_c(str));
 
 	str_truncate(str, 0);
-	var_expand(str, conn->set.pass_filter, vars);
+	auth_request_var_expand(str, conn->set.pass_filter,
+				auth_request, ldap_escape);
 	srequest->filter = p_strdup(auth_request->pool, str_c(str));
 
 	/* we don't need the attributes to perform authentication, but they
@@ -362,14 +359,12 @@
 		(struct ldap_passdb_module *)_module;
 	struct ldap_connection *conn = module->conn;
 	struct ldap_request_bind *brequest = &request->request.bind;
-        const struct var_expand_table *vars;
 	string_t *dn;
 
 	brequest->request.type = LDAP_REQUEST_TYPE_BIND;
 
-	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
 	dn = t_str_new(512);
-	var_expand(dn, conn->set.auth_bind_userdn, vars);
+	auth_request_var_expand(dn, conn->set.auth_bind_userdn, auth_request, ldap_escape);
 
 	brequest->dn = p_strdup(auth_request->pool, str_c(dn));
         ldap_auth_bind(conn, brequest);
--- a/src/auth/passdb-pam.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-pam.c	Fri May 29 21:39:33 2015 +0300
@@ -14,7 +14,6 @@
 
 #include "lib-signals.h"
 #include "str.h"
-#include "var-expand.h"
 #include "net.h"
 #include "safe-memset.h"
 #include "auth-cache.h"
@@ -314,7 +313,6 @@
         struct passdb_module *_module = request->passdb->passdb;
         struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
 	enum passdb_result result;
-	string_t *expanded_service;
 	const char *service;
 
 	if (module->requests_left > 0) {
@@ -322,10 +320,7 @@
 			worker_restart_request = TRUE;
 	}
 
-	expanded_service = t_str_new(64);
-	var_expand(expanded_service, module->service_name,
-		   auth_request_get_var_expand_table(request, NULL));
-	service = str_c(expanded_service);
+	service = t_auth_request_var_expand(module->service_name, request, NULL);
 
 	auth_request_log_debug(request, AUTH_SUBSYS_DB,
 			       "lookup service=%s", service);
--- a/src/auth/passdb-passwd-file.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-passwd-file.c	Fri May 29 21:39:33 2015 +0300
@@ -7,7 +7,6 @@
 
 #include "str.h"
 #include "auth-cache.h"
-#include "var-expand.h"
 #include "password-scheme.h"
 #include "db-passwd-file.h"
 
@@ -46,7 +45,8 @@
 			if (value != NULL) {
 				key = t_strdup_until(*p, value);
 				str_truncate(str, 0);
-				var_expand(str, value + 1, table);
+				auth_request_var_expand_with_table(str, value + 1,
+					request, table, NULL);
 				value = str_c(str);
 			} else {
 				key = *p;
--- a/src/auth/passdb-sql.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-sql.c	Fri May 29 21:39:33 2015 +0300
@@ -5,9 +5,6 @@
 
 #ifdef PASSDB_SQL
 
-#include "str.h"
-#include "strescape.h"
-#include "var-expand.h"
 #include "safe-memset.h"
 #include "password-scheme.h"
 #include "auth-cache.h"
@@ -158,18 +155,17 @@
 	struct passdb_module *_module =
 		sql_request->auth_request->passdb->passdb;
 	struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
-	string_t *query;
+	const char *query;
 
-	query = t_str_new(512);
-	var_expand(query, module->conn->set.password_query,
-		   auth_request_get_var_expand_table(sql_request->auth_request,
-						     passdb_sql_escape));
+	query = t_auth_request_var_expand(module->conn->set.password_query,
+					  sql_request->auth_request,
+					  passdb_sql_escape);
 
 	auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
-			       "query: %s", str_c(query));
+			       "query: %s", query);
 
 	auth_request_ref(sql_request->auth_request);
-	sql_query(module->conn->db, str_c(query),
+	sql_query(module->conn->db, query,
 		  sql_query_callback, sql_request);
 }
 
@@ -232,21 +228,19 @@
 		(struct sql_passdb_module *) request->passdb->passdb;
 	struct sql_transaction_context *transaction;
 	struct passdb_sql_request *sql_request;
-	string_t *query;
+	const char *query;
 
 	request->mech_password = p_strdup(request->pool, new_credentials);
 
-	query = t_str_new(512);
-	var_expand(query, module->conn->set.update_query, 
-		   auth_request_get_var_expand_table(request,
-						     passdb_sql_escape));
+	query = t_auth_request_var_expand(module->conn->set.update_query,
+					  request, passdb_sql_escape);
 
 	sql_request = i_new(struct passdb_sql_request, 1);
 	sql_request->auth_request = request;
 	sql_request->callback.set_credentials = callback;
 
 	transaction = sql_transaction_begin(module->conn->db);
-	sql_update(transaction, str_c(query));
+	sql_update(transaction, query);
 	sql_transaction_commit(&transaction,
 			       sql_set_credentials_callback, sql_request);
 	return 0;
--- a/src/auth/passdb-static.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-static.c	Fri May 29 21:39:33 2015 +0300
@@ -1,9 +1,6 @@
 /* Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file */
 
 #include "auth-common.h"
-#include "array.h"
-#include "str.h"
-#include "var-expand.h"
 #include "passdb.h"
 #include "passdb-template.h"
 
@@ -18,16 +15,13 @@
 {
 	struct static_passdb_module *module =
 		(struct static_passdb_module *)request->passdb->passdb;
-        const struct var_expand_table *table;
-	string_t *str = t_str_new(128);
 
 	auth_request_log_debug(request, AUTH_SUBSYS_DB, "lookup");
 	passdb_template_export(module->tmpl, request);
 
 	if (module->static_password_tmpl != NULL) {
-		table = auth_request_get_var_expand_table(request, NULL);
-		var_expand(str, module->static_password_tmpl, table);
-		*password_r = str_c(str);
+		*password_r = t_auth_request_var_expand(
+			module->static_password_tmpl, request, NULL);
 	} else if (auth_fields_exists(request->extra_fields, "nopassword")) {
 		*password_r = "";
 	} else {
--- a/src/auth/passdb-template.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/passdb-template.c	Fri May 29 21:39:33 2015 +0300
@@ -3,7 +3,6 @@
 #include "auth-common.h"
 #include "array.h"
 #include "str.h"
-#include "var-expand.h"
 #include "passdb.h"
 #include "passdb-template.h"
 
@@ -54,7 +53,8 @@
 			value = "";
 		else {
 			str_truncate(str, 0);
-			var_expand(str, args[i+1], table);
+			auth_request_var_expand_with_table(str, args[i+1],
+				auth_request, table, NULL);
 			value = str_c(str);
 		}
 		auth_request_set_field(auth_request, args[i], value,
--- a/src/auth/test-auth-request-var-expand.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/test-auth-request-var-expand.c	Fri May 29 21:39:33 2015 +0300
@@ -187,6 +187,43 @@
 	test_end();
 }
 
+static void test_auth_request_var_expand_funcs(void)
+{
+	pool_t pool;
+	const char *value;
+
+	test_begin("auth request var expand funcs");
+
+	pool = pool_alloconly_create("test var expand funcs", 1024);
+	test_request.extra_fields = auth_fields_init(pool);
+	test_request.userdb_reply = auth_fields_init(pool);
+
+	auth_fields_add(test_request.extra_fields, "pkey1", "-pval1", 0);
+	auth_fields_add(test_request.extra_fields, "pkey2", "", 0);
+
+	auth_fields_add(test_request.userdb_reply, "ukey1", "-uval1", 0);
+	auth_fields_add(test_request.userdb_reply, "ukey2", "", 0);
+
+	value = t_auth_request_var_expand(
+			"%{passdb:pkey1}\n%{passdb:pkey1:default1}\n"
+			"%{passdb:pkey2}\n%{passdb:pkey2:default2}\n"
+			"%{passdb:pkey3}\n%{passdb:pkey3:default3}\n"
+			"%{passdb:ukey1}\n%{passdb:ukey1:default4}\n",
+			&test_request, test_escape);
+	test_assert(strcmp(value, "+pval1\n+pval1\n\n\n\ndefault3\n\ndefault4\n") == 0);
+
+	value = t_auth_request_var_expand(
+			"%{userdb:ukey1}\n%{userdb:ukey1:default1}\n"
+			"%{userdb:ukey2}\n%{userdb:ukey2:default2}\n"
+			"%{userdb:ukey3}\n%{userdb:ukey3:default3}\n"
+			"%{userdb:pkey1}\n%{userdb:pkey1:default4}\n",
+			&test_request, test_escape);
+	test_assert(strcmp(value, "+uval1\n+uval1\n\n\n\ndefault3\n\ndefault4\n") == 0);
+
+	pool_unref(&pool);
+	test_end();
+}
+
 int main(void)
 {
 	static void (*test_functions[])(void) = {
@@ -194,6 +231,7 @@
 		test_auth_request_var_expand_flags,
 		test_auth_request_var_expand_long,
 		test_auth_request_var_expand_usernames,
+		test_auth_request_var_expand_funcs,
 		NULL
 	};
 	test_request = default_test_request;
--- a/src/auth/userdb-dict.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/userdb-dict.c	Fri May 29 21:39:33 2015 +0300
@@ -6,7 +6,6 @@
 #include "ioloop.h"
 #include "array.h"
 #include "str.h"
-#include "var-expand.h"
 #include "auth-cache.h"
 #include "db-dict.h"
 
@@ -89,7 +88,6 @@
 	struct dict_userdb_module *module =
 		(struct dict_userdb_module *)_module;
 	struct dict_userdb_iterate_context *ctx;
-        const struct var_expand_table *vars;
 	string_t *path;
 
 	ctx = i_new(struct dict_userdb_iterate_context, 1);
@@ -109,8 +107,8 @@
 
 	path = t_str_new(128);
 	str_append(path, DICT_PATH_SHARED);
-	vars = auth_request_get_var_expand_table(auth_request, NULL);
-	var_expand(path, module->conn->set.iterate_prefix, vars);
+	auth_request_var_expand(path, module->conn->set.iterate_prefix,
+				auth_request, NULL);
 	ctx->key_prefix = p_strdup(auth_request->pool, str_c(path));
 	ctx->key_prefix_len = strlen(ctx->key_prefix);
 
--- a/src/auth/userdb-ldap.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/userdb-ldap.c	Fri May 29 21:39:33 2015 +0300
@@ -8,7 +8,6 @@
 #include "ioloop.h"
 #include "array.h"
 #include "str.h"
-#include "var-expand.h"
 #include "auth-cache.h"
 #include "db-ldap.h"
 
@@ -110,7 +109,6 @@
 	struct ldap_userdb_module *module =
 		(struct ldap_userdb_module *)_module;
 	struct ldap_connection *conn = module->conn;
-        const struct var_expand_table *vars;
 	const char **attr_names = (const char **)conn->user_attr_names;
 	struct userdb_ldap_request *request;
 	string_t *str;
@@ -119,14 +117,12 @@
 	request = p_new(auth_request->pool, struct userdb_ldap_request, 1);
 	request->userdb_callback = callback;
 
-	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
-
 	str = t_str_new(512);
-	var_expand(str, conn->set.base, vars);
+	auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
 	request->request.base = p_strdup(auth_request->pool, str_c(str));
 
 	str_truncate(str, 0);
-	var_expand(str, conn->set.user_filter, vars);
+	auth_request_var_expand(str, conn->set.user_filter, auth_request, ldap_escape);
 	request->request.filter = p_strdup(auth_request->pool, str_c(str));
 
 	request->request.attr_map = &conn->user_attr_map;
@@ -195,7 +191,6 @@
 	struct ldap_connection *conn = module->conn;
 	struct ldap_userdb_iterate_context *ctx;
 	struct userdb_iter_ldap_request *request;
-        const struct var_expand_table *vars;
 	const char **attr_names = (const char **)conn->iterate_attr_names;
 	string_t *str;
 
@@ -210,14 +205,13 @@
 	auth_request_ref(auth_request);
 	request->request.request.auth_request = auth_request;
 
-	vars = auth_request_get_var_expand_table(auth_request, ldap_escape);
-
 	str = t_str_new(512);
-	var_expand(str, conn->set.base, vars);
+	auth_request_var_expand(str, conn->set.base, auth_request, ldap_escape);
 	request->request.base = p_strdup(auth_request->pool, str_c(str));
 
 	str_truncate(str, 0);
-	var_expand(str, conn->set.iterate_filter, vars);
+	auth_request_var_expand(str, conn->set.iterate_filter,
+				auth_request, ldap_escape);
 	request->request.filter = p_strdup(auth_request->pool, str_c(str));
 	request->request.attr_map = &conn->iterate_attr_map;
 	request->request.attributes = conn->iterate_attr_names;
--- a/src/auth/userdb-passwd-file.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/userdb-passwd-file.c	Fri May 29 21:39:33 2015 +0300
@@ -8,7 +8,6 @@
 #include "istream.h"
 #include "str.h"
 #include "auth-cache.h"
-#include "var-expand.h"
 #include "db-passwd-file.h"
 
 #include <unistd.h>
@@ -74,7 +73,8 @@
 			if (value != NULL) {
 				key = t_strdup_until(key, value);
 				str_truncate(str, 0);
-				var_expand(str, value + 1, table);
+				auth_request_var_expand_with_table(str, value + 1,
+					auth_request, table, NULL);
 				value = str_c(str);
 			} else {
 				value = "";
--- a/src/auth/userdb-sql.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/userdb-sql.c	Fri May 29 21:39:33 2015 +0300
@@ -5,9 +5,6 @@
 
 #ifdef USERDB_SQL
 
-#include "str.h"
-#include "strescape.h"
-#include "var-expand.h"
 #include "auth-cache.h"
 #include "db-sql.h"
 
@@ -109,21 +106,19 @@
 	struct sql_userdb_module *module =
 		(struct sql_userdb_module *)_module;
 	struct userdb_sql_request *sql_request;
-	string_t *query;
+	const char *query;
 
-	query = t_str_new(512);
-	var_expand(query, module->conn->set.user_query,
-		   auth_request_get_var_expand_table(auth_request,
-						     userdb_sql_escape));
+	query = t_auth_request_var_expand(module->conn->set.user_query,
+		   	auth_request, userdb_sql_escape);
 
 	auth_request_ref(auth_request);
 	sql_request = i_new(struct userdb_sql_request, 1);
 	sql_request->callback = callback;
 	sql_request->auth_request = auth_request;
 
-	auth_request_log_debug(auth_request, AUTH_SUBSYS_DB, "%s", str_c(query));
+	auth_request_log_debug(auth_request, AUTH_SUBSYS_DB, "%s", query);
 
-	sql_query(module->conn->db, str_c(query),
+	sql_query(module->conn->db, query,
 		  sql_query_callback, sql_request);
 }
 
@@ -147,12 +142,10 @@
 	struct sql_userdb_module *module =
 		(struct sql_userdb_module *)_module;
 	struct sql_userdb_iterate_context *ctx;
-	string_t *query;
+	const char *query;
 
-	query = t_str_new(512);
-	var_expand(query, module->conn->set.iterate_query,
-		   auth_request_get_var_expand_table(auth_request,
-						     userdb_sql_escape));
+	query = t_auth_request_var_expand(module->conn->set.iterate_query,
+		   auth_request, userdb_sql_escape);
 
 	ctx = i_new(struct sql_userdb_iterate_context, 1);
 	ctx->ctx.auth_request = auth_request;
@@ -160,9 +153,9 @@
 	ctx->ctx.context = context;
 	auth_request_ref(auth_request);
 
-	sql_query(module->conn->db, str_c(query),
+	sql_query(module->conn->db, query,
 		  sql_iter_query_callback, ctx);
-	auth_request_log_debug(auth_request, AUTH_SUBSYS_DB, "%s", str_c(query));
+	auth_request_log_debug(auth_request, AUTH_SUBSYS_DB, "%s", query);
 	return &ctx->ctx;
 }
 
--- a/src/auth/userdb-template.c	Fri May 29 20:56:13 2015 +0300
+++ b/src/auth/userdb-template.c	Fri May 29 21:39:33 2015 +0300
@@ -3,7 +3,6 @@
 #include "auth-common.h"
 #include "array.h"
 #include "str.h"
-#include "var-expand.h"
 #include "userdb.h"
 #include "userdb-template.h"
 
@@ -77,7 +76,8 @@
 			value = "";
 		else {
 			str_truncate(str, 0);
-			var_expand(str, args[i+1], table);
+			auth_request_var_expand_with_table(str, args[i+1],
+				auth_request, table, NULL);
 			value = str_c(str);
 		}
 		auth_request_set_userdb_field(auth_request, args[i], value);