]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth, login, mail: Added %{auth_user}, %{auth_username} and %{auth_domain}
authorTimo Sirainen <tss@iki.fi>
Tue, 14 Jan 2014 01:24:47 +0000 (03:24 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 14 Jan 2014 01:24:47 +0000 (03:24 +0200)
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.

src/auth/auth-request-handler.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-user.c
src/lib-storage/mail-user.h
src/login-common/client-common.c
src/login-common/client-common.h
src/login-common/sasl-server.c

index 50a82e08988b6e2e2641cbcbf036be733f8b4e72..c0f2bcc508a9ac433f8a5586bafd06567c183296 100644 (file)
@@ -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);
index dea26f51b7d9fac85217fe88261fad9d3c2ef720..65f4d160a59b6588581552bdaddf3c2b91ecdcd8 100644 (file)
@@ -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;
 
index 52f45476c73a7ce309dfa5ff3c673988ca86e0e6..d36665ca8332f452f34487064fc290fe0ce4be6e 100644 (file)
@@ -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;
index 54cbb9163b777c735fb58bf1f45c5490bcd8074f..bdd3a1b14b324b651bed8944e8feae7d17175449 100644 (file)
@@ -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.
index ce6e9f796772efc4c57349cb03e82e6b71157173..ae17b9d566ca68856f1fbcb2b1ba9482a8e1ad41 100644 (file)
@@ -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;
 }
index 89ee4c69d10fb329a33d5207e4fbb3e00f17713f..915207186b172e193e997e5ef752e0edb41a1de8 100644 (file)
@@ -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;
index a90141d2778c0571889b7f6a979fd404c34c4a10..96b378ae4fe4409a014c45434b72878c90375fb2 100644 (file)
@@ -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);
                                }
                        }
                }