static void pop3c_client_prelogin_input(struct pop3c_client *client) { const char *line, *errstr; i_assert(client->state != POP3C_CLIENT_STATE_DONE); /* we need to read as much as we can with SSL streams to avoid hanging */ while ((line = i_stream_read_next_line(client->input)) != NULL) { if (pop3c_client_prelogin_input_line(client, line) < 0) { pop3c_client_disconnect(client); return; } } if (client->input->closed || client->input->eof || client->input->stream_errno != 0) { /* disconnected */ if (client->ssl_iostream == NULL) { i_error("pop3c(%s): Server disconnected unexpectedly", client->set.host); } else { errstr = ssl_iostream_get_last_error(client->ssl_iostream); if (errstr == NULL) { errstr = client->input->stream_errno == 0 ? "EOF" : strerror(client->input->stream_errno); } i_error("pop3c(%s): Server disconnected: %s", client->set.host, errstr); } pop3c_client_disconnect(client); } }
static int server_connection_init_ssl(struct server_connection *conn) { struct ssl_iostream_settings ssl_set; const char *error; if (conn->server->ssl_ctx == NULL) return 0; memset(&ssl_set, 0, sizeof(ssl_set)); ssl_set.verify_remote_cert = TRUE; ssl_set.require_valid_cert = TRUE; ssl_set.verbose_invalid_cert = TRUE; if (io_stream_create_ssl_client(conn->server->ssl_ctx, conn->server->name, &ssl_set, &conn->input, &conn->output, &conn->ssl_iostream, &error) < 0) { i_error("Couldn't initialize SSL client: %s", error); return -1; } ssl_iostream_set_handshake_callback(conn->ssl_iostream, server_connection_ssl_handshaked, conn); if (ssl_iostream_handshake(conn->ssl_iostream) < 0) { i_error("SSL handshake failed: %s", ssl_iostream_get_last_error(conn->ssl_iostream)); return -1; } return 0; }
static int pop3c_client_ssl_init(struct pop3c_client *client) { struct ssl_iostream_settings ssl_set; struct stat st; const char *error; if (client->ssl_ctx == NULL) { i_error("pop3c(%s): No SSL context", client->set.host); return -1; } memset(&ssl_set, 0, sizeof(ssl_set)); if (client->set.ssl_verify) { ssl_set.verbose_invalid_cert = TRUE; ssl_set.verify_remote_cert = TRUE; ssl_set.require_valid_cert = TRUE; } if (client->set.debug) i_debug("pop3c(%s): Starting SSL handshake", client->set.host); if (client->raw_input != client->input) { /* recreate rawlog after STARTTLS */ i_stream_ref(client->raw_input); o_stream_ref(client->raw_output); i_stream_destroy(&client->input); o_stream_destroy(&client->output); client->input = client->raw_input; client->output = client->raw_output; } if (io_stream_create_ssl_client(client->ssl_ctx, client->set.host, &ssl_set, &client->input, &client->output, &client->ssl_iostream, &error) < 0) { i_error("pop3c(%s): Couldn't initialize SSL client: %s", client->set.host, error); return -1; } ssl_iostream_set_handshake_callback(client->ssl_iostream, pop3c_client_ssl_handshaked, client); if (ssl_iostream_handshake(client->ssl_iostream) < 0) { i_error("pop3c(%s): SSL handshake failed: %s", client->set.host, ssl_iostream_get_last_error(client->ssl_iostream)); return -1; } if (*client->set.rawlog_dir != '\0' && stat(client->set.rawlog_dir, &st) == 0) { iostream_rawlog_create(client->set.rawlog_dir, &client->input, &client->output); } return 0; }
static void server_log_disconnect_error(struct server_connection *conn) { const char *error; error = conn->ssl_iostream == NULL ? NULL : ssl_iostream_get_last_error(conn->ssl_iostream); if (error == NULL) { error = conn->input->stream_errno == 0 ? "EOF" : strerror(conn->input->stream_errno); } i_error("doveadm server disconnected before handshake: %s", error); }
static int client_connection_init_ssl(struct client_connection *conn) { if (master_service_ssl_init(master_service, &conn->input, &conn->output, &conn->ssl_iostream) < 0) return -1; if (ssl_iostream_handshake(conn->ssl_iostream) < 0) { i_error("SSL handshake failed: %s", ssl_iostream_get_last_error(conn->ssl_iostream)); return -1; } return 0; }
void server_connection_destroy(struct server_connection **_conn) { struct server_connection *conn = *_conn; struct server_connection *const *conns; const char *error; unsigned int i, count; *_conn = NULL; conns = array_get(&conn->server->connections, &count); for (i = 0; i < count; i++) { if (conns[i] == conn) { array_delete(&conn->server->connections, i, 1); break; } } if (conn->callback != NULL) { error = conn->ssl_iostream == NULL ? NULL : ssl_iostream_get_last_error(conn->ssl_iostream); if (error == NULL) { error = conn->input->stream_errno == 0 ? "EOF" : strerror(conn->input->stream_errno); } server_connection_callback(conn, SERVER_EXIT_CODE_DISCONNECTED, error); } if (printing_conn == conn) print_connection_released(); if (conn->input != NULL) i_stream_destroy(&conn->input); if (conn->output != NULL) o_stream_destroy(&conn->output); if (conn->cmd_input != NULL) i_stream_destroy(&conn->cmd_input); /* close cmd_output after its parent, so the "." isn't sent */ if (conn->cmd_output != NULL) o_stream_destroy(&conn->cmd_output); if (conn->ssl_iostream != NULL) ssl_iostream_unref(&conn->ssl_iostream); if (conn->io != NULL) io_remove(&conn->io); if (conn->fd != -1) { if (close(conn->fd) < 0) i_error("close(server) failed: %m"); } pool_unref(&conn->pool); }
int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io, const char *host, const char **error_r) { if (!ssl_iostream_has_valid_client_cert(ssl_io)) { if (!ssl_iostream_has_broken_client_cert(ssl_io)) *error_r = "SSL certificate not received"; else { *error_r = t_strdup(ssl_iostream_get_last_error(ssl_io)); if (*error_r == NULL) *error_r = "Received invalid SSL certificate"; } return -1; } else if (ssl_iostream_cert_match_name(ssl_io, host) < 0) { *error_r = t_strdup_printf( "SSL certificate doesn't match expected host name %s", host); return -1; } return 0; }