diff --git a/data/Dockerfiles/dovecot/auth-client-request.c b/data/Dockerfiles/dovecot/auth-client-request.c deleted file mode 100644 index 5437ffb4..00000000 --- a/data/Dockerfiles/dovecot/auth-client-request.c +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "str.h" -#include "strescape.h" -#include "ostream.h" -#include "auth-client-private.h" -#include "auth-server-connection.h" -#include "auth-client-request.h" - - -struct auth_client_request { - pool_t pool; - - struct auth_server_connection *conn; - unsigned int id; - time_t created; - - struct auth_request_info request_info; - - auth_request_callback_t *callback; - void *context; -}; - -static void auth_server_send_new_request(struct auth_server_connection *conn, - struct auth_client_request *request) -{ - struct auth_request_info *info = &request->request_info; - string_t *str; - - str = t_str_new(512); - str_printfa(str, "AUTH\t%u\t", request->id); - str_append_tabescaped(str, info->mech); - str_append(str, "\tservice="); - str_append_tabescaped(str, info->service); - - if ((info->flags & AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP) != 0) - str_append(str, "\tfinal-resp-ok"); - if ((info->flags & AUTH_REQUEST_FLAG_SECURED) != 0) - str_append(str, "\tsecured"); - if ((info->flags & AUTH_REQUEST_FLAG_NO_PENALTY) != 0) - str_append(str, "\tno-penalty"); - if ((info->flags & AUTH_REQUEST_FLAG_VALID_CLIENT_CERT) != 0) - str_append(str, "\tvalid-client-cert"); - if ((info->flags & AUTH_REQUEST_FLAG_DEBUG) != 0) - str_append(str, "\tdebug"); - - if (info->session_id != NULL) { - str_append(str, "\tsession="); - str_append_tabescaped(str, info->session_id); - } - if (info->cert_username != NULL) { - str_append(str, "\tcert_username="); - str_append_tabescaped(str, info->cert_username); - } - if (info->local_ip.family != 0) - str_printfa(str, "\tlip=%s", net_ip2addr(&info->local_ip)); - if (info->remote_ip.family != 0) - str_printfa(str, "\trip=%s", net_ip2addr(&info->remote_ip)); - if (info->local_port != 0) - str_printfa(str, "\tlport=%u", info->local_port); - if (info->remote_port != 0) - str_printfa(str, "\trport=%u", info->remote_port); - - /* send the real_* variants only when they differ from the unreal - ones */ - if (info->real_local_ip.family != 0 && - !net_ip_compare(&info->real_local_ip, &info->local_ip)) { - str_printfa(str, "\treal_lip=%s", - net_ip2addr(&info->real_local_ip)); - } - if (info->real_remote_ip.family != 0 && - !net_ip_compare(&info->real_remote_ip, &info->remote_ip)) { - str_printfa(str, "\treal_rip=%s", - net_ip2addr(&info->real_remote_ip)); - } - if (info->real_local_port != 0 && - info->real_local_port != info->local_port) - str_printfa(str, "\treal_lport=%u", info->real_local_port); - if (info->real_remote_port != 0 && - info->real_remote_port != info->remote_port) - str_printfa(str, "\treal_rport=%u", info->real_remote_port); - if (info->local_name != NULL && - *info->local_name != '\0') { - str_append(str, "\tlocal_name="); - str_append_tabescaped(str, info->local_name); - } - if (info->client_id != NULL && - *info->client_id != '\0') { - str_append(str, "\tclient_id="); - str_append_tabescaped(str, info->client_id); - } - if (info->forward_fields != NULL && - *info->forward_fields != '\0') { - str_append(str, "\tforward_fields="); - str_append_tabescaped(str, info->forward_fields); - } - if (info->initial_resp_base64 != NULL) { - str_append(str, "\tresp="); - str_append_tabescaped(str, info->initial_resp_base64); - } - str_append_c(str, '\n'); - - if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0) - i_error("Error sending request to auth server: %m"); -} - -struct auth_client_request * -auth_client_request_new(struct auth_client *client, - const struct auth_request_info *request_info, - auth_request_callback_t *callback, void *context) -{ - struct auth_client_request *request; - pool_t pool; - - pool = pool_alloconly_create("auth client request", 512); - request = p_new(pool, struct auth_client_request, 1); - request->pool = pool; - request->conn = client->conn; - - request->request_info = *request_info; - request->request_info.mech = p_strdup(pool, request_info->mech); - request->request_info.service = p_strdup(pool, request_info->service); - request->request_info.session_id = - p_strdup_empty(pool, request_info->session_id); - request->request_info.cert_username = - p_strdup_empty(pool, request_info->cert_username); - request->request_info.initial_resp_base64 = - p_strdup_empty(pool, request_info->initial_resp_base64); - - request->callback = callback; - request->context = context; - - request->id = - auth_server_connection_add_request(request->conn, request); - request->created = ioloop_time; - T_BEGIN { - auth_server_send_new_request(request->conn, request); - } T_END; - return request; -} - -void auth_client_request_continue(struct auth_client_request *request, - const char *data_base64) -{ - struct const_iovec iov[3]; - const char *prefix; - - prefix = t_strdup_printf("CONT\t%u\t", request->id); - - iov[0].iov_base = prefix; - iov[0].iov_len = strlen(prefix); - iov[1].iov_base = data_base64; - iov[1].iov_len = strlen(data_base64); - iov[2].iov_base = "\n"; - iov[2].iov_len = 1; - - if (o_stream_sendv(request->conn->output, iov, 3) < 0) - i_error("Error sending continue request to auth server: %m"); -} - -static void ATTR_NULL(3, 4) -call_callback(struct auth_client_request *request, - enum auth_request_status status, - const char *data_base64, - const char *const *args) -{ - auth_request_callback_t *callback = request->callback; - - if (status != AUTH_REQUEST_STATUS_CONTINUE) - request->callback = NULL; - callback(request, status, data_base64, args, request->context); -} - -void auth_client_request_abort(struct auth_client_request **_request) -{ - struct auth_client_request *request = *_request; - - *_request = NULL; - - auth_client_send_cancel(request->conn->client, request->id); - call_callback(request, AUTH_REQUEST_STATUS_ABORT, NULL, NULL); - auth_server_connection_remove_request(request->conn, request->id); - pool_unref(&request->pool); -} - -unsigned int auth_client_request_get_id(struct auth_client_request *request) -{ - return request->id; -} - -unsigned int -auth_client_request_get_server_pid(struct auth_client_request *request) -{ - return request->conn->server_pid; -} - -const char *auth_client_request_get_cookie(struct auth_client_request *request) -{ - return request->conn->cookie; -} - -bool auth_client_request_is_aborted(struct auth_client_request *request) -{ - return request->callback == NULL; -} - -time_t auth_client_request_get_create_time(struct auth_client_request *request) -{ - return request->created; -} - -void auth_client_request_server_input(struct auth_client_request *request, - enum auth_request_status status, - const char *const *args) -{ - const char *const *tmp, *base64_data = NULL; - - if (request->callback == NULL) { - /* aborted already */ - return; - } - - switch (status) { - case AUTH_REQUEST_STATUS_OK: - for (tmp = args; *tmp != NULL; tmp++) { - if (strncmp(*tmp, "resp=", 5) == 0) { - base64_data = *tmp + 5; - break; - } - } - break; - case AUTH_REQUEST_STATUS_CONTINUE: - base64_data = args[0]; - args = NULL; - break; - case AUTH_REQUEST_STATUS_FAIL: - case AUTH_REQUEST_STATUS_INTERNAL_FAIL: - case AUTH_REQUEST_STATUS_ABORT: - break; - } - - call_callback(request, status, base64_data, args); - if (status != AUTH_REQUEST_STATUS_CONTINUE) - pool_unref(&request->pool); -} - -void auth_client_send_cancel(struct auth_client *client, unsigned int id) -{ - const char *str = t_strdup_printf("CANCEL\t%u\n", id); - - if (o_stream_send_str(client->conn->output, str) < 0) - i_error("Error sending request to auth server: %m"); -} diff --git a/data/Dockerfiles/dovecot/auth-server-connection.c b/data/Dockerfiles/dovecot/auth-server-connection.c deleted file mode 100644 index 7a445549..00000000 --- a/data/Dockerfiles/dovecot/auth-server-connection.c +++ /dev/null @@ -1,489 +0,0 @@ -/* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "hash.h" -#include "hostpid.h" -#include "ioloop.h" -#include "istream.h" -#include "ostream.h" -#include "net.h" -#include "strescape.h" -#include "eacces-error.h" -#include "auth-client-private.h" -#include "auth-client-request.h" -#include "auth-server-connection.h" - -#include - -#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH -#define AUTH_HANDSHAKE_TIMEOUT (30*1000) -#define AUTH_SERVER_RECONNECT_TIMEOUT_SECS 5 - -static void -auth_server_connection_reconnect(struct auth_server_connection *conn, - const char *disconnect_reason); - -static int -auth_server_input_mech(struct auth_server_connection *conn, - const char *const *args) -{ - struct auth_mech_desc mech_desc; - - if (conn->handshake_received) { - i_error("BUG: Authentication server already sent handshake"); - return -1; - } - if (args[0] == NULL) { - i_error("BUG: Authentication server sent broken MECH line"); - return -1; - } - - i_zero(&mech_desc); - mech_desc.name = p_strdup(conn->pool, args[0]); - - if (strcmp(mech_desc.name, "PLAIN") == 0) - conn->has_plain_mech = TRUE; - - for (args++; *args != NULL; args++) { - if (strcmp(*args, "private") == 0) - mech_desc.flags |= MECH_SEC_PRIVATE; - else if (strcmp(*args, "anonymous") == 0) - mech_desc.flags |= MECH_SEC_ANONYMOUS; - else if (strcmp(*args, "plaintext") == 0) - mech_desc.flags |= MECH_SEC_PLAINTEXT; - else if (strcmp(*args, "dictionary") == 0) - mech_desc.flags |= MECH_SEC_DICTIONARY; - else if (strcmp(*args, "active") == 0) - mech_desc.flags |= MECH_SEC_ACTIVE; - else if (strcmp(*args, "forward-secrecy") == 0) - mech_desc.flags |= MECH_SEC_FORWARD_SECRECY; - else if (strcmp(*args, "mutual-auth") == 0) - mech_desc.flags |= MECH_SEC_MUTUAL_AUTH; - } - array_append(&conn->available_auth_mechs, &mech_desc, 1); - return 0; -} - -static int -auth_server_input_spid(struct auth_server_connection *conn, - const char *const *args) -{ - if (conn->handshake_received) { - i_error("BUG: Authentication server already sent handshake"); - return -1; - } - - if (str_to_uint(args[0], &conn->server_pid) < 0) { - i_error("BUG: Authentication server sent invalid PID"); - return -1; - } - return 0; -} - -static int -auth_server_input_cuid(struct auth_server_connection *conn, - const char *const *args) -{ - if (conn->handshake_received) { - i_error("BUG: Authentication server already sent handshake"); - return -1; - } - if (args[0] == NULL || - str_to_uint(args[0], &conn->connect_uid) < 0) { - i_error("BUG: Authentication server sent broken CUID line"); - return -1; - } - return 0; -} - -static int -auth_server_input_cookie(struct auth_server_connection *conn, - const char *const *args) -{ - if (conn->cookie != NULL) { - i_error("BUG: Authentication server already sent cookie"); - return -1; - } - conn->cookie = p_strdup(conn->pool, args[0]); - return 0; -} - -static int auth_server_input_done(struct auth_server_connection *conn) -{ - if (array_count(&conn->available_auth_mechs) == 0) { - i_error("BUG: Authentication server returned no mechanisms"); - return -1; - } - if (conn->cookie == NULL) { - i_error("BUG: Authentication server didn't send a cookie"); - return -1; - } - - if (conn->to != NULL) - timeout_remove(&conn->to); - - conn->handshake_received = TRUE; - if (conn->client->connect_notify_callback != NULL) { - conn->client->connect_notify_callback(conn->client, TRUE, - conn->client->connect_notify_context); - } - return 0; -} - -static int -auth_server_lookup_request(struct auth_server_connection *conn, - const char *id_arg, bool remove, - struct auth_client_request **request_r) -{ - struct auth_client_request *request; - unsigned int id; - - if (id_arg == NULL || str_to_uint(id_arg, &id) < 0) { - i_error("BUG: Authentication server input missing ID"); - return -1; - } - - request = hash_table_lookup(conn->requests, POINTER_CAST(id)); - if (request == NULL) { - i_error("BUG: Authentication server sent unknown id %u", id); - return -1; - } - if (remove || auth_client_request_is_aborted(request)) - hash_table_remove(conn->requests, POINTER_CAST(id)); - - *request_r = request; - return 0; -} - -static int -auth_server_input_ok(struct auth_server_connection *conn, - const char *const *args) -{ - struct auth_client_request *request; - - if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0) - return -1; - auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK, - args + 1); - return 0; -} - -static int auth_server_input_cont(struct auth_server_connection *conn, - const char *const *args) -{ - struct auth_client_request *request; - - if (str_array_length(args) < 2) { - i_error("BUG: Authentication server sent broken CONT line"); - return -1; - } - - if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0) - return -1; - auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE, - args + 1); - return 0; -} - -static int auth_server_input_fail(struct auth_server_connection *conn, - const char *const *args) -{ - struct auth_client_request *request; - - if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0) - return -1; - auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL, - args + 1); - return 0; -} - -static int -auth_server_connection_input_line(struct auth_server_connection *conn, - const char *line) -{ - const char *const *args; - - if (conn->client->debug) - i_debug("auth input: %s", line); - - args = t_strsplit_tabescaped(line); - if (args[0] == NULL) { - i_error("Auth server sent empty line"); - return -1; - } - if (strcmp(args[0], "OK") == 0) - return auth_server_input_ok(conn, args + 1); - else if (strcmp(args[0], "CONT") == 0) - return auth_server_input_cont(conn, args + 1); - else if (strcmp(args[0], "FAIL") == 0) - return auth_server_input_fail(conn, args + 1); - else if (strcmp(args[0], "MECH") == 0) - return auth_server_input_mech(conn, args + 1); - else if (strcmp(args[0], "SPID") == 0) - return auth_server_input_spid(conn, args + 1); - else if (strcmp(args[0], "CUID") == 0) - return auth_server_input_cuid(conn, args + 1); - else if (strcmp(args[0], "COOKIE") == 0) - return auth_server_input_cookie(conn, args + 1); - else if (strcmp(args[0], "DONE") == 0) - return auth_server_input_done(conn); - else { - i_error("Auth server sent unknown command: %s", args[0]); - return -1; - } -} - -static void auth_server_connection_input(struct auth_server_connection *conn) -{ - struct istream *input; - const char *line, *error; - int ret; - - switch (i_stream_read(conn->input)) { - case 0: - return; - case -1: - /* disconnected */ - error = conn->input->stream_errno != 0 ? - strerror(conn->input->stream_errno) : "EOF"; - auth_server_connection_reconnect(conn, error); - return; - case -2: - /* buffer full - can't happen unless auth is buggy */ - i_error("BUG: Auth server sent us more than %d bytes of data", - AUTH_SERVER_CONN_MAX_LINE_LENGTH); - auth_server_connection_disconnect(conn, "buffer full"); - return; - } - - if (!conn->version_received) { - line = i_stream_next_line(conn->input); - if (line == NULL) - return; - - /* make sure the major version matches */ - if (strncmp(line, "VERSION\t", 8) != 0 || - !str_uint_equals(t_strcut(line + 8, '\t'), - AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) { - i_error("Authentication server not compatible with " - "this client (mixed old and new binaries?)"); - auth_server_connection_disconnect(conn, - "incompatible server"); - return; - } - conn->version_received = TRUE; - } - - input = conn->input; - i_stream_ref(input); - while ((line = i_stream_next_line(input)) != NULL && !input->closed) { - T_BEGIN { - ret = auth_server_connection_input_line(conn, line); - } T_END; - - if (ret < 0) { - auth_server_connection_disconnect(conn, t_strdup_printf( - "Received broken input: %s", line)); - break; - } - } - i_stream_unref(&input); -} - -struct auth_server_connection * -auth_server_connection_init(struct auth_client *client) -{ - struct auth_server_connection *conn; - pool_t pool; - - pool = pool_alloconly_create("auth server connection", 1024); - conn = p_new(pool, struct auth_server_connection, 1); - conn->pool = pool; - - conn->client = client; - conn->fd = -1; - hash_table_create_direct(&conn->requests, pool, 100); - i_array_init(&conn->available_auth_mechs, 8); - return conn; -} - -static void -auth_server_connection_remove_requests(struct auth_server_connection *conn, - const char *disconnect_reason) -{ - static const char *const temp_failure_args[] = { "temp", NULL }; - struct hash_iterate_context *iter; - void *key; - struct auth_client_request *request; - time_t created, oldest = 0; - unsigned int request_count = 0; - - if (hash_table_count(conn->requests) == 0) - return; - - iter = hash_table_iterate_init(conn->requests); - while (hash_table_iterate(iter, conn->requests, &key, &request)) { - if (!auth_client_request_is_aborted(request)) { - request_count++; - created = auth_client_request_get_create_time(request); - if (oldest > created || oldest == 0) - oldest = created; - } - - auth_client_request_server_input(request, - AUTH_REQUEST_STATUS_INTERNAL_FAIL, - temp_failure_args); - } - hash_table_iterate_deinit(&iter); - hash_table_clear(conn->requests, FALSE); - - if (request_count > 0) { - i_warning("Auth connection closed with %u pending requests " - "(max %u secs, pid=%s, %s)", request_count, - (unsigned int)(ioloop_time - oldest), - my_pid, disconnect_reason); - } -} - -void auth_server_connection_disconnect(struct auth_server_connection *conn, - const char *reason) -{ - conn->handshake_received = FALSE; - conn->version_received = FALSE; - conn->has_plain_mech = FALSE; - conn->server_pid = 0; - conn->connect_uid = 0; - conn->cookie = NULL; - array_clear(&conn->available_auth_mechs); - - if (conn->to != NULL) - timeout_remove(&conn->to); - if (conn->io != NULL) - io_remove(&conn->io); - if (conn->fd != -1) { - i_stream_destroy(&conn->input); - o_stream_destroy(&conn->output); - - if (close(conn->fd) < 0) - i_error("close(auth server connection) failed: %m"); - conn->fd = -1; - } - - auth_server_connection_remove_requests(conn, reason); - - if (conn->client->connect_notify_callback != NULL) { - conn->client->connect_notify_callback(conn->client, FALSE, - conn->client->connect_notify_context); - } -} - -static void auth_server_reconnect_timeout(struct auth_server_connection *conn) -{ - (void)auth_server_connection_connect(conn); -} - -static void -auth_server_connection_reconnect(struct auth_server_connection *conn, - const char *disconnect_reason) -{ - time_t next_connect; - - auth_server_connection_disconnect(conn, disconnect_reason); - - next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS; - conn->to = timeout_add(ioloop_time >= next_connect ? 0 : - (next_connect - ioloop_time) * 1000, - auth_server_reconnect_timeout, conn); -} - -void auth_server_connection_deinit(struct auth_server_connection **_conn) -{ - struct auth_server_connection *conn = *_conn; - - *_conn = NULL; - - auth_server_connection_disconnect(conn, "deinitializing"); - i_assert(hash_table_count(conn->requests) == 0); - hash_table_destroy(&conn->requests); - array_free(&conn->available_auth_mechs); - pool_unref(&conn->pool); -} - -static void auth_client_handshake_timeout(struct auth_server_connection *conn) -{ - i_error("Timeout waiting for handshake from auth server. " - "my pid=%u, input bytes=%"PRIuUOFF_T, - conn->client->client_pid, conn->input->v_offset); - auth_server_connection_reconnect(conn, "auth server timeout"); -} - -int auth_server_connection_connect(struct auth_server_connection *conn) -{ - const char *handshake; - int fd; - - i_assert(conn->fd == -1); - - conn->last_connect = ioloop_time; - if (conn->to != NULL) - timeout_remove(&conn->to); - - /* max. 1 second wait here. */ - fd = net_connect_unix_with_retries(conn->client->auth_socket_path, - 1000); - if (fd == -1) { - if (errno == EACCES) { - i_error("auth: %s", - eacces_error_get("connect", - conn->client->auth_socket_path)); - } else { - i_error("auth: connect(%s) failed: %m", - conn->client->auth_socket_path); - } - return -1; - } - conn->fd = fd; - conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn); - conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH, - FALSE); - conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); - - handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n", - AUTH_CLIENT_PROTOCOL_MAJOR_VERSION, - AUTH_CLIENT_PROTOCOL_MINOR_VERSION, - conn->client->client_pid); - if (o_stream_send_str(conn->output, handshake) < 0) { - i_warning("Error sending handshake to auth server: %s", - o_stream_get_error(conn->output)); - auth_server_connection_disconnect(conn, - o_stream_get_error(conn->output)); - return -1; - } - - conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT, - auth_client_handshake_timeout, conn); - return 0; -} - -unsigned int -auth_server_connection_add_request(struct auth_server_connection *conn, - struct auth_client_request *request) -{ - unsigned int id; - - id = ++conn->client->request_id_counter; - if (id == 0) { - /* wrapped - ID 0 not allowed */ - id = ++conn->client->request_id_counter; - } - i_assert(hash_table_lookup(conn->requests, POINTER_CAST(id)) == NULL); - hash_table_insert(conn->requests, POINTER_CAST(id), request); - return id; -} - -void auth_server_connection_remove_request(struct auth_server_connection *conn, unsigned int id) -{ - i_assert(conn->handshake_received); - hash_table_remove(conn->requests, POINTER_CAST(id)); -} diff --git a/data/Dockerfiles/dovecot/auth-server-connection.h b/data/Dockerfiles/dovecot/auth-server-connection.h deleted file mode 100644 index ee219d13..00000000 --- a/data/Dockerfiles/dovecot/auth-server-connection.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef AUTH_SERVER_CONNECTION_H -#define AUTH_SERVER_CONNECTION_H - -struct auth_server_connection { - pool_t pool; - - struct auth_client *client; - int fd; - time_t last_connect; - - struct io *io; - struct timeout *to; - struct istream *input; - struct ostream *output; - - unsigned int server_pid; - unsigned int connect_uid; - char *cookie; - - ARRAY(struct auth_mech_desc) available_auth_mechs; - - /* id => request */ - HASH_TABLE(void *, struct auth_client_request *) requests; - - unsigned int version_received:1; - unsigned int handshake_received:1; - unsigned int has_plain_mech:1; -}; - -struct auth_server_connection * -auth_server_connection_init(struct auth_client *client); -void auth_server_connection_deinit(struct auth_server_connection **conn); - -int auth_server_connection_connect(struct auth_server_connection *conn); -void auth_server_connection_disconnect(struct auth_server_connection *conn, - const char *reason); - -unsigned int -auth_server_connection_add_request(struct auth_server_connection *conn, - struct auth_client_request *request); -void auth_server_connection_remove_request(struct auth_server_connection *conn, unsigned int id); -#endif -