Mercurial > dovecot > original-hg > dovecot-2.2
changeset 13760:acfe332f9aeb
auth: Support passing regular %variables to sql/ldap iterate queries.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 23 Nov 2011 22:07:08 +0200 |
parents | 35764175dc92 |
children | 59e25ebc976f |
files | src/auth/auth-master-connection.c src/auth/auth-settings.c src/auth/auth-worker-client.c src/auth/userdb-blocking.c src/auth/userdb-blocking.h src/auth/userdb-ldap.c src/auth/userdb-passwd-file.c src/auth/userdb-passwd.c src/auth/userdb-sql.c src/auth/userdb.h |
diffstat | 10 files changed, 130 insertions(+), 81 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-master-connection.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/auth-master-connection.c Wed Nov 23 22:07:08 2011 +0200 @@ -29,15 +29,13 @@ struct master_userdb_request { struct auth_master_connection *conn; - unsigned int id; struct auth_request *auth_request; }; struct master_list_iter_ctx { struct auth_master_connection *conn; - struct auth_userdb *userdb; struct userdb_iterate_context *iter; - unsigned int id; + struct auth_request *auth_request; bool failed; }; @@ -383,6 +381,8 @@ if (ctx->iter != NULL) (void)userdb_blocking_iter_deinit(&ctx->iter); o_stream_unset_flush_callback(ctx->conn->output); + auth_request_unref(&ctx->auth_request); + auth_master_connection_unref(&ctx->conn); i_free(ctx); } @@ -402,6 +402,7 @@ static void master_input_list_callback(const char *user, void *context) { struct master_list_iter_ctx *ctx = context; + struct auth_userdb *userdb = ctx->auth_request->userdb; int ret; if (user == NULL) { @@ -409,14 +410,15 @@ ctx->failed = TRUE; do { - ctx->userdb = ctx->userdb->next; - } while (ctx->userdb != NULL && - ctx->userdb->userdb->iface->iterate_init == NULL); - if (ctx->userdb == NULL) { + userdb = userdb->next; + } while (userdb != NULL && + userdb->userdb->iface->iterate_init == NULL); + if (userdb == NULL) { /* iteration is finished */ const char *str; - str = t_strdup_printf("DONE\t%u\t%s\n", ctx->id, + str = t_strdup_printf("DONE\t%u\t%s\n", + ctx->auth_request->id, ctx->failed ? "fail" : ""); (void)o_stream_send_str(ctx->conn->output, str); master_input_list_finish(ctx); @@ -424,7 +426,8 @@ } /* continue iterating next userdb */ - ctx->iter = userdb_blocking_iter_init(ctx->userdb->userdb, + ctx->auth_request->userdb = userdb; + ctx->iter = userdb_blocking_iter_init(ctx->auth_request, master_input_list_callback, ctx); userdb_blocking_iter_next(ctx->iter); return; @@ -433,7 +436,7 @@ T_BEGIN { const char *str; - str = t_strdup_printf("LIST\t%u\t%s\n", ctx->id, + str = t_strdup_printf("LIST\t%u\t%s\n", ctx->auth_request->id, str_tabescape(user)); ret = o_stream_send_str(ctx->conn->output, str); } T_END; @@ -450,15 +453,18 @@ master_input_list(struct auth_master_connection *conn, const char *args) { struct auth_userdb *userdb = conn->auth->userdbs; + struct auth_request *auth_request; struct master_list_iter_ctx *ctx; - const char *str; + const char *str, *name, *arg, *const *list; unsigned int id; - /* <id> */ - if (str_to_uint(args, &id) < 0) { + /* <id> [<parameters>] */ + list = t_strsplit(args, "\t"); + if (list[0] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Master sent broken LIST"); - return FALSE; + return -1; } + list++; if (conn->userdb_restricted_uid != 0) { i_error("Auth client doesn't have permissions to list users: %s", @@ -477,14 +483,42 @@ return TRUE; } + auth_request = auth_request_new_dummy(); + auth_request->id = id; + auth_request->master = conn; + auth_master_connection_ref(conn); + + for (; *list != NULL; list++) { + arg = strchr(*list, '='); + if (arg == NULL) { + name = *list; + arg = ""; + } else { + name = t_strdup_until(*list, arg); + arg++; + } + + if (!auth_request_import_info(auth_request, name, arg) && + strcmp(name, "user") == 0) { + /* username mask */ + auth_request->user = p_strdup(auth_request->pool, arg); + } + } + + /* rest of the code doesn't like NULL user or service */ + if (auth_request->user == NULL) + auth_request->user = ""; + if (auth_request->service == NULL) + auth_request->service = ""; + ctx = i_new(struct master_list_iter_ctx, 1); ctx->conn = conn; - ctx->userdb = userdb; - ctx->id = id; + ctx->auth_request = auth_request; + ctx->auth_request->userdb = userdb; io_remove(&conn->io); o_stream_set_flush_callback(conn->output, master_output_list, ctx); - ctx->iter = userdb_blocking_iter_init(ctx->userdb->userdb, + ctx->iter = userdb_blocking_iter_init(auth_request, master_input_list_callback, ctx); return TRUE; }
--- a/src/auth/auth-settings.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/auth-settings.c Wed Nov 23 22:07:08 2011 +0200 @@ -349,6 +349,7 @@ }; struct master_service_settings_input input; struct setting_parser_context *set_parser; + struct auth_settings *set; const char *error; memset(&input, 0, sizeof(input)); @@ -359,9 +360,12 @@ output_r, &error) < 0) i_fatal("Error reading configuration: %s", error); + pool_ref(pool); set_parser = settings_parser_dup(master_service->set_parser, pool); if (!settings_parser_check(set_parser, pool, &error)) i_unreached(); - return settings_parser_get_list(set_parser)[1]; + set = settings_parser_get_list(set_parser)[1]; + settings_parser_deinit(&set_parser); + return set; }
--- a/src/auth/auth-worker-client.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/auth-worker-client.c Wed Nov 23 22:07:08 2011 +0200 @@ -31,9 +31,8 @@ struct auth_worker_list_context { struct auth_worker_client *client; - struct userdb_module *userdb; + struct auth_request *auth_request; struct userdb_iterate_context *iter; - unsigned int id; bool sending, sent, done; }; @@ -415,14 +414,16 @@ i_assert(client->io == NULL); str = t_str_new(32); - if (ctx->userdb->iface->iterate_deinit(ctx->iter) < 0) - str_printfa(str, "%u\tFAIL\n", ctx->id); + if (ctx->auth_request->userdb->userdb->iface-> + iterate_deinit(ctx->iter) < 0) + str_printfa(str, "%u\tFAIL\n", ctx->auth_request->id); else - str_printfa(str, "%u\tOK\n", ctx->id); + str_printfa(str, "%u\tOK\n", ctx->auth_request->id); auth_worker_send_reply(client, str); client->io = io_add(client->fd, IO_READ, auth_worker_input, client); o_stream_set_flush_callback(client->output, auth_worker_output, client); + auth_request_unref(&ctx->auth_request); auth_worker_client_unref(&client); i_free(ctx); } @@ -442,7 +443,7 @@ T_BEGIN { str = t_str_new(128); - str_printfa(str, "%u\t*\t%s\n", ctx->id, user); + str_printfa(str, "%u\t*\t%s\n", ctx->auth_request->id, user); o_stream_send(ctx->client->output, str_data(str), str_len(str)); } T_END; @@ -455,7 +456,8 @@ do { ctx->sending = TRUE; ctx->sent = FALSE; - ctx->userdb->iface->iterate_next(ctx->iter); + ctx->auth_request->userdb->userdb->iface-> + iterate_next(ctx->iter); } while (ctx->sent && o_stream_get_buffer_used_size(ctx->client->output) == 0); ctx->sending = FALSE; @@ -471,8 +473,10 @@ list_iter_deinit(ctx); return 1; } - if (ret > 0) - ctx->userdb->iface->iterate_next(ctx->iter); + if (ret > 0) { + ctx->auth_request->userdb->userdb->iface-> + iterate_next(ctx->iter); + } return 1; } @@ -497,16 +501,22 @@ ctx = i_new(struct auth_worker_list_context, 1); ctx->client = client; - ctx->id = id; - ctx->userdb = userdb->userdb; + ctx->auth_request = worker_auth_request_new(client, id, args + 1); + ctx->auth_request->userdb = userdb; + if (ctx->auth_request->user == NULL || + ctx->auth_request->service == NULL) { + i_error("BUG: LIST had missing parameters"); + auth_request_unref(&ctx->auth_request); + i_free(ctx); + return FALSE; + } io_remove(&ctx->client->io); o_stream_set_flush_callback(ctx->client->output, auth_worker_list_output, ctx); - client->refcount++; - ctx->iter = ctx->userdb->iface-> - iterate_init(userdb->userdb, list_iter_callback, ctx); - ctx->userdb->iface->iterate_next(ctx->iter); + ctx->iter = ctx->auth_request->userdb->userdb->iface-> + iterate_init(ctx->auth_request, list_iter_callback, ctx); + ctx->auth_request->userdb->userdb->iface->iterate_next(ctx->iter); return TRUE; }
--- a/src/auth/userdb-blocking.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-blocking.c Wed Nov 23 22:07:08 2011 +0200 @@ -10,7 +10,6 @@ struct blocking_userdb_iterate_context { struct userdb_iterate_context ctx; - pool_t pool; struct auth_worker_connection *conn; bool next; bool destroyed; @@ -66,7 +65,6 @@ static bool iter_callback(const char *reply, void *context) { struct blocking_userdb_iterate_context *ctx = context; - pool_t pool = ctx->pool; if (strncmp(reply, "*\t", 2) == 0) { ctx->next = FALSE; @@ -78,31 +76,30 @@ ctx->ctx.failed = TRUE; if (!ctx->destroyed) ctx->ctx.callback(NULL, ctx->ctx.context); - pool_unref(&pool); + auth_request_unref(&ctx->ctx.auth_request); return TRUE; } struct userdb_iterate_context * -userdb_blocking_iter_init(struct userdb_module *userdb, +userdb_blocking_iter_init(struct auth_request *request, userdb_iter_callback_t *callback, void *context) { struct blocking_userdb_iterate_context *ctx; struct auth_stream_reply *reply; - pool_t pool; reply = auth_stream_reply_init(pool_datastack_create()); auth_stream_reply_add(reply, "LIST", NULL); - auth_stream_reply_add(reply, NULL, dec2str(userdb->id)); + auth_stream_reply_add(reply, NULL, + dec2str(request->userdb->userdb->id)); + auth_request_export(request, reply); - pool = pool_alloconly_create("userdb iter", 512); - ctx = p_new(pool, struct blocking_userdb_iterate_context, 1); - ctx->ctx.userdb = userdb; + ctx = p_new(request->pool, struct blocking_userdb_iterate_context, 1); + ctx->ctx.auth_request = request; ctx->ctx.callback = callback; ctx->ctx.context = context; - ctx->pool = pool; - pool_ref(pool); - ctx->conn = auth_worker_call(pool, reply, iter_callback, ctx); + auth_request_ref(request); + ctx->conn = auth_worker_call(request->pool, reply, iter_callback, ctx); return &ctx->ctx; } @@ -123,7 +120,7 @@ *_ctx = NULL; + /* iter_callback() may still be called */ ctx->destroyed = TRUE; - pool_unref(&ctx->pool); return ret; }
--- a/src/auth/userdb-blocking.h Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-blocking.h Wed Nov 23 22:07:08 2011 +0200 @@ -4,7 +4,7 @@ void userdb_blocking_lookup(struct auth_request *request); struct userdb_iterate_context * -userdb_blocking_iter_init(struct userdb_module *userdb, +userdb_blocking_iter_init(struct auth_request *request, userdb_iter_callback_t *callback, void *context); void userdb_blocking_iter_next(struct userdb_iterate_context *ctx); int userdb_blocking_iter_deinit(struct userdb_iterate_context **ctx);
--- a/src/auth/userdb-ldap.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-ldap.c Wed Nov 23 22:07:08 2011 +0200 @@ -185,37 +185,39 @@ } static struct userdb_iterate_context * -userdb_ldap_iterate_init(struct userdb_module *userdb, +userdb_ldap_iterate_init(struct auth_request *auth_request, userdb_iter_callback_t *callback, void *context) { - static struct var_expand_table static_tab[] = { - /* nothing for now, but e.g. %{hostname} can be used */ - { '\0', NULL, NULL } - }; + struct userdb_module *_module = auth_request->userdb->userdb; struct ldap_userdb_module *module = - (struct ldap_userdb_module *)userdb; + (struct ldap_userdb_module *)_module; 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; ctx = i_new(struct ldap_userdb_iterate_context, 1); - ctx->ctx.userdb = userdb; + ctx->ctx.auth_request = auth_request; ctx->ctx.callback = callback; ctx->ctx.context = context; ctx->conn = conn; request = &ctx->request; request->ctx = ctx; - request->request.request.auth_request = auth_request_new_dummy(); - request->request.base = conn->set.base; + 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.iterate_filter, static_tab); - request->request.filter = - p_strdup(request->request.request.auth_request->pool, - str_c(str)); + var_expand(str, conn->set.base, vars); + request->request.base = p_strdup(auth_request->pool, str_c(str)); + + str_truncate(str, 0); + var_expand(str, conn->set.iterate_filter, vars); + request->request.filter = p_strdup(auth_request->pool, str_c(str)); request->request.attributes = conn->iterate_attr_names; if (global_auth_settings->debug) {
--- a/src/auth/userdb-passwd-file.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-passwd-file.c Wed Nov 23 22:07:08 2011 +0200 @@ -85,16 +85,17 @@ } static struct userdb_iterate_context * -passwd_file_iterate_init(struct userdb_module *userdb, +passwd_file_iterate_init(struct auth_request *auth_request, userdb_iter_callback_t *callback, void *context) { + struct userdb_module *_module = auth_request->userdb->userdb; struct passwd_file_userdb_module *module = - (struct passwd_file_userdb_module *)userdb; + (struct passwd_file_userdb_module *)_module; struct passwd_file_userdb_iterate_context *ctx; int fd; ctx = i_new(struct passwd_file_userdb_iterate_context, 1); - ctx->ctx.userdb = userdb; + ctx->ctx.auth_request = auth_request; ctx->ctx.callback = callback; ctx->ctx.context = context; if (module->pwf->default_file == NULL) {
--- a/src/auth/userdb-passwd.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-passwd.c Wed Nov 23 22:07:08 2011 +0200 @@ -19,7 +19,6 @@ struct passwd_userdb_iterate_context { struct userdb_iterate_context ctx; struct passwd_userdb_iterate_context *next_waiting; - const struct auth_settings *set; }; static struct passwd_userdb_iterate_context *cur_userdb_iter = NULL; @@ -62,16 +61,15 @@ } static struct userdb_iterate_context * -passwd_iterate_init(struct userdb_module *userdb, +passwd_iterate_init(struct auth_request *auth_request, userdb_iter_callback_t *callback, void *context) { struct passwd_userdb_iterate_context *ctx; ctx = i_new(struct passwd_userdb_iterate_context, 1); - ctx->ctx.userdb = userdb; + ctx->ctx.auth_request = auth_request; ctx->ctx.callback = callback; ctx->ctx.context = context; - ctx->set = auth_find_service("")->set; setpwent(); if (cur_userdb_iter == NULL) @@ -83,6 +81,7 @@ { struct passwd_userdb_iterate_context *ctx = (struct passwd_userdb_iterate_context *)_ctx; + const struct auth_settings *set = _ctx->auth_request->set; struct passwd *pw; if (cur_userdb_iter != NULL && cur_userdb_iter != ctx) { @@ -97,9 +96,9 @@ while ((pw = getpwent()) != NULL) { /* skip entries not in valid UID range. they're users for daemons and such. */ - if (pw->pw_uid >= (uid_t)ctx->set->first_valid_uid && - (ctx->set->last_valid_uid == 0 || - pw->pw_uid <= (uid_t)ctx->set->last_valid_uid)) { + if (pw->pw_uid >= (uid_t)set->first_valid_uid && + (set->last_valid_uid == 0 || + pw->pw_uid <= (uid_t)set->last_valid_uid)) { _ctx->callback(pw->pw_name, _ctx->context); return; }
--- a/src/auth/userdb-sql.c Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb-sql.c Wed Nov 23 22:07:08 2011 +0200 @@ -140,28 +140,29 @@ } static struct userdb_iterate_context * -userdb_sql_iterate_init(struct userdb_module *userdb, +userdb_sql_iterate_init(struct auth_request *auth_request, userdb_iter_callback_t *callback, void *context) { - static struct var_expand_table static_tab[] = { - /* nothing for now, but e.g. %{hostname} can be used */ - { '\0', NULL, NULL } - }; + struct userdb_module *_module = auth_request->userdb->userdb; struct sql_userdb_module *module = - (struct sql_userdb_module *)userdb; + (struct sql_userdb_module *)_module; struct sql_userdb_iterate_context *ctx; string_t *query; query = t_str_new(512); - var_expand(query, module->conn->set.iterate_query, static_tab); + var_expand(query, module->conn->set.iterate_query, + auth_request_get_var_expand_table(auth_request, + userdb_sql_escape)); ctx = i_new(struct sql_userdb_iterate_context, 1); - ctx->ctx.userdb = userdb; + ctx->ctx.auth_request = auth_request; ctx->ctx.callback = callback; ctx->ctx.context = context; + auth_request_ref(auth_request); sql_query(module->conn->db, str_c(query), sql_iter_query_callback, ctx); + auth_request_log_debug(auth_request, "sql", "%s", str_c(query)); return &ctx->ctx; } @@ -199,7 +200,7 @@ { struct sql_userdb_iterate_context *ctx = (struct sql_userdb_iterate_context *)_ctx; - struct userdb_module *_module = _ctx->userdb; + struct userdb_module *_module = _ctx->auth_request->userdb->userdb; struct sql_userdb_module *module = (struct sql_userdb_module *)_module; const char *user; int ret; @@ -242,6 +243,7 @@ (struct sql_userdb_iterate_context *)_ctx; int ret = _ctx->failed ? -1 : 0; + auth_request_unref(&_ctx->auth_request); if (ctx->result == NULL) { /* sql query hasn't finished yet */ ctx->freed = TRUE;
--- a/src/auth/userdb.h Wed Nov 23 21:40:04 2011 +0200 +++ b/src/auth/userdb.h Wed Nov 23 22:07:08 2011 +0200 @@ -41,7 +41,7 @@ }; struct userdb_iterate_context { - struct userdb_module *userdb; + struct auth_request *auth_request; userdb_iter_callback_t *callback; void *context; bool failed; @@ -58,7 +58,7 @@ userdb_callback_t *callback); struct userdb_iterate_context * - (*iterate_init)(struct userdb_module *userdb, + (*iterate_init)(struct auth_request *auth_request, userdb_iter_callback_t *callback, void *context); void (*iterate_next)(struct userdb_iterate_context *ctx);