From: Timo Sirainen Date: Tue, 14 Jan 2014 01:24:47 +0000 (+0200) Subject: auth, login, mail: Added %{auth_user}, %{auth_username} and %{auth_domain} X-Git-Tag: 2.2.11~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2f90189c6ee66a17f7bf838a8eb8a69868630fb8;p=thirdparty%2Fdovecot%2Fcore.git auth, login, mail: Added %{auth_user}, %{auth_username} and %{auth_domain} They expand to the SASL authentication ID. So if master user login is done, it expands to the master user. If username changes during authentication, it expands to the original username. Otherwise %{user} and %{auth_user} are equal. --- diff --git a/src/auth/auth-request-handler.c b/src/auth/auth-request-handler.c index 50a82e0898..c0f2bcc508 100644 --- a/src/auth/auth-request-handler.c +++ b/src/auth/auth-request-handler.c @@ -177,6 +177,8 @@ auth_str_append_extra_fields(struct auth_request *request, string_t *dest) auth_str_add_keyvalue(dest, "original_user", request->original_username); } + if (request->master_user != NULL) + auth_str_add_keyvalue(dest, "auth_user", request->master_user); if (!request->auth_only && auth_fields_exists(request->extra_fields, "proxy")) { @@ -621,6 +623,44 @@ bool auth_request_handler_auth_continue(struct auth_request_handler *handler, return TRUE; } +static void auth_str_append_userdb_extra_fields(struct auth_request *request, + string_t *dest) +{ + str_append_c(dest, '\t'); + auth_fields_append(request->userdb_reply, dest, + AUTH_FIELD_FLAG_HIDDEN, 0); + + if (request->master_user != NULL && + !auth_fields_exists(request->userdb_reply, "master_user")) { + auth_str_add_keyvalue(dest, "master_user", + request->master_user); + } + if (*request->set->anonymous_username != '\0' && + strcmp(request->user, request->set->anonymous_username) == 0) { + /* this is an anonymous login, either via ANONYMOUS + SASL mechanism or simply logging in as the anonymous + user via another mechanism */ + str_append(dest, "\tanonymous"); + } + /* generate auth_token when master service provided session_pid */ + if (request->request_auth_token && + request->session_pid != (pid_t)-1) { + const char *auth_token = + auth_token_get(request->service, + dec2str(request->session_pid), + request->user, + request->session_id); + auth_str_add_keyvalue(dest, "auth_token", auth_token); + } + if (request->master_user != NULL) { + auth_str_add_keyvalue(dest, "auth_user", request->master_user); + } else if (request->original_username != NULL && + strcmp(request->original_username, request->user) != 0) { + auth_str_add_keyvalue(dest, "auth_user", + request->original_username); + } +} + static void userdb_callback(enum userdb_result result, struct auth_request *request) { @@ -651,33 +691,7 @@ static void userdb_callback(enum userdb_result result, case USERDB_RESULT_OK: str_printfa(str, "USER\t%u\t", request->id); str_append_tabescaped(str, request->user); - str_append_c(str, '\t'); - auth_fields_append(request->userdb_reply, str, - AUTH_FIELD_FLAG_HIDDEN, 0); - - if (request->master_user != NULL && - !auth_fields_exists(request->userdb_reply, "master_user")) { - auth_str_add_keyvalue(str, "master_user", - request->master_user); - } - if (*request->set->anonymous_username != '\0' && - strcmp(request->user, - request->set->anonymous_username) == 0) { - /* this is an anonymous login, either via ANONYMOUS - SASL mechanism or simply logging in as the anonymous - user via another mechanism */ - str_append(str, "\tanonymous"); - } - /* generate auth_token when master service provided session_pid */ - if (request->request_auth_token && - request->session_pid != (pid_t)-1) { - const char *auth_token = - auth_token_get(request->service, - dec2str(request->session_pid), - request->user, - request->session_id); - auth_str_add_keyvalue(str, "auth_token", auth_token); - } + auth_str_append_userdb_extra_fields(request, str); break; } handler->master_callback(str_c(str), request->master); diff --git a/src/lib-storage/mail-storage-service.c b/src/lib-storage/mail-storage-service.c index dea26f51b7..65f4d160a5 100644 --- a/src/lib-storage/mail-storage-service.c +++ b/src/lib-storage/mail-storage-service.c @@ -75,7 +75,7 @@ struct mail_storage_service_user { enum mail_storage_service_flags flags; struct ioloop_context *ioloop_ctx; - const char *log_prefix, *auth_token; + const char *log_prefix, *auth_token, *auth_user; const char *system_groups_user, *uid_source, *gid_source; const struct mail_user_settings *user_set; @@ -278,6 +278,8 @@ user_reply_handle(struct mail_storage_service_ctx *ctx, #endif } else if (strncmp(line, "auth_token=", 11) == 0) { user->auth_token = p_strdup(user->pool, line+11); + } else if (strncmp(line, "auth_user=", 10) == 0) { + user->auth_user = p_strdup(user->pool, line+10); } else if (strncmp(line, "admin=", 6) == 0) { user->admin = line[6] == 'y' || line[6] == 'Y' || line[6] == '1'; @@ -376,6 +378,7 @@ static bool parse_gid(const char *str, gid_t *gid_r, const char **error_r) static const struct var_expand_table * get_var_expand_table(struct master_service *service, + struct mail_storage_service_user *user, struct mail_storage_service_input *input, struct mail_storage_service_privileges *priv) { @@ -390,6 +393,9 @@ get_var_expand_table(struct master_service *service, { 'i', NULL, "uid" }, { '\0', NULL, "gid" }, { '\0', NULL, "session" }, + { '\0', NULL, "auth_user" }, + { '\0', NULL, "auth_username" }, + { '\0', NULL, "auth_domain" }, { '\0', NULL, NULL } }; struct var_expand_table *tab; @@ -408,6 +414,15 @@ get_var_expand_table(struct master_service *service, tab[7].value = dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid); tab[8].value = dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid); tab[9].value = input->session_id; + if (user == NULL || user->auth_user == NULL) { + tab[10].value = tab[0].value; + tab[11].value = tab[1].value; + tab[12].value = tab[2].value; + } else { + tab[10].value = user->auth_user; + tab[11].value = t_strcut(user->auth_user, '@'); + tab[12].value = strchr(user->auth_user, '@'); + } return tab; } @@ -420,12 +435,12 @@ mail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx, memset(&priv, 0, sizeof(priv)); priv.uid = (uid_t)-1; priv.gid = (gid_t)-1; - return get_var_expand_table(ctx->service, input, &priv); + return get_var_expand_table(ctx->service, NULL, input, &priv); } static const char * user_expand_varstr(struct master_service *service, - struct mail_storage_service_input *input, + struct mail_storage_service_user *user, struct mail_storage_service_privileges *priv, const char *str) { @@ -437,7 +452,8 @@ user_expand_varstr(struct master_service *service, i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]); ret = t_str_new(256); - var_expand(ret, str + 1, get_var_expand_table(service, input, priv)); + var_expand(ret, str + 1, + get_var_expand_table(service, user, &user->input, priv)); return str_c(ret); } @@ -492,9 +508,9 @@ service_parse_privileges(struct mail_storage_service_ctx *ctx, /* variable strings are expanded in mail_user_init(), but we need the home and chroot sooner so do them separately here. */ - priv_r->home = user_expand_varstr(ctx->service, &user->input, priv_r, + priv_r->home = user_expand_varstr(ctx->service, user, priv_r, user->user_set->mail_home); - priv_r->chroot = user_expand_varstr(ctx->service, &user->input, priv_r, + priv_r->chroot = user_expand_varstr(ctx->service, user, priv_r, user->user_set->mail_chroot); return 0; } @@ -627,6 +643,7 @@ mail_storage_service_init_post(struct mail_storage_service_ctx *ctx, mail_user->anonymous = user->anonymous; mail_user->admin = user->admin; mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token); + mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user); mail_set = mail_user_set_get_storage_set(mail_user); @@ -699,7 +716,7 @@ mail_storage_service_init_log(struct mail_storage_service_ctx *ctx, str = t_str_new(256); var_expand(str, user->user_set->mail_log_prefix, - get_var_expand_table(ctx->service, &user->input, priv)); + get_var_expand_table(ctx->service, user, &user->input, priv)); user->log_prefix = p_strdup(user->pool, str_c(str)); } T_END; diff --git a/src/lib-storage/mail-user.c b/src/lib-storage/mail-user.c index 52f45476c7..d36665ca83 100644 --- a/src/lib-storage/mail-user.c +++ b/src/lib-storage/mail-user.c @@ -207,6 +207,9 @@ mail_user_var_expand_table(struct mail_user *user) { 'p', NULL, "pid" }, { 'i', NULL, "uid" }, { '\0', NULL, "gid" }, + { '\0', NULL, "auth_user" }, + { '\0', NULL, "auth_username" }, + { '\0', NULL, "auth_domain" }, { '\0', NULL, NULL } }; struct var_expand_table *tab; @@ -232,6 +235,15 @@ mail_user_var_expand_table(struct mail_user *user) tab[7].value = my_pid; tab[8].value = p_strdup(user->pool, dec2str(user->uid)); tab[9].value = p_strdup(user->pool, dec2str(user->gid)); + if (user->auth_user == NULL) { + tab[10].value = tab[0].value; + tab[11].value = tab[1].value; + tab[12].value = tab[2].value; + } else { + tab[10].value = user->auth_user; + tab[11].value = t_strcut(user->auth_user, '@'); + tab[12].value = strchr(user->auth_user, '@'); + } user->var_expand_table = tab; return user->var_expand_table; diff --git a/src/lib-storage/mail-user.h b/src/lib-storage/mail-user.h index 54cbb9163b..bdd3a1b14b 100644 --- a/src/lib-storage/mail-user.h +++ b/src/lib-storage/mail-user.h @@ -24,7 +24,7 @@ struct mail_user { gid_t gid; const char *service; struct ip_addr *local_ip, *remote_ip; - const char *auth_token; + const char *auth_token, *auth_user; const struct var_expand_table *var_expand_table; /* If non-NULL, fail the user initialization with this error. diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index ce6e9f7967..ae17b9d566 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -273,6 +273,7 @@ bool client_unref(struct client **_client) i_free(client->proxy_master_user); i_free(client->virtual_user); i_free(client->virtual_user_orig); + i_free(client->virtual_auth_user); i_free(client->auth_mech_name); i_free(client->master_data_prefix); pool_unref(&client->pool); @@ -474,28 +475,37 @@ static struct var_expand_table login_var_expand_empty_tab[] = { { '\0', NULL, "orig_user" }, { '\0', NULL, "orig_username" }, { '\0', NULL, "orig_domain" }, + { '\0', NULL, "auth_user" }, + { '\0', NULL, "auth_username" }, + { '\0', NULL, "auth_domain" }, { '\0', NULL, NULL } }; +static void +get_var_expand_users(struct var_expand_table *tab, const char *user) +{ + unsigned int i; + + tab[0].value = user; + tab[1].value = t_strcut(user, '@'); + tab[2].value = strchr(user, '@'); + if (tab[2].value != NULL) tab[2].value++; + + for (i = 0; i < 3; i++) + tab[i].value = str_sanitize(tab[i].value, 80); +} + static const struct var_expand_table * get_var_expand_table(struct client *client) { struct var_expand_table *tab; - unsigned int i; tab = t_malloc(sizeof(login_var_expand_empty_tab)); memcpy(tab, login_var_expand_empty_tab, sizeof(login_var_expand_empty_tab)); - if (client->virtual_user != NULL) { - tab[0].value = client->virtual_user; - tab[1].value = t_strcut(client->virtual_user, '@'); - tab[2].value = strchr(client->virtual_user, '@'); - if (tab[2].value != NULL) tab[2].value++; - - for (i = 0; i < 3; i++) - tab[i].value = str_sanitize(tab[i].value, 80); - } + if (client->virtual_user != NULL) + get_var_expand_users(tab, client->virtual_user); tab[3].value = login_binary->protocol; tab[4].value = getenv("HOME"); tab[5].value = net_ip2addr(&client->local_ip); @@ -527,18 +537,19 @@ get_var_expand_table(struct client *client) tab[16].value = net_ip2addr(&client->real_remote_ip); tab[17].value = dec2str(client->real_local_port); tab[18].value = dec2str(client->real_remote_port); - if (client->virtual_user_orig == NULL) { + if (client->virtual_user_orig != NULL) + get_var_expand_users(tab+19, client->virtual_user_orig); + else { tab[19].value = tab[0].value; tab[20].value = tab[1].value; tab[21].value = tab[2].value; - } else { - tab[19].value = client->virtual_user_orig; - tab[20].value = t_strcut(client->virtual_user_orig, '@'); - tab[21].value = strchr(client->virtual_user_orig, '@'); - if (tab[21].value != NULL) tab[21].value++; - - for (i = 0; i < 3; i++) - tab[i].value = str_sanitize(tab[i].value, 80); + } + if (client->virtual_auth_user != NULL) + get_var_expand_users(tab+22, client->virtual_auth_user); + else { + tab[22].value = tab[0].value; + tab[23].value = tab[1].value; + tab[24].value = tab[2].value; } return tab; } diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 89ee4c69d1..915207186b 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -142,7 +142,7 @@ struct client { unsigned int auth_attempts, auth_successes; pid_t mail_pid; - char *virtual_user, *virtual_user_orig; + char *virtual_user, *virtual_user_orig, *virtual_auth_user; unsigned int destroyed:1; unsigned int input_blocked:1; unsigned int login_success:1; diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index a90141d277..96b378ae4f 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -240,10 +240,15 @@ authenticate_callback(struct auth_client_request *request, if (strncmp(args[i], "user=", 5) == 0) { i_free(client->virtual_user); i_free_and_null(client->virtual_user_orig); + i_free_and_null(client->virtual_auth_user); client->virtual_user = i_strdup(args[i] + 5); } else if (strncmp(args[i], "original_user=", 14) == 0) { i_free(client->virtual_user_orig); client->virtual_user_orig = i_strdup(args[i] + 14); + } else if (strncmp(args[i], "auth_user=", 10) == 0) { + i_free(client->virtual_auth_user); + client->virtual_auth_user = + i_strdup(args[i] + 10); } else if (strcmp(args[i], "nologin") == 0 || strcmp(args[i], "proxy") == 0) { /* user can't login */ @@ -276,12 +281,17 @@ authenticate_callback(struct auth_client_request *request, if (strncmp(args[i], "user=", 5) == 0) { i_free(client->virtual_user); i_free_and_null(client->virtual_user_orig); + i_free_and_null(client->virtual_auth_user); client->virtual_user = i_strdup(args[i] + 5); } else if (strncmp(args[i], "original_user=", 14) == 0) { i_free(client->virtual_user_orig); client->virtual_user_orig = i_strdup(args[i] + 14); + } else if (strncmp(args[i], "auth_user=", 10) == 0) { + i_free(client->virtual_auth_user); + client->virtual_auth_user = + i_strdup(args[i] + 10); } } }