diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/imap-urlauth/imap-urlauth-login.c | |
parent | Initial commit. (diff) | |
download | dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/imap-urlauth/imap-urlauth-login.c')
-rw-r--r-- | src/imap-urlauth/imap-urlauth-login.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/imap-urlauth/imap-urlauth-login.c b/src/imap-urlauth/imap-urlauth-login.c new file mode 100644 index 0000000..e917a5b --- /dev/null +++ b/src/imap-urlauth/imap-urlauth-login.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "login-common.h" +#include "str.h" +#include "strescape.h" +#include "base64.h" +#include "net.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "master-service.h" +#include "auth-client.h" +#include "client-common.h" +#include "imap-urlauth-login-settings.h" + +#define IMAP_URLAUTH_PROTOCOL_MAJOR_VERSION 2 +#define IMAP_URLAUTH_PROTOCOL_MINOR_VERSION 0 + +struct imap_urlauth_client { + struct client common; + + const struct imap_urlauth_login_settings *set; + + bool version_received:1; +}; + +static void +imap_urlauth_client_auth_result(struct client *client, + enum client_auth_result result, + const struct client_auth_reply *reply ATTR_UNUSED, + const char *text ATTR_UNUSED) +{ + if (result != CLIENT_AUTH_RESULT_SUCCESS) { + /* failed or otherwise invalid status */ + client_send_raw(client, "FAILED\n"); + client_destroy(client, "Authentication failed"); + } else { + /* authentication succeeded */ + } +} + +static void imap_urlauth_client_handle_input(struct client *client) +{ +#define AUTH_ARG_COUNT 6 + struct imap_urlauth_client *uauth_client = + (struct imap_urlauth_client *)client; + struct net_unix_cred cred; + const char *line; + const char *const *args; + pid_t pid; + + if (!uauth_client->version_received) { + if ((line = i_stream_next_line(client->input)) == NULL) + return; + + if (!version_string_verify(line, "imap-urlauth", + IMAP_URLAUTH_PROTOCOL_MAJOR_VERSION)) { + e_error(client->event, + "IMAP URLAUTH client not compatible with this server " + "(mixed old and new binaries?) %s", line); + client_destroy(client, "Version mismatch"); + return; + } + uauth_client->version_received = TRUE; + } + + if ((line = i_stream_next_line(client->input)) == NULL) + return; + + /* read authentication info from input; + "AUTH"\t<service>\t<session-pid>\t<auth-username>\t<session_id>\t<token> */ + args = t_strsplit_tabescaped(line); + if (str_array_length(args) < AUTH_ARG_COUNT || + strcmp(args[0], "AUTH") != 0 || str_to_pid(args[2], &pid) < 0) { + e_error(client->event, + "IMAP URLAUTH client sent unexpected AUTH input: %s", line); + client_destroy(client, "Unexpected input"); + return; + } + + /* only imap and submission have direct access to urlauth service */ + if (strcmp(args[1], "imap") != 0 && strcmp(args[1], "submission") != 0) { + e_error(client->event, + "IMAP URLAUTH accessed from inappropriate service: %s", args[1]); + client_destroy(client, "Unexpected input"); + return; + } + + /* verify session pid if possible */ + if (net_getunixcred(client->fd, &cred) == 0 && + cred.pid != (pid_t)-1 && pid != cred.pid) { + e_error(client->event, + "IMAP URLAUTH client sent invalid session pid %ld in AUTH request: " + "it did not match peer credentials (pid=%ld, uid=%ld)", + (long)pid, (long)cred.pid, (long)cred.uid); + client_destroy(client, "Invalid AUTH request"); + return; + } + + T_BEGIN { + string_t *auth_data = t_str_new(128); + string_t *init_resp; + unsigned int i; + + str_append(auth_data, args[1]); + for (i = 2; i < AUTH_ARG_COUNT; i++) { + str_append_c(auth_data, '\0'); + str_append(auth_data, args[i]); + } + init_resp = t_str_new(256); + base64_encode(str_data(auth_data), + str_len(auth_data), init_resp); + + (void)client_auth_begin_private(client, "DOVECOT-TOKEN", + str_c(init_resp)); + } T_END; +} + +static void imap_urlauth_client_input(struct client *client) +{ + if (!client_read(client)) + return; + + client_ref(client); + o_stream_cork(client->output); + if (!auth_client_is_connected(auth_client)) { + /* we're not currently connected to auth process - + don't allow any commands */ + timeout_remove(&client->to_auth_waiting); + client->input_blocked = TRUE; + } else { + imap_urlauth_client_handle_input(client); + } + o_stream_uncork(client->output); + client_unref(&client); +} + +static struct client *imap_urlauth_client_alloc(pool_t pool) +{ + struct imap_urlauth_client *uauth_client; + + uauth_client = p_new(pool, struct imap_urlauth_client, 1); + return &uauth_client->common; +} + +static void imap_urlauth_client_create +(struct client *client, void **other_sets) +{ + struct imap_urlauth_client *uauth_client = + (struct imap_urlauth_client *)client; + + uauth_client->set = other_sets[0]; + client->io = io_add_istream(client->input, client_input, client); +} + +static void imap_urlauth_login_preinit(void) +{ + login_set_roots = imap_urlauth_login_setting_roots; +} + +static void imap_urlauth_login_init(void) +{ +} + +static void imap_urlauth_login_deinit(void) +{ + clients_destroy_all(); +} + +static struct client_vfuncs imap_urlauth_vfuncs = { + .alloc = imap_urlauth_client_alloc, + .create = imap_urlauth_client_create, + .input = imap_urlauth_client_input, + .auth_result = imap_urlauth_client_auth_result, + .send_raw_data = client_common_send_raw_data, + .free = client_common_default_free, +}; + +static struct login_binary imap_urlauth_login_binary = { + .protocol = "imap-urlauth", + .process_name = "imap-urlauth-login", + .default_login_socket = LOGIN_TOKEN_DEFAULT_SOCKET, + + .event_category = { + .name = "imap", + }, + + .client_vfuncs = &imap_urlauth_vfuncs, + .preinit = imap_urlauth_login_preinit, + .init = imap_urlauth_login_init, + .deinit = imap_urlauth_login_deinit, + + .anonymous_login_acceptable = TRUE, +}; + +int main(int argc, char *argv[]) +{ + return login_binary_run(&imap_urlauth_login_binary, argc, argv); +} |