]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp: Fix for wrong session id of mail user when saving mail, quota checking on
authorSergey Kitov <sergey.kitov@open-xchange.com>
Thu, 6 Jul 2017 12:45:24 +0000 (15:45 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 12 Sep 2017 10:50:33 +0000 (13:50 +0300)
When quota is checked mail user is allocated with custom ":quota" session id
suffix without incrementing service user session id counter

src/lib-storage/mail-storage-service.c
src/lib-storage/mail-storage-service.h
src/lmtp/commands.c

index a60eb5787b192331095033aac448c6091d0a9bcb..c0d1ffb05c574614f65ab3e315f42c164eab9053 100644 (file)
@@ -643,6 +643,7 @@ static int
 mail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
                               struct mail_storage_service_user *user,
                               struct mail_storage_service_privileges *priv,
+                              const char *session_id_suffix,
                               struct mail_user **mail_user_r,
                               const char **error_r)
 {
@@ -670,15 +671,23 @@ mail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
                        user->input.session_create_time;
                mail_user->session_restored = TRUE;
        }
-       if (user->session_id_counter++ == 0) {
-               mail_user->session_id =
-                       p_strdup(mail_user->pool, user->input.session_id);
-       } else {
+
+       if (session_id_suffix == NULL) {
+               if (user->session_id_counter++ == 0) {
+                       mail_user->session_id =
+                               p_strdup(mail_user->pool, user->input.session_id);
+               } else {
+                       mail_user->session_id =
+                               p_strdup_printf(mail_user->pool, "%s:%u",
+                                               user->input.session_id,
+                                               user->session_id_counter);
+               }
+       } else
                mail_user->session_id =
-                       p_strdup_printf(mail_user->pool, "%s:%u",
+                       p_strdup_printf(mail_user->pool, "%s:%s",
                                        user->input.session_id,
-                                       user->session_id_counter);
-       }
+                                       session_id_suffix);
+
        mail_user->userdb_fields = user->input.userdb_fields == NULL ? NULL :
                p_strarray_dup(mail_user->pool, user->input.userdb_fields);
        
@@ -1367,6 +1376,7 @@ void mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx *ct
 static int
 mail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
                               struct mail_storage_service_user *user,
+                              const char *session_id_suffix,
                               struct mail_user **mail_user_r)
 {
        struct mail_storage_service_privileges priv;
@@ -1445,6 +1455,7 @@ mail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
        module_dir_init(mail_storage_service_modules);
 
        if (mail_storage_service_init_post(ctx, user, &priv,
+                                          session_id_suffix,
                                           mail_user_r, &error) < 0) {
                i_error("User initialization failed: %s", error);
                return -2;
@@ -1455,6 +1466,17 @@ mail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
 int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
                              struct mail_storage_service_user *user,
                              struct mail_user **mail_user_r)
+{
+       return mail_storage_service_next_with_session_suffix(ctx,
+                                                            user,
+                                                            NULL,
+                                                            mail_user_r);
+}
+
+int mail_storage_service_next_with_session_suffix(struct mail_storage_service_ctx *ctx,
+                                                 struct mail_storage_service_user *user,
+                                                 const char *session_id_suffix,
+                                                 struct mail_user **mail_user_r)
 {
        char *old_log_prefix = i_strdup(i_get_failure_prefix());
        int ret;
@@ -1462,7 +1484,8 @@ int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
        mail_storage_service_set_log_prefix(ctx, user->user_set, user,
                                            &user->input, NULL);
        i_set_failure_prefix("%s", old_log_prefix);
-       ret = mail_storage_service_next_real(ctx, user, mail_user_r);
+       ret = mail_storage_service_next_real(ctx, user, session_id_suffix,
+                                            mail_user_r);
        if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) != 0)
                i_set_failure_prefix("%s", old_log_prefix);
        i_free(old_log_prefix);
index b71b34df19bb8a74616d5c38d979ca20dfa0af16..b75983a11b1ecd5b4afeadd2ba47aa76ed5db260 100644 (file)
@@ -102,6 +102,11 @@ void mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx *ct
 int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
                              struct mail_storage_service_user *user,
                              struct mail_user **mail_user_r);
+/* Returns 0 if ok, -1 if fatal error, -2 if error is user-specific. */
+int mail_storage_service_next_with_session_suffix(struct mail_storage_service_ctx *ctx,
+                                                 struct mail_storage_service_user *user,
+                                                 const char *session_id_postfix,
+                                                 struct mail_user **mail_user_r);
 void mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
                                          struct mail_storage_service_user *user);
 /* Combine lookup() and next() into one call. */
index 3fe90f8fe88567c5be3d0a99b63728c6f648e4a0..2496c1f8a9466fefd1be36dd3fbc60c22c9c3cca 100644 (file)
@@ -552,8 +552,17 @@ lmtp_rcpt_to_is_over_quota(struct client *client,
        if (!client->lmtp_set->lmtp_rcpt_check_quota)
                return 0;
 
-       ret = mail_storage_service_next(storage_service,
-                                       rcpt->service_user, &user);
+       /* mail user will be created second time when mail is saved,
+          so it's session_id needs to be different,
+          but second time session_id needs to be the same as rcpt session_id and
+          mail user session id for the first rcpt should not overlap with session id
+          of the second recipient, so add custom ":quota" suffix to the session_id without
+          session_id counter increment, so next time mail user will get
+          the same session id as rcpt */
+       ret = mail_storage_service_next_with_session_suffix(storage_service,
+                                                           rcpt->service_user,
+                                                           "quota",
+                                                           &user);
        if (ret < 0)
                return -1;