From: Stephan Bosch Date: Thu, 1 Dec 2022 22:11:55 +0000 (+0100) Subject: imap-urlauth: Move worker client to separate source file. X-Git-Tag: 2.4.0~2878 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fc5640162410ad9f4d223837db325c62471ad44;p=thirdparty%2Fdovecot%2Fcore.git imap-urlauth: Move worker client to separate source file. --- diff --git a/src/imap-urlauth/imap-urlauth-client.c b/src/imap-urlauth/imap-urlauth-client.c index d27f7051b2..5f6b179821 100644 --- a/src/imap-urlauth/imap-urlauth-client.c +++ b/src/imap-urlauth/imap-urlauth-client.c @@ -134,202 +134,7 @@ void client_send_line(struct client *client, const char *fmt, ...) va_end(va); } -static int client_worker_connect(struct client *client) -{ - static const char handshake[] = "VERSION\timap-urlauth-worker\t2\t0\n"; - const char *socket_path; - ssize_t ret; - unsigned char data; - - socket_path = t_strconcat(client->set->base_dir, - "/"IMAP_URLAUTH_WORKER_SOCKET, NULL); - - e_debug(client->event, "Connecting to worker socket %s", socket_path); - - client->fd_ctrl = net_connect_unix_with_retries(socket_path, 1000); - if (client->fd_ctrl < 0) { - if (errno == EACCES) { - e_error(client->event, "imap-urlauth-client: %s", - eacces_error_get("net_connect_unix", - socket_path)); - } else { - e_error(client->event, "imap-urlauth-client: " - "net_connect_unix(%s) failed: %m", - socket_path); - } - return -1; - } - - /* transfer one or two fds */ - data = (client->fd_in == client->fd_out ? '0' : '1'); - ret = fd_send(client->fd_ctrl, client->fd_in, &data, sizeof(data)); - if (ret > 0 && client->fd_in != client->fd_out) { - data = '0'; - ret = fd_send(client->fd_ctrl, client->fd_out, - &data, sizeof(data)); - } - - if (ret <= 0) { - if (ret < 0) { - e_error(client->event, - "fd_send(%s, %d) failed: %m", - socket_path, client->fd_ctrl); - } else { - e_error(client->event, - "fd_send(%s, %d) failed to send byte", - socket_path, client->fd_ctrl); - } - client_worker_disconnect(client); - return -1; - } - - client->ctrl_output = o_stream_create_fd(client->fd_ctrl, SIZE_MAX); - - /* send protocol version handshake */ - if (o_stream_send_str(client->ctrl_output, handshake) < 0) { - e_error(client->event, - "Error sending handshake to imap-urlauth worker: %m"); - client_worker_disconnect(client); - return -1; - } - - client->ctrl_input = - i_stream_create_fd(client->fd_ctrl, MAX_INBUF_SIZE); - client->ctrl_io = - io_add(client->fd_ctrl, IO_READ, client_worker_input, client); - return 0; -} - -void client_worker_disconnect(struct client *client) -{ - client->worker_state = IMAP_URLAUTH_WORKER_STATE_INACTIVE; - - io_remove(&client->ctrl_io); - o_stream_destroy(&client->ctrl_output); - i_stream_destroy(&client->ctrl_input); - if (client->fd_ctrl >= 0) { - net_disconnect(client->fd_ctrl); - client->fd_ctrl = -1; - } -} - -static int -client_worker_input_line(struct client *client, const char *response) -{ - const char *const *apps; - unsigned int count, i; - bool restart; - string_t *str; - int ret; - - switch (client->worker_state) { - case IMAP_URLAUTH_WORKER_STATE_INACTIVE: - if (strcasecmp(response, "OK") != 0) { - client_disconnect(client, "Worker handshake failed"); - return -1; - } - client->worker_state = IMAP_URLAUTH_WORKER_STATE_CONNECTED; - - str = t_str_new(256); - str_append(str, "ACCESS\t"); - if (client->username != NULL) - str_append_tabescaped(str, client->username); - str_append(str, "\t"); - str_append_tabescaped(str, client->service); - if (client->set->mail_debug) - str_append(str, "\tdebug"); - if (array_count(&client->access_apps) > 0) { - str_append(str, "\tapps="); - apps = array_get(&client->access_apps, &count); - str_append(str, apps[0]); - for (i = 1; i < count; i++) { - str_append_c(str, ','); - str_append_tabescaped(str, apps[i]); - } - } - str_append(str, "\n"); - - ret = o_stream_send(client->ctrl_output, - str_data(str), str_len(str)); - i_assert(ret < 0 || (size_t)ret == str_len(str)); - if (ret < 0) { - client_disconnect(client, - "Failed to send ACCESS control command to worker"); - return -1; - } - break; - - case IMAP_URLAUTH_WORKER_STATE_CONNECTED: - if (strcasecmp(response, "OK") != 0) { - client_disconnect(client, - "Failed to negotiate access parameters"); - return -1; - } - client->worker_state = IMAP_URLAUTH_WORKER_STATE_ACTIVE; - break; - - case IMAP_URLAUTH_WORKER_STATE_ACTIVE: - restart = TRUE; - if (strcasecmp(response, "DISCONNECTED") == 0) { - /* worker detected client disconnect */ - restart = FALSE; - } else if (strcasecmp(response, "FINISHED") != 0) { - /* unknown response */ - client_disconnect(client, - "Worker finished with unknown response"); - return -1; - } - - e_debug(client->event, "Worker finished successfully"); - - if (restart) { - /* connect to new worker for accessing different user */ - client_worker_disconnect(client); - if (client_worker_connect(client) < 0) { - client_disconnect(client, - "Failed to connect to new worker"); - return -1; - } - - /* indicate success of "END" command */ - client_send_line(client, "OK"); - } else { - client_disconnect(client, "Client disconnected"); - } - return -1; - default: - i_unreached(); - } - return 0; -} - -void client_worker_input(struct client *client) -{ - struct istream *input = client->ctrl_input; - const char *line; - - if (input->closed) { - /* disconnected */ - client_disconnect(client, "Worker disconnected unexpectedly"); - return; - } - - switch (i_stream_read(input)) { - case -1: - /* disconnected */ - client_disconnect(client, "Worker disconnected unexpectedly"); - return; - case -2: - /* input buffer full */ - client_disconnect(client, "Worker sent too large input"); - return; - } - - while ((line = i_stream_next_line(input)) != NULL) { - if (client_worker_input_line(client, line) < 0) - return; - } -} +#include "imap-urlauth-worker-client.c" void client_destroy(struct client *client, const char *reason) { diff --git a/src/imap-urlauth/imap-urlauth-worker-client.c b/src/imap-urlauth/imap-urlauth-worker-client.c new file mode 100644 index 0000000000..f4d3788ef3 --- /dev/null +++ b/src/imap-urlauth/imap-urlauth-worker-client.c @@ -0,0 +1,196 @@ +static int client_worker_connect(struct client *client) +{ + static const char handshake[] = "VERSION\timap-urlauth-worker\t2\t0\n"; + const char *socket_path; + ssize_t ret; + unsigned char data; + + socket_path = t_strconcat(client->set->base_dir, + "/"IMAP_URLAUTH_WORKER_SOCKET, NULL); + + e_debug(client->event, "Connecting to worker socket %s", socket_path); + + client->fd_ctrl = net_connect_unix_with_retries(socket_path, 1000); + if (client->fd_ctrl < 0) { + if (errno == EACCES) { + e_error(client->event, "imap-urlauth-client: %s", + eacces_error_get("net_connect_unix", + socket_path)); + } else { + e_error(client->event, "imap-urlauth-client: " + "net_connect_unix(%s) failed: %m", + socket_path); + } + return -1; + } + + /* transfer one or two fds */ + data = (client->fd_in == client->fd_out ? '0' : '1'); + ret = fd_send(client->fd_ctrl, client->fd_in, &data, sizeof(data)); + if (ret > 0 && client->fd_in != client->fd_out) { + data = '0'; + ret = fd_send(client->fd_ctrl, client->fd_out, + &data, sizeof(data)); + } + + if (ret <= 0) { + if (ret < 0) { + e_error(client->event, + "fd_send(%s, %d) failed: %m", + socket_path, client->fd_ctrl); + } else { + e_error(client->event, + "fd_send(%s, %d) failed to send byte", + socket_path, client->fd_ctrl); + } + client_worker_disconnect(client); + return -1; + } + + client->ctrl_output = o_stream_create_fd(client->fd_ctrl, SIZE_MAX); + + /* send protocol version handshake */ + if (o_stream_send_str(client->ctrl_output, handshake) < 0) { + e_error(client->event, + "Error sending handshake to imap-urlauth worker: %m"); + client_worker_disconnect(client); + return -1; + } + + client->ctrl_input = + i_stream_create_fd(client->fd_ctrl, MAX_INBUF_SIZE); + client->ctrl_io = + io_add(client->fd_ctrl, IO_READ, client_worker_input, client); + return 0; +} + +void client_worker_disconnect(struct client *client) +{ + client->worker_state = IMAP_URLAUTH_WORKER_STATE_INACTIVE; + + io_remove(&client->ctrl_io); + o_stream_destroy(&client->ctrl_output); + i_stream_destroy(&client->ctrl_input); + if (client->fd_ctrl >= 0) { + net_disconnect(client->fd_ctrl); + client->fd_ctrl = -1; + } +} + +static int +client_worker_input_line(struct client *client, const char *response) +{ + const char *const *apps; + unsigned int count, i; + bool restart; + string_t *str; + int ret; + + switch (client->worker_state) { + case IMAP_URLAUTH_WORKER_STATE_INACTIVE: + if (strcasecmp(response, "OK") != 0) { + client_disconnect(client, "Worker handshake failed"); + return -1; + } + client->worker_state = IMAP_URLAUTH_WORKER_STATE_CONNECTED; + + str = t_str_new(256); + str_append(str, "ACCESS\t"); + if (client->username != NULL) + str_append_tabescaped(str, client->username); + str_append(str, "\t"); + str_append_tabescaped(str, client->service); + if (client->set->mail_debug) + str_append(str, "\tdebug"); + if (array_count(&client->access_apps) > 0) { + str_append(str, "\tapps="); + apps = array_get(&client->access_apps, &count); + str_append(str, apps[0]); + for (i = 1; i < count; i++) { + str_append_c(str, ','); + str_append_tabescaped(str, apps[i]); + } + } + str_append(str, "\n"); + + ret = o_stream_send(client->ctrl_output, + str_data(str), str_len(str)); + i_assert(ret < 0 || (size_t)ret == str_len(str)); + if (ret < 0) { + client_disconnect(client, + "Failed to send ACCESS control command to worker"); + return -1; + } + break; + + case IMAP_URLAUTH_WORKER_STATE_CONNECTED: + if (strcasecmp(response, "OK") != 0) { + client_disconnect(client, + "Failed to negotiate access parameters"); + return -1; + } + client->worker_state = IMAP_URLAUTH_WORKER_STATE_ACTIVE; + break; + + case IMAP_URLAUTH_WORKER_STATE_ACTIVE: + restart = TRUE; + if (strcasecmp(response, "DISCONNECTED") == 0) { + /* worker detected client disconnect */ + restart = FALSE; + } else if (strcasecmp(response, "FINISHED") != 0) { + /* unknown response */ + client_disconnect(client, + "Worker finished with unknown response"); + return -1; + } + + e_debug(client->event, "Worker finished successfully"); + + if (restart) { + /* connect to new worker for accessing different user */ + client_worker_disconnect(client); + if (client_worker_connect(client) < 0) { + client_disconnect(client, + "Failed to connect to new worker"); + return -1; + } + + /* indicate success of "END" command */ + client_send_line(client, "OK"); + } else { + client_disconnect(client, "Client disconnected"); + } + return -1; + default: + i_unreached(); + } + return 0; +} + +void client_worker_input(struct client *client) +{ + struct istream *input = client->ctrl_input; + const char *line; + + if (input->closed) { + /* disconnected */ + client_disconnect(client, "Worker disconnected unexpectedly"); + return; + } + + switch (i_stream_read(input)) { + case -1: + /* disconnected */ + client_disconnect(client, "Worker disconnected unexpectedly"); + return; + case -2: + /* input buffer full */ + client_disconnect(client, "Worker sent too large input"); + return; + } + + while ((line = i_stream_next_line(input)) != NULL) { + if (client_worker_input_line(client, line) < 0) + return; + } +}