From: Stephan Bosch Date: Wed, 27 Mar 2019 00:25:57 +0000 (+0100) Subject: lib-lda: Initialize/deinitialize mail_deliver_context in separate functions. X-Git-Tag: 2.3.8~80 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3dc59dc2f51aaa7b6c6e1e2f5f3f5e558f0d74df;p=thirdparty%2Fdovecot%2Fcore.git lib-lda: Initialize/deinitialize mail_deliver_context in separate functions. This changes the allocation of parsed SMTP addresses to initially use a datastack pool rather than the mail_deliver context pool. This is necessary because the context is created a bit later. Upon mail_deliver_init(), the addresses are moved to the context pool. --- diff --git a/src/lda/main.c b/src/lda/main.c index 643e749945..57aa76ef29 100644 --- a/src/lda/main.c +++ b/src/lda/main.c @@ -46,12 +46,12 @@ static const char *wanted_headers[] = { static int seekable_fd_callback(const char **path_r, void *context) { - struct mail_deliver_context *ctx = context; + struct mail_deliver_input *dinput = context; string_t *path; int fd; path = t_str_new(128); - mail_user_set_get_temp_prefix(path, ctx->rcpt_user->set); + mail_user_set_get_temp_prefix(path, dinput->rcpt_user->set); fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); if (fd == -1) { i_error("safe_mkstemp(%s) failed: %m", str_c(path)); @@ -70,7 +70,7 @@ static int seekable_fd_callback(const char **path_r, void *context) } static struct istream * -create_raw_stream(struct mail_deliver_context *ctx, +create_raw_stream(struct mail_deliver_input *dinput, int fd, time_t *mtime_r) { struct istream *input, *input2, *input_list[2]; @@ -105,16 +105,17 @@ create_raw_stream(struct mail_deliver_context *ctx, } } - if (sender != NULL && ctx->mail_from == NULL) { + if (sender != NULL && dinput->mail_from == NULL) { struct smtp_address *mail_from = NULL; /* use the envelope sender from From_-line, but only if it hasn't been specified with -f already. */ - if (smtp_address_parse_mailbox(ctx->pool, - sender, 0, &mail_from, &error) < 0) { + if (smtp_address_parse_mailbox(pool_datastack_create(), + sender, 0, &mail_from, + &error) < 0) { i_warning("Failed to parse address from `From_'-line: %s", error); } - ctx->mail_from = mail_from; + dinput->mail_from = mail_from; } i_free(sender); @@ -128,13 +129,13 @@ create_raw_stream(struct mail_deliver_context *ctx, input_list[0] = input2; input_list[1] = NULL; input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER, - seekable_fd_callback, ctx); + seekable_fd_callback, dinput); i_stream_unref(&input2); return input; } static struct mail * -lda_raw_mail_open(struct mail_deliver_context *ctx, const char *path) +lda_raw_mail_open(struct mail_deliver_input *dinput, const char *path) { struct mail_user *raw_mail_user; struct mailbox *box; @@ -148,13 +149,13 @@ lda_raw_mail_open(struct mail_deliver_context *ctx, const char *path) int ret; sets = master_service_settings_get_others(master_service); - raw_mail_user = - raw_storage_create_from_set(ctx->rcpt_user->set_info, sets[0]); + raw_mail_user = raw_storage_create_from_set(dinput->rcpt_user->set_info, + sets[0]); - mail_from = ctx->mail_from != NULL ? - ctx->mail_from : DEFAULT_ENVELOPE_SENDER; + mail_from = (dinput->mail_from != NULL ? + dinput->mail_from : DEFAULT_ENVELOPE_SENDER); if (path == NULL) { - input = create_raw_stream(ctx, 0, &mtime); + input = create_raw_stream(dinput, 0, &mtime); i_stream_set_name(input, "stdin"); ret = raw_mailbox_alloc_stream(raw_mail_user, input, mtime, smtp_address_encode(mail_from), &box); @@ -178,39 +179,41 @@ lda_raw_mail_open(struct mail_deliver_context *ctx, const char *path) } static void -lda_set_rcpt_to(struct mail_deliver_context *ctx, +lda_set_rcpt_to(struct mail_deliver_input *dinput, const struct smtp_address *rcpt_to, const char *user, const char *rcpt_to_source) { const char *error; if (rcpt_to == NULL && - *ctx->set->lda_original_recipient_header != '\0') { - rcpt_to = mail_deliver_get_address(ctx->src_mail, - ctx->set->lda_original_recipient_header); + *dinput->set->lda_original_recipient_header != '\0') { + rcpt_to = mail_deliver_get_address( + dinput->src_mail, + dinput->set->lda_original_recipient_header); rcpt_to_source = t_strconcat( - ctx->set->lda_original_recipient_header, " header", NULL); + dinput->set->lda_original_recipient_header, + " header", NULL); } if (rcpt_to == NULL) { struct smtp_address *user_addr; - if (smtp_address_parse_username(ctx->pool, user, - &user_addr, &error) < 0) { + if (smtp_address_parse_username(pool_datastack_create(), user, + &user_addr, &error) < 0) { i_fatal_status(EX_USAGE, "Cannot obtain SMTP address from username `%s': %s", user, error); } if (user_addr->domain == NULL) - user_addr->domain = ctx->set->hostname; + user_addr->domain = dinput->set->hostname; rcpt_to = user_addr; rcpt_to_source = "user@hostname"; } - ctx->rcpt_params.orcpt.addr = rcpt_to; - if (ctx->rcpt_to == NULL) - ctx->rcpt_to = rcpt_to; + dinput->rcpt_params.orcpt.addr = rcpt_to; + if (dinput->rcpt_to == NULL) + dinput->rcpt_to = rcpt_to; - e_debug(ctx->rcpt_user->event, + e_debug(dinput->rcpt_user->event, "Destination address: %s (source: %s)", smtp_address_encode_path(rcpt_to), rcpt_to_source); } @@ -268,40 +271,44 @@ lda_do_deliver(struct mail_deliver_context *ctx, bool stderr_rejection) } static int -lda_deliver(struct mail_deliver_context *ctx, +lda_deliver(struct mail_deliver_input *dinput, struct mail_storage_service_user *service_user, const char *user, const char *path, struct smtp_address *rcpt_to, const char *rcpt_to_source, bool stderr_rejection) { + struct mail_deliver_context ctx; const struct var_expand_table *var_table; struct lda_settings *lda_set; struct smtp_submit_settings *smtp_set; const char *errstr; int ret; - var_table = mail_user_var_expand_table(ctx->rcpt_user); + var_table = mail_user_var_expand_table(dinput->rcpt_user); smtp_set = mail_storage_service_user_get_set(service_user)[1]; lda_set = mail_storage_service_user_get_set(service_user)[2]; ret = settings_var_expand( &lda_setting_parser_info, - lda_set, ctx->rcpt_user->pool, var_table, + lda_set, dinput->rcpt_user->pool, var_table, &errstr); if (ret > 0) { ret = settings_var_expand( &smtp_submit_setting_parser_info, - smtp_set, ctx->rcpt_user->pool, var_table, + smtp_set, dinput->rcpt_user->pool, var_table, &errstr); } if (ret <= 0) i_fatal("Failed to expand settings: %s", errstr); - ctx->set = lda_set; - ctx->smtp_set = smtp_set; + dinput->set = lda_set; + dinput->smtp_set = smtp_set; + + dinput->src_mail = lda_raw_mail_open(dinput, path); + lda_set_rcpt_to(dinput, rcpt_to, user, rcpt_to_source); - ctx->src_mail = lda_raw_mail_open(ctx, path); - lda_set_rcpt_to(ctx, rcpt_to, user, rcpt_to_source); + mail_deliver_init(&ctx, dinput); + ret = lda_do_deliver(&ctx, stderr_rejection); + mail_deliver_deinit(&ctx); - ret = lda_do_deliver(ctx, stderr_rejection); return ret; } @@ -346,7 +353,7 @@ int main(int argc, char *argv[]) &lda_setting_parser_info, NULL }; - struct mail_deliver_context ctx; + struct mail_deliver_input dinput; enum mail_storage_service_flags service_flags = 0; const char *user, *errstr, *path; struct smtp_address *rcpt_to, *final_rcpt_to, *mail_from; @@ -384,10 +391,9 @@ int main(int argc, char *argv[]) MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME, &argc, &argv, "a:d:ef:m:p:r:"); - i_zero(&ctx); - ctx.session = mail_deliver_session_init(); - ctx.pool = ctx.session->pool; - ctx.rcpt_default_mailbox = "INBOX"; + i_zero(&dinput); + dinput.session = mail_deliver_session_init(); + dinput.rcpt_default_mailbox = "INBOX"; path = NULL; user = getenv("USER"); @@ -396,10 +402,11 @@ int main(int argc, char *argv[]) switch (c) { case 'a': /* original recipient address */ - if (smtp_address_parse_path(ctx.pool, optarg, - SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | + if (smtp_address_parse_path( + pool_datastack_create(), optarg, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL, - &rcpt_to, &errstr) < 0) { + &rcpt_to, &errstr) < 0) { i_fatal_status(EX_USAGE, "Invalid -a parameter: %s", errstr); } @@ -415,11 +422,12 @@ int main(int argc, char *argv[]) break; case 'f': /* envelope sender address */ - if (smtp_address_parse_path(ctx.pool, optarg, - SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL | + if (smtp_address_parse_path( + pool_datastack_create(), optarg, + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL | SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY, - &mail_from, &errstr) < 0) { + &mail_from, &errstr) < 0) { i_fatal_status(EX_USAGE, "Invalid -f parameter: %s", errstr); } @@ -433,7 +441,7 @@ int main(int argc, char *argv[]) i_fatal("Mailbox name not UTF-8: %s", optarg); } - ctx.rcpt_default_mailbox = optarg; + dinput.rcpt_default_mailbox = optarg; } T_END; break; case 'p': @@ -445,10 +453,11 @@ int main(int argc, char *argv[]) break; case 'r': /* final recipient address */ - if (smtp_address_parse_path(ctx.pool, optarg, - SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | + if (smtp_address_parse_path( + pool_datastack_create(), optarg, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL, - &final_rcpt_to, &errstr) < 0) { + &final_rcpt_to, &errstr) < 0) { i_fatal_status(EX_USAGE, "Invalid -r parameter: %s", errstr); } @@ -505,9 +514,10 @@ int main(int argc, char *argv[]) mail_deliver_hooks_init(); /* set before looking up the user (or ideally we'd do this between _lookup() and _next(), but don't bother) */ - ctx.delivery_time_started = ioloop_timeval; - ret = mail_storage_service_lookup_next(storage_service, &service_input, - &service_user, &ctx.rcpt_user, + dinput.delivery_time_started = ioloop_timeval; + ret = mail_storage_service_lookup_next(storage_service, + &service_input, &service_user, + &dinput.rcpt_user, &errstr); if (ret <= 0) { if (ret < 0) @@ -518,29 +528,29 @@ int main(int argc, char *argv[]) lib_signals_ignore(SIGXFSZ, TRUE); #endif if (*user_source != '\0') { - e_debug(ctx.rcpt_user->event, + e_debug(dinput.rcpt_user->event, "userdb lookup skipped, username taken from %s", user_source); } - ctx.mail_from = mail_from; - ctx.rcpt_to = final_rcpt_to; + dinput.mail_from = mail_from; + dinput.rcpt_to = final_rcpt_to; - ret = lda_deliver(&ctx, service_user, user, path, + ret = lda_deliver(&dinput, service_user, user, path, rcpt_to, rcpt_to_source, stderr_rejection); struct mailbox_transaction_context *t = - ctx.src_mail->transaction; - struct mailbox *box = ctx.src_mail->box; + dinput.src_mail->transaction; + struct mailbox *box = dinput.src_mail->box; - mail_free(&ctx.src_mail); + mail_free(&dinput.src_mail); mailbox_transaction_rollback(&t); mailbox_free(&box); - mail_user_unref(&ctx.rcpt_user); + mail_user_unref(&dinput.rcpt_user); mail_storage_service_user_unref(&service_user); } - mail_deliver_session_deinit(&ctx.session); + mail_deliver_session_deinit(&dinput.session); mail_storage_service_deinit(&storage_service); master_service_deinit(&master_service); return ret; diff --git a/src/lib-lda/mail-deliver.c b/src/lib-lda/mail-deliver.c index c0280c40ec..91132409e3 100644 --- a/src/lib-lda/mail-deliver.c +++ b/src/lib-lda/mail-deliver.c @@ -291,6 +291,39 @@ void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *sessio } } +void mail_deliver_init(struct mail_deliver_context *ctx, + struct mail_deliver_input *input) +{ + i_zero(ctx); + ctx->set = input->set; + ctx->smtp_set = input->smtp_set; + + ctx->session = input->session; + ctx->pool = input->session->pool; + pool_ref(ctx->pool); + + ctx->session_time_msecs = input->session_time_msecs; + ctx->delivery_time_started = input->delivery_time_started; + ctx->session_id = p_strdup(ctx->pool, input->session_id); + ctx->src_mail = input->src_mail; + ctx->save_dest_mail = input->save_dest_mail; + + ctx->mail_from = smtp_address_clone(ctx->pool, input->mail_from); + smtp_params_mail_copy(ctx->pool, &ctx->mail_params, + &input->mail_params); + ctx->rcpt_to = smtp_address_clone(ctx->pool, input->rcpt_to); + smtp_params_rcpt_copy(ctx->pool, &ctx->rcpt_params, + &input->rcpt_params); + ctx->rcpt_user = input->rcpt_user; + ctx->rcpt_default_mailbox = p_strdup(ctx->pool, + input->rcpt_default_mailbox); +} + +void mail_deliver_deinit(struct mail_deliver_context *ctx) +{ + pool_unref(&ctx->pool); +} + static struct mail * mail_deliver_open_mail(struct mailbox *box, uint32_t uid, enum mail_fetch_field wanted_fields, diff --git a/src/lib-lda/mail-deliver.h b/src/lib-lda/mail-deliver.h index 68e6456e36..8ff9c7a5a1 100644 --- a/src/lib-lda/mail-deliver.h +++ b/src/lib-lda/mail-deliver.h @@ -20,6 +20,37 @@ struct mail_deliver_session { ARRAY(guid_128_t) inbox_guids; }; +struct mail_deliver_input { + const struct lda_settings *set; + const struct smtp_submit_settings *smtp_set; + struct mail_deliver_session *session; + + unsigned int session_time_msecs; + struct timeval delivery_time_started; + + /* Session ID, used as log line prefix if non-NULL. */ + const char *session_id; + /* Mail to save */ + struct mail *src_mail; + + /* Envelope sender, if known. */ + const struct smtp_address *mail_from; + /* MAIL parameters */ + struct smtp_params_mail mail_params; + + /* Envelope recipient (final recipient) */ + const struct smtp_address *rcpt_to; + /* RCPT parameters (can contain original recipient) */ + struct smtp_params_rcpt rcpt_params; + /* Destination user */ + struct mail_user *rcpt_user; + /* Mailbox where mail should be saved, unless e.g. Sieve does + something to it. */ + const char *rcpt_default_mailbox; + + bool save_dest_mail:1; +}; + struct mail_deliver_context { pool_t pool; const struct lda_settings *set; @@ -98,6 +129,10 @@ const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx); struct mail_deliver_session *mail_deliver_session_init(void); void mail_deliver_session_deinit(struct mail_deliver_session **session); +void mail_deliver_init(struct mail_deliver_context *ctx, + struct mail_deliver_input *input); +void mail_deliver_deinit(struct mail_deliver_context *ctx); + /* Try to open mailbox for saving. Returns 0 if ok, -1 if error. The box may be returned even with -1, and the caller must free it then. */ int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx, diff --git a/src/lmtp/lmtp-local.c b/src/lmtp/lmtp-local.c index 302a188af5..cf4db8cc5e 100644 --- a/src/lmtp/lmtp-local.c +++ b/src/lmtp/lmtp-local.c @@ -568,47 +568,48 @@ int lmtp_local_default_deliver(struct client *client, struct smtp_server_recipient *rcpt = lrcpt->rcpt; struct smtp_address *rcpt_to = rcpt->path; unsigned int rcpt_idx = rcpt->index; + struct mail_deliver_input dinput; struct mail_deliver_context dctx; struct mail_storage *storage; enum mail_error mail_error; const char *error; int ret; - i_zero(&dctx); - dctx.session = lldctx->session; - dctx.pool = lldctx->session->pool; - dctx.set = lldctx->lda_set; - dctx.smtp_set = lldctx->smtp_set; - dctx.session_id = lldctx->session_id; - dctx.src_mail = lldctx->src_mail; + i_zero(&dinput); + dinput.session = lldctx->session; + dinput.set = lldctx->lda_set; + dinput.smtp_set = lldctx->smtp_set; + dinput.session_id = lldctx->session_id; + dinput.src_mail = lldctx->src_mail; /* MAIL FROM */ - dctx.mail_from = trans->mail_from; - smtp_params_mail_copy(dctx.pool, - &dctx.mail_params, &trans->params); + dinput.mail_from = trans->mail_from; + dinput.mail_params = trans->params; /* RCPT TO */ - dctx.rcpt_user = lldctx->rcpt_user; - smtp_params_rcpt_copy(dctx.pool, &dctx.rcpt_params, &rcpt->params); - if (dctx.rcpt_params.orcpt.addr == NULL && - *dctx.set->lda_original_recipient_header != '\0') { - dctx.rcpt_params.orcpt.addr = - mail_deliver_get_address(lldctx->src_mail, - dctx.set->lda_original_recipient_header); + dinput.rcpt_user = lldctx->rcpt_user; + dinput.rcpt_params = rcpt->params; + if (dinput.rcpt_params.orcpt.addr == NULL && + *dinput.set->lda_original_recipient_header != '\0') { + dinput.rcpt_params.orcpt.addr = + mail_deliver_get_address( + lldctx->src_mail, + dinput.set->lda_original_recipient_header); } - if (dctx.rcpt_params.orcpt.addr == NULL) - dctx.rcpt_params.orcpt.addr = rcpt_to; - dctx.rcpt_to = rcpt_to; - dctx.rcpt_default_mailbox = lldctx->rcpt_default_mailbox; + if (dinput.rcpt_params.orcpt.addr == NULL) + dinput.rcpt_params.orcpt.addr = rcpt_to; + dinput.rcpt_to = rcpt_to; + dinput.rcpt_default_mailbox = lldctx->rcpt_default_mailbox; - dctx.save_dest_mail = array_count(&trans->rcpt_to) > 1 && + dinput.save_dest_mail = array_count(&trans->rcpt_to) > 1 && local->first_saved_mail == NULL; - dctx.session_time_msecs = + dinput.session_time_msecs = timeval_diff_msecs(&client->state.data_end_timeval, &trans->timestamp); - dctx.delivery_time_started = lldctx->delivery_time_started; + dinput.delivery_time_started = lldctx->delivery_time_started; + mail_deliver_init(&dctx, &dinput); if (mail_deliver(&dctx, &storage) == 0) { if (dctx.dest_mail != NULL) { i_assert(local->first_saved_mail == NULL); @@ -642,6 +643,8 @@ int lmtp_local_default_deliver(struct client *client, smtp_address_encode(rcpt_to)); ret = -1; } + mail_deliver_deinit(&dctx); + return ret; }