diff options
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 119 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 10 |
3 files changed, 100 insertions, 41 deletions
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index a4386a11b3a..120c2e75d28 100644 --- a/usr.sbin/smtpd/smtp_session.c +++ b/usr.sbin/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.150 2011/10/23 09:30:07 gilles Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.151 2011/12/12 17:20:36 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -71,6 +71,10 @@ static int session_set_mailaddr(struct mailaddr *, char *); static void session_imsg(struct session *, enum smtp_proc_type, enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); +static void session_enter_state(struct session *, int); + +const char *session_strstate(int); + struct session_cmd { char *name; int (*func)(struct session *, char *); @@ -124,7 +128,7 @@ session_rfc3207_stls_handler(struct session *s, char *args) return 1; } - s->s_state = S_TLS; + session_enter_state(s, S_TLS); session_respond(s, "220 Ready to start TLS"); return 1; @@ -186,11 +190,11 @@ session_rfc4954_auth_plain(struct session *s, char *arg) switch (s->s_state) { case S_HELO: if (arg == NULL) { - s->s_state = S_AUTH_INIT; + session_enter_state(s, S_AUTH_INIT); session_respond(s, "334 "); return; } - s->s_state = S_AUTH_INIT; + session_enter_state(s, S_AUTH_INIT); /* FALLTHROUGH */ case S_AUTH_INIT: @@ -217,7 +221,7 @@ session_rfc4954_auth_plain(struct session *s, char *arg) if (strlcpy(a->pass, pass, sizeof(a->pass)) >= sizeof(a->pass)) goto abort; - s->s_state = S_AUTH_FINALIZE; + session_enter_state(s, S_AUTH_FINALIZE); a->id = s->s_id; session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1, @@ -232,7 +236,7 @@ session_rfc4954_auth_plain(struct session *s, char *arg) abort: session_respond(s, "501 Syntax error"); - s->s_state = S_HELO; + session_enter_state(s, S_HELO); } static void @@ -242,7 +246,7 @@ session_rfc4954_auth_login(struct session *s, char *arg) switch (s->s_state) { case S_HELO: - s->s_state = S_AUTH_USERNAME; + session_enter_state(s, S_AUTH_USERNAME); session_respond(s, "334 VXNlcm5hbWU6"); return; @@ -251,7 +255,7 @@ session_rfc4954_auth_login(struct session *s, char *arg) if (__b64_pton(arg, (unsigned char *)a->user, sizeof(a->user) - 1) == -1) goto abort; - s->s_state = S_AUTH_PASSWORD; + session_enter_state(s, S_AUTH_PASSWORD); session_respond(s, "334 UGFzc3dvcmQ6"); return; @@ -260,7 +264,7 @@ session_rfc4954_auth_login(struct session *s, char *arg) if (__b64_pton(arg, (unsigned char *)a->pass, sizeof(a->pass) - 1) == -1) goto abort; - s->s_state = S_AUTH_FINALIZE; + session_enter_state(s, S_AUTH_FINALIZE); a->id = s->s_id; session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1, @@ -275,7 +279,7 @@ session_rfc4954_auth_login(struct session *s, char *arg) abort: session_respond(s, "501 Syntax error"); - s->s_state = S_HELO; + session_enter_state(s, S_HELO); } static int @@ -293,12 +297,12 @@ session_rfc1652_mail_handler(struct session *s, char *args) *body++ = '\0'; if (strncasecmp(body, "AUTH=", 5) == 0) { - log_debug("AUTH in MAIL FROM command, skipping"); + log_debug("smtp: AUTH in MAIL FROM command, skipping"); continue; } if (strncasecmp(body, "BODY=", 5) == 0) { - log_debug("BODY in MAIL FROM command"); + log_debug("smtp: BODY in MAIL FROM command"); if (strncasecmp("body=7bit", body, 9) == 0) { s->s_flags &= ~F_8BITMIME; @@ -330,8 +334,8 @@ session_rfc5321_helo_handler(struct session *s, char *args) } s->s_msg.session_id = s->s_id; - s->s_state = S_HELO; s->s_flags &= F_SECURE|F_AUTHENTICATED; + session_enter_state(s, S_HELO); session_imsg(s, PROC_MFA, IMSG_MFA_HELO, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); @@ -353,10 +357,10 @@ session_rfc5321_ehlo_handler(struct session *s, char *args) } s->s_msg.session_id = s->s_id; - s->s_state = S_HELO; s->s_flags &= F_SECURE|F_AUTHENTICATED; s->s_flags |= F_EHLO; s->s_flags |= F_8BITMIME; + session_enter_state(s, S_HELO); session_imsg(s, PROC_MFA, IMSG_MFA_HELO, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); @@ -366,7 +370,7 @@ session_rfc5321_ehlo_handler(struct session *s, char *args) static int session_rfc5321_rset_handler(struct session *s, char *args) { - s->s_state = S_HELO; + session_enter_state(s, S_HELO); session_respond(s, "250 2.0.0 Reset state"); return 1; @@ -400,12 +404,10 @@ session_rfc5321_mail_handler(struct session *s, char *args) } s->rcptcount = 0; - s->s_state = S_MAIL_MFA; s->s_msg.id = 0; s->s_msg.ss = s->s_ss; - log_debug("session_rfc5321_mail_handler: sending notification to mfa"); - + session_enter_state(s, S_MAIL_MFA); session_imsg(s, PROC_MFA, IMSG_MFA_MAIL, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); return 1; @@ -430,7 +432,7 @@ session_rfc5321_rcpt_handler(struct session *s, char *args) return 1; } - s->s_state = S_RCPT_MFA; + session_enter_state(s, S_RCPT_MFA); session_imsg(s, PROC_MFA, IMSG_MFA_RCPT, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); return 1; @@ -441,6 +443,7 @@ session_rfc5321_quit_handler(struct session *s, char *args) { s->s_flags |= F_QUIT; session_respond(s, "221 2.0.0 %s Closing connection", env->sc_hostname); + return 1; } @@ -462,7 +465,7 @@ session_rfc5321_data_handler(struct session *s, char *args) return 1; } - s->s_state = S_DATA_QUEUE; + session_enter_state(s, S_DATA_QUEUE); session_imsg(s, PROC_QUEUE, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); @@ -507,6 +510,16 @@ session_rfc5321_help_handler(struct session *s, char *args) } static void +session_enter_state(struct session *s, int newstate) +{ + log_trace(TRACE_SMTP, "smtp: %p: %s -> %s", s, + session_strstate(s->s_state), + session_strstate(newstate)); + + s->s_state = newstate; +} + +static void session_command(struct session *s, char *cmd) { char *ep, *args; @@ -591,16 +604,15 @@ session_pickup(struct session *s, struct submit_status *ss) switch (s->s_state) { case S_INIT: - s->s_state = S_GREETED; - log_debug("session_pickup: greeting client"); session_respond(s, SMTPD_BANNER, env->sc_hostname); + session_enter_state(s, S_GREETED); break; case S_TLS: if (s->s_flags & F_WRITEONLY) fatalx("session_pickup: corrupt session"); bufferevent_enable(s->s_bev, EV_READ); - s->s_state = S_GREETED; + session_enter_state(s, S_GREETED); break; case S_AUTH_FINALIZE: @@ -608,14 +620,14 @@ session_pickup(struct session *s, struct submit_status *ss) session_respond(s, "235 Authentication succeeded"); else session_respond(s, "535 Authentication failed"); - s->s_state = S_HELO; + session_enter_state(s, S_HELO); break; case S_HELO: if (ss == NULL) fatalx("bad ss at S_HELO"); if (ss->code != 250) { - s->s_state = S_GREETED; + session_enter_state(s, S_GREETED); session_respond(s, "%d Helo rejected", ss->code); return; } @@ -645,12 +657,12 @@ session_pickup(struct session *s, struct submit_status *ss) if (ss == NULL) fatalx("bad ss at S_MAIL_MFA"); if (ss->code != 250) { - s->s_state = S_HELO; + session_enter_state(s, S_HELO); session_respond(s, "%d Sender rejected", ss->code); - return; + break; } - s->s_state = S_MAIL_QUEUE; + session_enter_state(s, S_MAIL_QUEUE); s->s_msg.sender = ss->u.maddr; session_imsg(s, PROC_QUEUE, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, @@ -660,7 +672,7 @@ session_pickup(struct session *s, struct submit_status *ss) case S_MAIL_QUEUE: if (ss == NULL) fatalx("bad ss at S_MAIL_QUEUE"); - s->s_state = S_MAIL; + session_enter_state(s, S_MAIL); session_respond(s, "%d 2.1.0 Sender ok", ss->code); break; @@ -671,16 +683,16 @@ session_pickup(struct session *s, struct submit_status *ss) if (ss->code != 250) { /* We do not have a valid recipient, downgrade state */ if (s->rcptcount == 0) - s->s_state = S_MAIL; + session_enter_state(s, S_MAIL); else - s->s_state = S_RCPT; + session_enter_state(s, S_RCPT); session_respond(s, "%d 5.0.0 Recipient rejected: %s@%s", ss->code, s->s_msg.rcpt.user, s->s_msg.rcpt.domain); - return; + break; } - s->s_state = S_RCPT; + session_enter_state(s, S_RCPT); s->rcptcount++; s->s_msg.dest = ss->u.maddr; @@ -688,7 +700,7 @@ session_pickup(struct session *s, struct submit_status *ss) break; case S_DATA_QUEUE: - s->s_state = S_DATACONTENT; + session_enter_state(s, S_DATACONTENT); session_respond(s, "354 Enter mail, end with \".\" on a line by" " itself"); @@ -735,7 +747,7 @@ session_pickup(struct session *s, struct submit_status *ss) s->s_hostname, ss_to_text(&s->s_ss)); - s->s_state = S_HELO; + session_enter_state(s, S_HELO); s->s_msg.id = 0; bzero(&s->s_nresp, sizeof(s->s_nresp)); break; @@ -869,7 +881,7 @@ session_read_data(struct session *s, char *line) if (s->s_msg.status & DS_PERMFAILURE) { session_respond(s, "554 5.0.0 Transaction failed"); - s->s_state = S_HELO; + session_enter_state(s, S_HELO); } else if (s->s_msg.status & DS_TEMPFAILURE) { session_respond(s, "421 4.0.0 Temporary failure"); s->s_flags |= F_QUIT; @@ -877,7 +889,7 @@ session_read_data(struct session *s, char *line) } else { session_imsg(s, PROC_QUEUE, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); - s->s_state = S_DONE; + session_enter_state(s, S_DONE); } goto end; } @@ -1215,3 +1227,36 @@ session_imsg(struct session *s, enum smtp_proc_type proc, enum imsg_type type, } SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp); + +#define CASE(x) case x : return #x + +const char * +session_strstate(int state) +{ + static char buf[32]; + + switch (state) { + CASE(S_INVALID); + CASE(S_INIT); + CASE(S_GREETED); + CASE(S_TLS); + CASE(S_AUTH_INIT); + CASE(S_AUTH_USERNAME); + CASE(S_AUTH_PASSWORD); + CASE(S_AUTH_FINALIZE); + CASE(S_HELO); + CASE(S_MAIL_MFA); + CASE(S_MAIL_QUEUE); + CASE(S_MAIL); + CASE(S_RCPT_MFA); + CASE(S_RCPT); + CASE(S_DATA); + CASE(S_DATA_QUEUE); + CASE(S_DATACONTENT); + CASE(S_DONE); + CASE(S_QUIT); + default: + snprintf(buf, sizeof(buf), "S_??? (%d)", state); + return buf; + } +} diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index d70376b0812..5d832e902f1 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.139 2011/12/08 17:00:28 todd Exp $ */ +/* $OpenBSD: smtpd.c,v 1.140 2011/12/12 17:20:36 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -454,6 +454,16 @@ main(int argc, char *argv[]) case 'T': if (!strcmp(optarg, "imsg")) verbose |= TRACE_IMSG; + else if (!strcmp(optarg, "io")) + verbose |= TRACE_IO; + else if (!strcmp(optarg, "smtp")) + verbose |= TRACE_SMTP; + else if (!strcmp(optarg, "mta")) + verbose |= TRACE_MTA; + else if (!strcmp(optarg, "bounce")) + verbose |= TRACE_BOUNCE; + else if (!strcmp(optarg, "all")) + verbose |= ~TRACE_VERBOSE; else log_warnx("unknown trace flag \"%s\"", optarg); break; diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 40df5d7e3e5..4e3b190ef08 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.259 2011/12/12 16:45:16 chl Exp $ */ +/* $OpenBSD: smtpd.h,v 1.260 2011/12/12 17:20:36 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -631,8 +631,12 @@ struct smtpd { u_int64_t filtermask; }; -#define TRACE_VERBOSE 0x01 -#define TRACE_IMSG 0x02 +#define TRACE_VERBOSE 0x0001 +#define TRACE_IMSG 0x0002 +#define TRACE_IO 0x0004 +#define TRACE_SMTP 0x0008 +#define TRACE_MTA 0x0010 +#define TRACE_BOUNCE 0x0020 enum { STATS_SMTP_SESSION = 0, |