-/* $OpenBSD: smtp_session.c,v 1.283 2016/07/02 09:32:30 eric Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.284 2016/07/22 12:12:29 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
static void smtp_rfc4954_auth_plain(struct smtp_session *, char *);
static void smtp_rfc4954_auth_login(struct smtp_session *, char *);
static void smtp_message_end(struct smtp_session *);
-static void smtp_message_reset(struct smtp_session *, int);
static int smtp_message_printf(struct smtp_session *, const char *, ...);
static void smtp_free(struct smtp_session *, const char *);
static const char *smtp_strstate(int);
if ((s = calloc(1, sizeof(*s))) == NULL)
return (-1);
- if (smtp_tx(s) == 0) {
- free(s);
- return -1;
- }
-
if (iobuf_init(&s->iobuf, LINE_MAX, LINE_MAX) == -1) {
- smtp_tx_free(s->tx);
free(s);
return (-1);
}
- TAILQ_INIT(&s->tx->rcpts);
s->id = generate_uid();
s->listener = listener;
io_init(&s->io, sock, s, smtp_io, &s->iobuf);
io_set_timeout(&s->io, SMTPD_SESSION_TIMEOUT * 1000);
io_set_write(&s->io);
- io_init(&s->tx->oev, -1, s, NULL, NULL); /* initialise 'sock', but not to 0 */
s->state = STATE_NEW;
s->phase = PHASE_INIT;
"[hostname=%s, port=%d, tag=%s]", s, listener,
listener->hostname, ntohs(listener->port), listener->tag);
- /* Setup parser and callbacks before smtp_connected() can be called */
- rfc2822_parser_init(&s->tx->rfc2822_parser);
- rfc2822_header_default_callback(&s->tx->rfc2822_parser,
- header_default_callback, s);
- rfc2822_header_callback(&s->tx->rfc2822_parser, "bcc",
- header_bcc_callback, s);
- rfc2822_header_callback(&s->tx->rfc2822_parser, "from",
- header_domain_append_callback, s);
- rfc2822_header_callback(&s->tx->rfc2822_parser, "to",
- header_domain_append_callback, s);
- rfc2822_header_callback(&s->tx->rfc2822_parser, "cc",
- header_domain_append_callback, s);
- rfc2822_body_callback(&s->tx->rfc2822_parser,
- dataline_callback, s);
-
- if (listener->local || listener->port == 587) {
- rfc2822_missing_header_callback(&s->tx->rfc2822_parser, "date",
- header_missing_callback, s);
- rfc2822_missing_header_callback(&s->tx->rfc2822_parser, "message-id",
- header_missing_callback, s);
- }
-
/* For local enqueueing, the hostname is already set */
if (hostname) {
s->flags |= SF_AUTHENTICATED;
case LKA_PERMFAIL:
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
smtp_reply(s, "%d %s", 530, "Sender rejected");
io_reload(&s->io);
break;
case LKA_TEMPFAIL:
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
smtp_reply(s, "421 %s: Temporary Error",
esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
io_reload(&s->io);
esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
} else {
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
smtp_reply(s, "421 %s: Temporary Error",
esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
smtp_enter_state(s, STATE_QUIT);
s = tree_xpop(&wait_queue_commit, reqid);
if (!success) {
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
smtp_reply(s, "421 %s: Temporary failure",
esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
smtp_enter_state(s, STATE_QUIT);
rcpt->destcount,
s->flags & SF_EHLO ? "ESMTP" : "SMTP");
}
-
+ smtp_tx_free(s->tx);
s->mailcount++;
s->phase = PHASE_SETUP;
- smtp_message_reset(s, 0);
smtp_enter_state(s, STATE_HELO);
io_reload(&s->io);
return;
case QUERY_MAIL:
if (status != FILTER_OK) {
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
code = code ? code : 530;
line = line ? line : "Sender rejected";
smtp_reply(s, "%d %s", code, line);
tree_pop(&wait_filter_data, s->id);
smtp_filter_tx_rollback(s);
smtp_queue_rollback(s);
+ smtp_tx_free(s->tx);
code = code ? code : 530;
line = line ? line : "Message rejected";
smtp_reply(s, "%d %s", code, line);
- smtp_message_reset(s, 0);
smtp_enter_state(s, STATE_HELO);
io_reload(&s->io);
return;
if (tx == NULL)
return 0;
+ TAILQ_INIT(&tx->rcpts);
+ io_init(&tx->oev, -1, s, NULL, NULL); /* initialise 'sock', but not to 0 */
+
s->tx = tx;
tx->session = s;
+ /* setup the envelope */
+ s->tx->evp.ss = s->ss;
+ (void)strlcpy(s->tx->evp.tag, s->listener->tag, sizeof(s->tx->evp.tag));
+ (void)strlcpy(s->tx->evp.smtpname, s->smtpname, sizeof(s->tx->evp.smtpname));
+ (void)strlcpy(s->tx->evp.hostname, s->hostname, sizeof s->tx->evp.hostname);
+ (void)strlcpy(s->tx->evp.helo, s->helo, sizeof s->tx->evp.helo);
+
+ if (s->flags & SF_BOUNCE)
+ s->tx->evp.flags |= EF_BOUNCE;
+ if (s->flags & SF_AUTHENTICATED)
+ s->tx->evp.flags |= EF_AUTHENTICATED;
+
+ /* Setup parser and callbacks */
+ rfc2822_parser_init(&tx->rfc2822_parser);
+ rfc2822_header_default_callback(&tx->rfc2822_parser,
+ header_default_callback, s);
+ rfc2822_header_callback(&tx->rfc2822_parser, "bcc",
+ header_bcc_callback, s);
+ rfc2822_header_callback(&tx->rfc2822_parser, "from",
+ header_domain_append_callback, s);
+ rfc2822_header_callback(&tx->rfc2822_parser, "to",
+ header_domain_append_callback, s);
+ rfc2822_header_callback(&tx->rfc2822_parser, "cc",
+ header_domain_append_callback, s);
+ rfc2822_body_callback(&tx->rfc2822_parser,
+ dataline_callback, s);
+
+ if (s->listener->local || s->listener->port == 587) {
+ rfc2822_missing_header_callback(&tx->rfc2822_parser, "date",
+ header_missing_callback, s);
+ rfc2822_missing_header_callback(&tx->rfc2822_parser, "message-id",
+ header_missing_callback, s);
+ }
+
return 1;
}
static void
smtp_tx_free(struct smtp_tx *tx)
{
+ struct smtp_rcpt *rcpt;
+
+ rfc2822_parser_release(&tx->rfc2822_parser);
+
+ while ((rcpt = TAILQ_FIRST(&tx->rcpts))) {
+ TAILQ_REMOVE(&tx->rcpts, rcpt, entry);
+ free(rcpt);
+ }
+
tx->session->tx = NULL;
free(tx);
esc_description(ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED));
else if (s->tx->msgflags)
smtp_reply(s, "421 Internal server error");
- smtp_message_reset(s, 0);
+ smtp_tx_free(s->tx);
smtp_enter_state(s, STATE_HELO);
io_reload(&s->io);
}
s->flags |= SF_8BITMIME;
}
- smtp_message_reset(s, 1);
-
smtp_filter_helo(s);
break;
/*
break;
}
- smtp_message_reset(s, 1);
+ if (!smtp_tx(s)) {
+ smtp_reply(s, "421 %s: Temporary Error",
+ esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
+ smtp_enter_state(s, STATE_QUIT);
+ break;
+ }
if (smtp_mailaddr(&s->tx->evp.sender, args, 1, &args,
s->smtpname) == 0) {
+ smtp_tx_free(s->tx);
smtp_reply(s, "553 %s: Sender address syntax error",
esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
break;
}
- if (args && smtp_parse_mail_args(s, args) == -1)
+ if (args && smtp_parse_mail_args(s, args) == -1) {
+ smtp_tx_free(s->tx);
break;
+ }
smtp_filter_tx_begin(s);
smtp_filter_mail(s);
break;
}
- if (s->flags & SF_FILTERTX)
+ if (s->tx) {
smtp_filter_tx_rollback(s);
- if (s->tx->msgid)
- smtp_queue_rollback(s);
+ if (s->tx->msgid)
+ smtp_queue_rollback(s);
+ smtp_tx_free(s->tx);
+ }
smtp_filter_rset(s);
s->phase = PHASE_SETUP;
- smtp_message_reset(s, 0);
smtp_reply(s, "250 %s: Reset state",
esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
break;
break;
}
- rfc2822_parser_reset(&s->tx->rfc2822_parser);
-
smtp_filter_data(s);
break;
/*
esc_description(ESC_MESSAGE_TOO_BIG_FOR_SYSTEM));
else
smtp_reply(s, "%d Message rejected", s->tx->msgcode);
- smtp_message_reset(s, 0);
+ smtp_tx_free(s->tx);
smtp_enter_state(s, STATE_HELO);
return;
}
smtp_queue_commit(s);
}
-static void
-smtp_message_reset(struct smtp_session *s, int prepare)
-{
- struct smtp_rcpt *rcpt;
-
- while ((rcpt = TAILQ_FIRST(&s->tx->rcpts))) {
- TAILQ_REMOVE(&s->tx->rcpts, rcpt, entry);
- free(rcpt);
- }
-
- s->tx->msgid = 0;
- memset(&s->tx->evp, 0, sizeof s->tx->evp);
- s->tx->msgflags = 0;
- s->tx->destcount = 0;
- s->tx->rcptcount = 0;
- s->tx->datain = 0;
- s->tx->odatalen = 0;
- s->tx->dataeom = 0;
- s->tx->rcvcount = 0;
- s->tx->hdrdone = 0;
-
- if (prepare) {
- s->tx->evp.ss = s->ss;
- (void)strlcpy(s->tx->evp.tag, s->listener->tag, sizeof(s->tx->evp.tag));
- (void)strlcpy(s->tx->evp.smtpname, s->smtpname, sizeof(s->tx->evp.smtpname));
- (void)strlcpy(s->tx->evp.hostname, s->hostname, sizeof s->tx->evp.hostname);
- (void)strlcpy(s->tx->evp.helo, s->helo, sizeof s->tx->evp.helo);
-
- if (s->flags & SF_BOUNCE)
- s->tx->evp.flags |= EF_BOUNCE;
- if (s->flags & SF_AUTHENTICATED)
- s->tx->evp.flags |= EF_AUTHENTICATED;
- }
-}
-
static int
smtp_message_printf(struct smtp_session *s, const char *fmt, ...)
{
static void
smtp_free(struct smtp_session *s, const char * reason)
{
- struct smtp_rcpt *rcpt;
-
log_debug("debug: smtp: %p: deleting session: %s", s, reason);
tree_pop(&wait_filter_data, s->id);
- if (s->tx->msgid) {
- smtp_queue_rollback(s);
- io_clear(&s->tx->oev);
- iobuf_clear(&s->tx->obuf);
- }
-
- if (s->flags & SF_FILTERTX)
+ if (s->tx) {
+ if (s->tx->msgid) {
+ smtp_queue_rollback(s);
+ io_clear(&s->tx->oev);
+ iobuf_clear(&s->tx->obuf);
+ }
smtp_filter_tx_rollback(s);
+ smtp_tx_free(s->tx);
+ }
if (s->flags & SF_FILTERCONN)
smtp_filter_disconnect(s);
if (s->flags & SF_SECURE && s->listener->flags & F_STARTTLS)
stat_decrement("smtp.tls", 1);
- while ((rcpt = TAILQ_FIRST(&s->tx->rcpts))) {
- TAILQ_REMOVE(&s->tx->rcpts, rcpt, entry);
- free(rcpt);
- }
-
- rfc2822_parser_release(&s->tx->rfc2822_parser);
-
io_clear(&s->io);
iobuf_clear(&s->iobuf);
- smtp_tx_free(s->tx);
free(s);
smtp_collect();