diff options
author | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-05-18 20:23:36 +0000 |
---|---|---|
committer | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-05-18 20:23:36 +0000 |
commit | 70d04b4454983db7f8ade89c13bbf7afd8c5c946 (patch) | |
tree | d75be19c4c8d99803499e99d4c00ac0170e449ac /usr.sbin | |
parent | 8ea800ac124a5b897090f73a4ecb57ffc0b0075d (diff) |
Complete rework of bufferevent event masking allowing for more
strictness:
- Drop clients attempting command pipelining; protects the daemon
from all kinds of abuse.
- Replace F_EVLOCKED flag with F_WRITEONLY which has cleaner sematics:
when up, session must not be destroyed nor read from, but may be
written to.
- Write callback becomes a central place for enabling EV_READ.
- Delay bufferevent creation until after ssl handshake is completed.
A bunch of session error stats were added to smtpctl's "show stats".
These could help spotting event masking errors in the future.
ok gilles@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/smtpd/smtp.c | 24 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 389 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl.c | 18 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 17 | ||||
-rw-r--r-- | usr.sbin/smtpd/ssl.c | 8 |
5 files changed, 282 insertions, 174 deletions
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c index f1f9de3e9e8..852322156d9 100644 --- a/usr.sbin/smtpd/smtp.c +++ b/usr.sbin/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.45 2009/05/14 15:05:12 eric Exp $ */ +/* $OpenBSD: smtp.c,v 1.46 2009/05/18 20:23:35 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -397,22 +397,18 @@ smtp_dispatch_queue(int sig, short event, void *p) log_debug("smtp_dispatch_queue: tempfail in queue"); - /* - * IMSG_QUEUE_TEMPFAIL is not the final reply to - * IMSG_MFA_RCPT - IMSG_QUEUE_COMMIT_ENVELOPES is. - * Therefore, nothing more but updating the flags - * is allowed here. If session_lookup were to be - * called, then subsequent session_lookup in the - * IMSG_QUEUE_COMMIT_ENVELOPES handler would fatal for - * either of two reasons: missing session, or missing - * EVLOCKED flag. - */ key.s_id = ss->id; s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); if (s == NULL) fatalx("smtp_dispatch_queue: session is gone"); - s->s_msg.status |= S_MESSAGE_TEMPFAILURE; + if (s->s_flags & F_WRITEONLY) { + /* + * Session is write-only, can't destroy it. + */ + s->s_msg.status |= S_MESSAGE_TEMPFAILURE; + } else + fatalx("smtp_dispatch_queue: corrupt session"); break; } @@ -752,9 +748,9 @@ session_lookup(struct smtpd *env, u_int64_t id) if (s == NULL) fatalx("session_lookup: session is gone"); - if (!(s->s_flags & F_EVLOCKED)) + if (!(s->s_flags & F_WRITEONLY)) fatalx("session_lookup: corrupt session"); - s->s_flags &= ~F_EVLOCKED; + s->s_flags &= ~F_WRITEONLY; if (s->s_flags & F_QUIT) { session_destroy(s); diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index 07711efdb60..8affe5ebeea 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.88 2009/05/14 15:05:12 eric Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.89 2009/05/18 20:23:35 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -41,37 +41,38 @@ #include "smtpd.h" -int session_rfc5321_helo_handler(struct session *, char *); -int session_rfc5321_ehlo_handler(struct session *, char *); -int session_rfc5321_rset_handler(struct session *, char *); -int session_rfc5321_noop_handler(struct session *, char *); -int session_rfc5321_data_handler(struct session *, char *); -int session_rfc5321_mail_handler(struct session *, char *); -int session_rfc5321_rcpt_handler(struct session *, char *); -int session_rfc5321_vrfy_handler(struct session *, char *); -int session_rfc5321_expn_handler(struct session *, char *); -int session_rfc5321_turn_handler(struct session *, char *); -int session_rfc5321_help_handler(struct session *, char *); -int session_rfc5321_quit_handler(struct session *, char *); -int session_rfc5321_none_handler(struct session *, char *); - -int session_rfc1652_mail_handler(struct session *, char *); - -int session_rfc3207_stls_handler(struct session *, char *); - -int session_rfc4954_auth_handler(struct session *, char *); -int session_rfc4954_auth_plain(struct session *, char *, size_t); -int session_rfc4954_auth_login(struct session *, char *, size_t); -void session_auth_pickup(struct session *, char *, size_t); - -void session_read(struct bufferevent *, void *); -int session_read_data(struct session *, char *, size_t); -void session_write(struct bufferevent *, void *); -void session_error(struct bufferevent *, short, void *); -void session_command(struct session *, char *, char *); -int session_set_path(struct path *, char *); -void session_imsg(struct session *, enum smtp_proc_type, - enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); +int session_rfc5321_helo_handler(struct session *, char *); +int session_rfc5321_ehlo_handler(struct session *, char *); +int session_rfc5321_rset_handler(struct session *, char *); +int session_rfc5321_noop_handler(struct session *, char *); +int session_rfc5321_data_handler(struct session *, char *); +int session_rfc5321_mail_handler(struct session *, char *); +int session_rfc5321_rcpt_handler(struct session *, char *); +int session_rfc5321_vrfy_handler(struct session *, char *); +int session_rfc5321_expn_handler(struct session *, char *); +int session_rfc5321_turn_handler(struct session *, char *); +int session_rfc5321_help_handler(struct session *, char *); +int session_rfc5321_quit_handler(struct session *, char *); +int session_rfc5321_none_handler(struct session *, char *); + +int session_rfc1652_mail_handler(struct session *, char *); + +int session_rfc3207_stls_handler(struct session *, char *); + +int session_rfc4954_auth_handler(struct session *, char *); +int session_rfc4954_auth_plain(struct session *, char *, size_t); +int session_rfc4954_auth_login(struct session *, char *, size_t); +void session_auth_pickup(struct session *, char *, size_t); + +void session_read(struct bufferevent *, void *); +void session_read_data(struct session *, char *, size_t); +void session_write(struct bufferevent *, void *); +void session_error(struct bufferevent *, short event, void *); +void session_command(struct session *, char *, size_t); +char *session_readline(struct session *, size_t *); +int session_set_path(struct path *, char *); +void session_imsg(struct session *, enum smtp_proc_type, + enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); extern struct s_session s_smtp; @@ -123,8 +124,6 @@ session_rfc3207_stls_handler(struct session *s, char *args) session_respond(s, "220 Ready to start TLS"); s->s_state = S_TLS; - bufferevent_disable(s->s_bev, EV_READ); - ssl_session_init(s); return 1; } @@ -422,7 +421,6 @@ session_rfc5321_quit_handler(struct session *s, char *args) session_respond(s, "221 %s Closing connection", s->s_env->sc_hostname); s->s_flags |= F_QUIT; - bufferevent_disable(s->s_bev, EV_READ); return 1; } @@ -490,9 +488,27 @@ session_rfc5321_help_handler(struct session *s, char *args) } void -session_command(struct session *s, char *cmd, char *args) +session_command(struct session *s, char *cmd, size_t nr) { - unsigned int i; + char *ep, *args; + unsigned int i; + + if (nr > SMTP_CMDLINE_MAX) { + session_respond(s, "500 Line too long"); + return; + } + + if ((ep = strchr(cmd, ':')) == NULL) + ep = strchr(cmd, ' '); + if (ep != NULL) { + *ep = '\0'; + args = ++ep; + while (isspace((int)*args)) + args++; + } else + args = NULL; + + log_debug("command: %s\targs: %s", cmd, args); if (!(s->s_flags & F_EHLO)) goto rfc5321; @@ -545,8 +561,6 @@ session_auth_pickup(struct session *s, char *arg, size_t nr) if (s == NULL) fatal("session_auth_pickup: desynchronized"); - bufferevent_enable(s->s_bev, EV_READ); - switch (s->s_state) { case S_AUTH_INIT: session_rfc4954_auth_plain(s, arg, nr); @@ -576,13 +590,11 @@ session_pickup(struct session *s, struct submit_status *ss) if (s == NULL) fatal("session_pickup: desynchronized"); - bufferevent_enable(s->s_bev, EV_READ); - if ((ss != NULL && ss->code == 421) || (s->s_msg.status & S_MESSAGE_TEMPFAILURE)) { session_respond(s, "421 Service temporarily unavailable"); + s_smtp.tempfail++; s->s_flags |= F_QUIT; - bufferevent_disable(s->s_bev, EV_READ); return; } @@ -678,82 +690,90 @@ session_init(struct listener *l, struct session *s) { s->s_state = S_INIT; - if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, - session_error, s)) == NULL) - fatalx("session_init: bufferevent_new failed"); - - bufferevent_settimeout(s->s_bev, SMTPD_SESSION_TIMEOUT, - SMTPD_SESSION_TIMEOUT); - if (l->flags & F_SMTPS) { - log_debug("session_init: initializing ssl"); - s->s_flags |= F_EVLOCKED; - bufferevent_disable(s->s_bev, EV_READ|EV_WRITE); ssl_session_init(s); return; } + session_bufferevent_new(s); session_pickup(s, NULL); } void +session_bufferevent_new(struct session *s) +{ + if (s->s_bev != NULL) + fatalx("session_bufferevent_new: attempt to override existing " + "bufferevent"); + + if (s->s_flags & F_WRITEONLY) + fatalx("session_bufferevent_new: corrupt session"); + + s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, + session_error, s); + if (s->s_bev == NULL) + fatal("session_bufferevent_new"); + + bufferevent_settimeout(s->s_bev, SMTPD_SESSION_TIMEOUT, + SMTPD_SESSION_TIMEOUT); + + bufferevent_enable(s->s_bev, EV_READ); +} + +void session_read(struct bufferevent *bev, void *p) { struct session *s = p; char *line; - char *ep; - char *args; size_t nr; + int expect_lines = 1; -read: - nr = EVBUFFER_LENGTH(bev->input); - line = evbuffer_readline(bev->input); - if (line == NULL) { - if (EVBUFFER_LENGTH(bev->input) > SMTP_ANYLINE_MAX) { - session_respond(s, "500 Line too long"); + for (;;) { + line = session_readline(s, &nr); + if (line == NULL) + return; + + if (! expect_lines) { + session_respond(s, "500 Pipelining unsupported"); + s_smtp.toofast++; s->s_flags |= F_QUIT; - bufferevent_disable(s->s_bev, EV_READ); + return; } - return; - } - nr -= EVBUFFER_LENGTH(bev->input); + expect_lines = 0; - if (s->s_state == S_DATACONTENT) { - if (session_read_data(s, line, nr)) { - free(line); - return; + if (s->s_flags & F_WRITEONLY) + fatalx("session_read: corrupt session"); + + switch (s->s_state) { + case S_AUTH_INIT: + case S_AUTH_USERNAME: + case S_AUTH_PASSWORD: + case S_AUTH_FINALIZE: + session_auth_pickup(s, line, nr); + break; + + case S_GREETED: + case S_HELO: + case S_MAIL: + case S_RCPT: + session_command(s, line, nr); + break; + + case S_DATACONTENT: + if (strcmp(line, ".") != 0) + expect_lines = 1; + session_read_data(s, line, nr); + break; + + default: + fatalx("session_read: unexpected state"); } - free(line); - goto read; - } - if (IS_AUTH(s->s_state)) { - session_auth_pickup(s, line, nr); free(line); - return; } - - if (nr > SMTP_CMDLINE_MAX) { - session_respond(s, "500 Line too long"); - return; - } - - if ((ep = strchr(line, ':')) == NULL) - ep = strchr(line, ' '); - if (ep != NULL) { - *ep = '\0'; - args = ++ep; - while (isspace((int)*args)) - args++; - } else - args = NULL; - log_debug("command: %s\targs: %s", line, args); - session_command(s, line, args); - free(line); - return; } -int +void session_read_data(struct session *s, char *line, size_t nread) { size_t len; @@ -769,23 +789,24 @@ session_read_data(struct session *s, char *line, size_t nread) s->s_state = S_HELO; } else if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) { session_respond(s, "421 Temporary failure"); - s->s_state = S_HELO; + s->s_flags |= F_QUIT; + s_smtp.tempfail++; } 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; } - return 1; + return; } /* Don't waste resources on message if it's going to bin anyway. */ if (s->s_msg.status & (S_MESSAGE_PERMFAILURE|S_MESSAGE_TEMPFAILURE)) - return 0; + return; if (nread > SMTP_TEXTLINE_MAX) { s->s_msg.status |= S_MESSAGE_PERMFAILURE; - return 0; + return; } /* "If the first character is a period and there are other characters @@ -799,7 +820,7 @@ session_read_data(struct session *s, char *line, size_t nread) if (fwrite(line, len, 1, s->datafp) != 1 || fwrite("\n", 1, 1, s->datafp) != 1) { s->s_msg.status |= S_MESSAGE_TEMPFAILURE; - return 0; + return; } if (! (s->s_flags & F_8BITMIME)) { @@ -808,11 +829,9 @@ session_read_data(struct session *s, char *line, size_t nread) break; if (i != len) { s->s_msg.status |= S_MESSAGE_PERMFAILURE; - return 0; + return; } } - - return 0; } void @@ -820,8 +839,83 @@ session_write(struct bufferevent *bev, void *p) { struct session *s = p; - if (s->s_flags & F_QUIT) + if (s->s_flags & F_WRITEONLY) { + /* + * Finished writing to a session that is waiting for an IMSG + * response, therefore can't destroy session nor re-enable + * reading from it. + * + * If session_respond caller used F_QUIT to request session + * destroy after final write, then session will be destroyed + * in session_lookup. + * + * Reading from session will be re-enabled in session_pickup + * using another call to session_respond. + */ + return; + } else if (s->s_flags & F_QUIT) { + /* + * session_respond caller requested the session to be dropped. + */ session_destroy(s); + } else if (s->s_state == S_TLS) { + /* + * Start the TLS conversation. + * Destroy the bufferevent as the SSL module re-creates it. + */ + bufferevent_free(s->s_bev); + s->s_bev = NULL; + ssl_session_init(s); + } else { + /* + * Common case of responding to client's request. + * Re-enable reading from session so that more commands can + * be processed. + */ + bufferevent_enable(s->s_bev, EV_READ); + } +} + +void +session_error(struct bufferevent *bev, short event, void *p) +{ + struct session *s = p; + char *ip = ss_to_text(&s->s_ss); + + if (event & EVBUFFER_READ) { + if (event & EVBUFFER_TIMEOUT) { + log_warnx("client %s read timeout", ip); + s_smtp.read_timeout++; + } else if (event & EVBUFFER_EOF) + s_smtp.read_eof++; + else if (event & EVBUFFER_ERROR) { + log_warn("client %s read error", ip); + s_smtp.read_error++; + } + + session_destroy(s); + return; + } + + if (event & EVBUFFER_WRITE) { + if (event & EVBUFFER_TIMEOUT) { + log_warnx("client %s write timeout", ip); + s_smtp.write_timeout++; + } else if (event & EVBUFFER_EOF) + s_smtp.write_eof++; + else if (event & EVBUFFER_ERROR) { + log_warn("client %s write error", ip); + s_smtp.write_error++; + } + + if (s->s_flags & F_WRITEONLY) + s->s_flags |= F_QUIT; + else + session_destroy(s); + return; + } + + fatalx("session_error: unexpected error"); } void @@ -829,57 +923,53 @@ session_destroy(struct session *s) { log_debug("session_destroy: killing client: %p", s); + if (s->s_flags & F_WRITEONLY) + fatalx("session_destroy: corrupt session"); + if (s->datafp != NULL) fclose(s->datafp); - if (s->s_msg.message_id[0] != '\0' && s->s_state != S_DONE) { - /* - * IMSG_QUEUE_REMOVE_MESSAGE must not be sent using session_imsg - * since no reply for it is expected. - */ + if (s->s_msg.message_id[0] != '\0' && s->s_state != S_DONE) imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); - s->s_msg.message_id[0] = '\0'; - s->s_msg.message_uid[0] = '\0'; - } - close(s->s_fd); + ssl_session_destroy(s); + + if (s->s_bev != NULL) + bufferevent_free(s->s_bev); + + if (close(s->s_fd) == -1) + fatal("session_destroy: close"); s_smtp.sessions_active--; if (s_smtp.sessions_active < s->s_env->sc_maxconn && !(s->s_msg.flags & F_MESSAGE_ENQUEUED)) event_add(&s->s_l->ev, NULL); - if (s->s_bev != NULL) { - bufferevent_free(s->s_bev); - } - ssl_session_destroy(s); - SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s); bzero(s, sizeof(*s)); free(s); } -void -session_error(struct bufferevent *bev, short event, void *p) +char * +session_readline(struct session *s, size_t *nr) { - struct session *s = p; + char *line; - if (event & EVBUFFER_TIMEOUT) - s_smtp.timeout++; - else - s_smtp.aborted++; + *nr = EVBUFFER_LENGTH(s->s_bev->input); + line = evbuffer_readline(s->s_bev->input); + if (line == NULL) { + if (EVBUFFER_LENGTH(s->s_bev->input) > SMTP_ANYLINE_MAX) { + session_respond(s, "500 Line too long"); + s_smtp.linetoolong++; + s->s_flags |= F_QUIT; + } + return NULL; + } + *nr -= EVBUFFER_LENGTH(s->s_bev->input); - /* If events are locked, do not destroy session - * but set F_QUIT flag so that we destroy it as - * soon as the event lock is removed. - */ - if (s->s_flags & F_EVLOCKED) { - s->s_flags |= F_QUIT; - bufferevent_disable(s->s_bev, EV_READ); - } else - session_destroy(s); + return line; } int @@ -921,6 +1011,8 @@ session_respond(struct session *s, char *fmt, ...) fatal("session_respond: evbuffer_add_vprintf failed"); va_end(ap); + if (smtpd_process == PROC_SMTP) + bufferevent_disable(s->s_bev, EV_READ); bufferevent_enable(s->s_bev, EV_WRITE); } @@ -931,26 +1023,25 @@ void session_imsg(struct session *s, enum smtp_proc_type proc, enum imsg_type type, u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) { - imsg_compose(s->s_env->sc_ibufs[proc], type, peerid, pid, fd, data, - datalen); + if (s->s_flags & F_WRITEONLY) + fatalx("session_imsg: corrupt session"); /* - * Most IMSGs require replies before session can be safely resumed. - * Ignore client events so that malicious client cannot trigger - * session_pickup at a bad time. + * Each outgoing IMSG has a response IMSG associated that must be + * waited for before the session can be progressed further. + * During the wait period: + * 1) session must not be destroyed, + * 2) session must not be read from, + * 3) session may be written to. + * Session flag F_WRITEONLY is needed to enforce this policy. + * + * F_WRITEONLY is cleared in session_lookup. + * Reading is re-enabled in session_pickup. */ + s->s_flags |= F_WRITEONLY; bufferevent_disable(s->s_bev, EV_READ); - - /* - * If session is unexpectedly teared down, event(3) calls session_error - * without honoring EV_READ block. - * To avoid session data being destroyed while an IMSG requiring it - * is with other process, provide a flag that session_error can use to - * determine if it is safe to destroy session data. - */ - if (s->s_flags & F_EVLOCKED) - fatalx("session_imsg: imsg sent when another is pending"); - s->s_flags |= F_EVLOCKED; + imsg_compose(s->s_env->sc_ibufs[proc], type, peerid, pid, fd, data, + datalen); } SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp); diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c index ecd1cc457ca..ed4bcb3cd86 100644 --- a/usr.sbin/smtpd/smtpctl.c +++ b/usr.sbin/smtpd/smtpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpctl.c,v 1.24 2009/04/23 08:28:45 jacekm Exp $ */ +/* $OpenBSD: smtpctl.c,v 1.25 2009/05/18 20:23:35 jacekm Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -294,10 +294,22 @@ show_stats_output(struct imsg *imsg) printf("runner.active=%zd\n", s_runner.active); + printf("smtp.errors.linetoolong=%zd\n", s_smtp.linetoolong); + printf("smtp.errors.read_eof=%zd\n", s_smtp.read_eof); + printf("smtp.errors.read_system=%zd\n", s_smtp.read_error); + printf("smtp.errors.read_timeout=%zd\n", s_smtp.read_timeout); + printf("smtp.errors.tempfail=%zd\n", s_smtp.tempfail); + printf("smtp.errors.toofast=%zd\n", s_smtp.toofast); + printf("smtp.errors.write_eof=%zd\n", s_smtp.write_eof); + printf("smtp.errors.write_system=%zd\n", s_smtp.write_error); + printf("smtp.errors.write_timeout=%zd\n", s_smtp.write_timeout); + printf("smtp.sessions=%zd\n", s_smtp.sessions); - printf("smtp.sessions.aborted=%zd\n", s_smtp.aborted); + printf("smtp.sessions.aborted=%zd\n", s_smtp.read_eof + + s_smtp.read_error + s_smtp.write_eof + s_smtp.write_error); printf("smtp.sessions.active=%zd\n", s_smtp.sessions_active); - printf("smtp.sessions.timeout=%zd\n", s_smtp.timeout); + printf("smtp.sessions.timeout=%zd\n", s_smtp.read_timeout + + s_smtp.write_timeout); printf("smtp.sessions.smtps=%zd\n", s_smtp.smtps); printf("smtp.sessions.smtps.active=%zd\n", s_smtp.smtps_active); printf("smtp.sessions.starttls=%zd\n", s_smtp.starttls); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 5a25bb49864..2d464a3db45 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.107 2009/05/09 20:03:07 jacekm Exp $ */ +/* $OpenBSD: smtpd.h,v 1.108 2009/05/18 20:23:35 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -547,7 +547,6 @@ enum session_state { S_DONE, S_QUIT }; -#define IS_AUTH(x) ((x) == S_AUTH_INIT || (x) == S_AUTH_USERNAME || (x) == S_AUTH_PASSWORD || (x) == S_AUTH_FINALIZE) struct ssl { SPLAY_ENTRY(ssl) ssl_nodes; @@ -590,7 +589,7 @@ enum session_flags { F_AUTHENTICATED = 0x10, F_PEERHASTLS = 0x20, F_PEERHASAUTH = 0x40, - F_EVLOCKED = 0x80 + F_WRITEONLY = 0x80 }; struct session { @@ -680,8 +679,15 @@ struct s_session { size_t starttls; size_t starttls_active; - size_t aborted; - size_t timeout; + size_t read_error; + size_t read_timeout; + size_t read_eof; + size_t write_error; + size_t write_timeout; + size_t write_eof; + size_t toofast; + size_t tempfail; + size_t linetoolong; }; struct stats { @@ -907,6 +913,7 @@ void session_pickup(struct session *, struct submit_status *); void session_destroy(struct session *); void session_respond(struct session *, char *, ...) __attribute__ ((format (printf, 2, 3))); +void session_bufferevent_new(struct session *); SPLAY_PROTOTYPE(sessiontree, session, s_nodes, session_cmp); diff --git a/usr.sbin/smtpd/ssl.c b/usr.sbin/smtpd/ssl.c index 3164c776754..e921382392d 100644 --- a/usr.sbin/smtpd/ssl.c +++ b/usr.sbin/smtpd/ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl.c,v 1.13 2009/04/15 20:34:59 jacekm Exp $ */ +/* $OpenBSD: ssl.c,v 1.14 2009/05/18 20:23:35 jacekm Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -503,8 +503,6 @@ ssl_session_accept(int fd, short event, void *p) } } - event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); - event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); log_info("ssl_session_accept: accepted ssl client"); s->s_flags |= F_SECURE; @@ -518,7 +516,11 @@ ssl_session_accept(int fd, short event, void *p) s_smtp.starttls_active++; } + session_bufferevent_new(s); + event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); + event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); session_pickup(s, NULL); + return; retry: event_add(&s->s_ev, &s->s_tv); |