smtp-server-cmd-starttls.c revision 9249c80276766fdc4d31fc3eebc22fba7d53d77c
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen/* STARTTLS command (RFC 3207) */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic int cmd_starttls_start(struct smtp_server_connection *conn)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen const struct smtp_server_callbacks *callbacks = conn->callbacks;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen smtp_server_connection_debug(conn, "Starting TLS");
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if (callbacks != NULL && callbacks->conn_start_tls != NULL) {
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_connection *tmp_conn = conn;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen ret = callbacks->conn_start_tls(tmp_conn->context,
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen if (!smtp_server_connection_unref(&tmp_conn) || ret < 0)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen smtp_server_connection_set_streams(conn, input, output);
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen } else if (smtp_server_connection_ssl_init(conn) < 0) {
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen "SSL Initialization failed");
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen /* RFC 3207, Section 4.2:
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen Upon completion of the TLS handshake, the SMTP protocol is reset to
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen the initial state (the state in SMTP after a server issues a 220
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen service ready greeting). The server MUST discard any knowledge
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen obtained from the client, such as the argument to the EHLO command,
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen which was not obtained from the TLS negotiation itself.
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenstatic int cmd_starttls_output(struct smtp_server_connection *conn)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if ((ret=smtp_server_connection_flush(conn)) < 0)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen o_stream_unset_flush_callback(conn->conn.output);
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainenstatic void cmd_starttls_destroy(struct smtp_server_cmd_ctx *cmd)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_command *command = cmd->cmd;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if (smtp_server_command_replied_success(command)) {
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen /* only one valid success status for STARTTLS command */
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen i_assert(smtp_server_command_reply_status_equals(command, 220));
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen /* the buffer has to be flushed */
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen o_stream_set_flush_callback(conn->conn.output,
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen o_stream_set_flush_pending(conn->conn.output, TRUE);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void cmd_starttls_next(struct smtp_server_cmd_ctx *cmd)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_command *command = cmd->cmd;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen const struct smtp_server_callbacks *callbacks = conn->callbacks;
74f810327aca91b3375d3fc963bce8076785b1cbTimo Sirainen smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_STARTTLS);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (callbacks != NULL && callbacks->conn_cmd_starttls != NULL)
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen ret = callbacks->conn_cmd_starttls(conn->context, cmd);
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen i_assert(ret == 0 || smtp_server_command_is_replied(command));
f8512649cd4db427a8dc5dc8f45c8e379ffd4d76Timo Sirainen /* command is waiting for external event or it failed */
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen if (!smtp_server_command_is_replied(command)) {
63a2f941c1ad029061129ba6384d1d2a02382220Timo Sirainenvoid smtp_server_cmd_starttls(struct smtp_server_cmd_ctx *cmd,
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen struct smtp_server_command *command = cmd->cmd;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen enum smtp_capability capabilities = conn->set.capabilities;
ea37a9aedfc3a6ff5f4ea10bc4eff4ca23f62a15Timo Sirainen i_assert((capabilities & SMTP_CAPABILITY_STARTTLS) == 0);
0a70a2e71658d168f75d1f075661d7936701343cTimo Sirainen } else if ((capabilities & SMTP_CAPABILITY_STARTTLS) == 0) {
4fdf60e22b5340fe35f083b9ea5eb3fd1cf2e742Timo Sirainen /* "STARTTLS" CRLF */