]> 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)
committerGitLab <gitlab@git.dovecot.net>
Thu, 6 Jul 2017 15:38:31 +0000 (18:38 +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 b37b7b73e456e889e5913efca8c642e6d1ff864f..d5d88495b10da55fbc448b79fd539ccaa2198a06 100644 (file)
@@ -651,6 +651,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)
 {
@@ -678,15 +679,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);
        
@@ -1359,6 +1368,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,
                               const char **error_r)
 {
@@ -1438,6 +1448,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_r) < 0)
                return -2;
        return 0;
@@ -1447,6 +1458,19 @@ int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
                              struct mail_storage_service_user *user,
                              struct mail_user **mail_user_r,
                              const char **error_r)
+{
+       return mail_storage_service_next_with_session_suffix(ctx,
+                                                            user,
+                                                            NULL,
+                                                            mail_user_r,
+                                                            error_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,
+                                                 const char **error_r)
 {
        char *old_log_prefix = i_strdup(i_get_failure_prefix());
        int ret;
@@ -1454,7 +1478,9 @@ 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, error_r);
+       ret = mail_storage_service_next_real(ctx, user,
+                                            session_id_suffix,
+                                            mail_user_r, error_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 22f5b0403496c48428508b35d8f1b9330b831413..e047a719f611ed4813343dbaa0d9399174264c54 100644 (file)
@@ -102,6 +102,12 @@ int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
                              struct mail_storage_service_user *user,
                              struct mail_user **mail_user_r,
                              const char **error_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,
+                                                  const char **error_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 fd71a0405d2ec7a4e39aea310a06a1768f83d3f5..770406a2677cca3b0fa95e858afea8847108c822 100644 (file)
@@ -554,8 +554,18 @@ 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, &errstr);
+       /* 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, &errstr);
+
        if (ret < 0) {
                i_error("Failed to initialize user %s: %s", rcpt->address, errstr);
                return -1;