]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
*-login: Use auth proxy parsing API
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 17 Jun 2021 10:17:31 +0000 (13:17 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 17 Jan 2022 11:52:09 +0000 (13:52 +0200)
src/imap-login/client-authenticate.c
src/imap-login/imap-proxy.c
src/login-common/client-common-auth.c
src/login-common/client-common.h
src/login-common/login-proxy.c
src/login-common/login-proxy.h
src/pop3-login/pop3-proxy.c
src/submission-login/submission-proxy.c

index c8c3db288f533ae3aa1a78d46d68a5b78cd58159..f08c313bcab728d3e8c7e40cb9af81d095e54fb7 100644 (file)
@@ -58,11 +58,11 @@ void imap_client_auth_result(struct client *client,
                referral = t_str_new(128);
 
                i_zero(&url);
-               url.userid = reply->destuser;
+               url.userid = reply->proxy.username;
                url.auth_type = client->auth_mech_name;
-               url.host.name = reply->host;
-               if (reply->port != 143)
-                       url.port = reply->port;
+               url.host.name = reply->proxy.host;
+               if (reply->proxy.port != 143)
+                       url.port = reply->proxy.port;
                str_append(referral, "REFERRAL ");
                str_append(referral, imap_url_create(&url));
 
index f185f3d8cad74a87e7a4db5dabe090f29288119f..772515dada8932ac5e4567ea73e388d4d999337c 100644 (file)
@@ -68,8 +68,9 @@ static void proxy_write_id(struct imap_client *client, string_t *str)
 
 static int proxy_write_starttls(struct imap_client *client, string_t *str)
 {
-       enum login_proxy_ssl_flags ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
-       if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
+       enum auth_proxy_ssl_flags ssl_flags =
+               login_proxy_get_ssl_flags(client->common.login_proxy);
+       if ((ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) != 0) {
                if (client->proxy_backend_capability != NULL &&
                    !str_array_icase_find(t_strsplit(client->proxy_backend_capability, " "), "STARTTLS")) {
                        login_proxy_failed(client->common.login_proxy,
index 848285a14ed0db274ca19119d7a467c5e231c086..671c835cec27092f6d4d699695e5f99355ed5dfa 100644 (file)
@@ -135,6 +135,7 @@ static bool client_auth_parse_args(const struct client *client, bool success,
                                   struct client_auth_reply *reply_r)
 {
        const char *key, *value, *p, *error;
+       int ret;
 
        i_zero(reply_r);
        t_array_init(&reply_r->alt_usernames, 4);
@@ -150,55 +151,22 @@ static bool client_auth_parse_args(const struct client *client, bool success,
                        key = t_strdup_until(*args, p);
                        value = p + 1;
                }
+               ret = auth_proxy_settings_parse(&reply_r->proxy, NULL,
+                                               key, value, &error);
+               if (ret < 0) {
+                       e_error(client->event, "Auth service returned invalid "
+                               "%s value '%s': %s", key, value, error);
+                       return FALSE;
+               }
+               if (ret > 0)
+                       continue;
+
                if (strcmp(key, "nologin") == 0) {
                        reply_r->nologin = TRUE;
                        reply_r->fail_code = CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED;
-               } else if (strcmp(key, "proxy") == 0)
-                       reply_r->proxy = TRUE;
-               else if (strcmp(key, "reason") == 0)
+               } else if (strcmp(key, "reason") == 0)
                        reply_r->reason = value;
-               else if (strcmp(key, "host") == 0)
-                       reply_r->host = value;
-               else if (strcmp(key, "hostip") == 0) {
-                       if (value[0] != '\0' &&
-                           net_addr2ip(value, &reply_r->host_ip) < 0) {
-                               e_error(client->event,
-                                       "Auth service returned invalid "
-                                       "hostip %s", value);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "source_ip") == 0) {
-                       if (value[0] != '\0' &&
-                           net_addr2ip(value, &reply_r->source_ip) < 0) {
-                               e_error(client->event,
-                                       "Auth service returned invalid "
-                                       "source_ip %s", value);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "port") == 0) {
-                       if (net_str2port(value, &reply_r->port) < 0) {
-                               e_error(client->event,
-                                       "Auth service returned invalid "
-                                       "port number: %s", value);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "destuser") == 0)
-                       reply_r->destuser = value;
-               else if (strcmp(key, "pass") == 0)
-                       reply_r->password = value;
-               else if (strcmp(key, "proxy_timeout") == 0) {
-                       /* backwards compatibility: plain number is seconds */
-                       if (str_to_uint(value, &reply_r->proxy_timeout_msecs) == 0)
-                               reply_r->proxy_timeout_msecs *= 1000;
-                       else if (settings_get_time_msecs(value,
-                               &reply_r->proxy_timeout_msecs, &error) < 0) {
-                               e_error(client->event,
-                                       "Auth service returned invalid "
-                                       "proxy_timeout value '%s': %s",
-                                       value, error);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "proxy_host_immediate_failure_after") == 0) {
+               else if (strcmp(key, "proxy_host_immediate_failure_after") == 0) {
                        if (settings_get_time(value,
                                &reply_r->proxy_host_immediate_failure_after_secs,
                                &error) < 0) {
@@ -215,31 +183,6 @@ static bool client_auth_parse_args(const struct client *client, bool success,
                                        "proxy_refresh value: %s", value);
                                return FALSE;
                        }
-               } else if (strcmp(key, "proxy_mech") == 0)
-                       reply_r->proxy_mech = value;
-               else if (strcmp(key, "proxy_noauth") == 0)
-                       reply_r->proxy_noauth = TRUE;
-               else if (strcmp(key, "proxy_nopipelining") == 0)
-                       reply_r->proxy_nopipelining = TRUE;
-               else if (strcmp(key, "proxy_not_trusted") == 0)
-                       reply_r->proxy_not_trusted = TRUE;
-               else if (strcmp(key, "proxy_redirect_reauth") == 0)
-                       reply_r->proxy_redirect_reauth = TRUE;
-               else if (strcmp(key, "master") == 0) {
-                       /* ignore empty master field */
-                       if (*value != '\0')
-                               reply_r->master_user = value;
-               } else if (strcmp(key, "ssl") == 0) {
-                       reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
-                       if (strcmp(value, "any-cert") == 0)
-                               reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
-                       if (reply_r->port == 0)
-                               reply_r->port = login_binary->default_ssl_port;
-               } else if (strcmp(key, "starttls") == 0) {
-                       reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
-                               PROXY_SSL_FLAG_STARTTLS;
-                       if (strcmp(value, "any-cert") == 0)
-                               reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
                } else if (strcmp(key, "code") == 0) {
                        if (reply_r->fail_code != CLIENT_AUTH_FAIL_CODE_NONE) {
                                /* code already assigned */
@@ -259,27 +202,34 @@ static bool client_auth_parse_args(const struct client *client, bool success,
                } else
                        e_debug(event_auth, "Ignoring unknown passdb extra field: %s", key);
        }
-       if (reply_r->port == 0)
-               reply_r->port = login_binary->default_port;
+       if (reply_r->proxy.port == 0) {
+               if ((reply_r->proxy.ssl_flags & AUTH_PROXY_SSL_FLAG_YES) != 0 &&
+                   (reply_r->proxy.ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0)
+                       reply_r->proxy.port = login_binary->default_ssl_port;
+               else
+                       reply_r->proxy.port = login_binary->default_port;
+       }
 
-       if (reply_r->destuser == NULL)
-               reply_r->destuser = client->virtual_user;
+       if (reply_r->proxy.username == NULL)
+               reply_r->proxy.username = client->virtual_user;
 
-       if (reply_r->proxy) {
-               if (reply_r->password == NULL) {
+       if (reply_r->proxy.proxy) {
+               if (reply_r->proxy.password == NULL) {
                        e_error(client->event, "proxy: pass field is missing");
                        return FALSE;
                }
-               if (reply_r->host == NULL || reply_r->host[0] == '\0') {
+               if (reply_r->proxy.host == NULL ||
+                   reply_r->proxy.host[0] == '\0') {
                        e_error(client->event, "proxy: host field not given");
                        return FALSE;
                }
 
-               if (reply_r->host_ip.family == 0 &&
-                   net_addr2ip(reply_r->host, &reply_r->host_ip) < 0) {
+               if (reply_r->proxy.host_ip.family == 0 &&
+                   net_addr2ip(reply_r->proxy.host,
+                               &reply_r->proxy.host_ip) < 0) {
                        e_error(client->event,
                                "proxy: host %s is not an IP (auth should have changed it)",
-                               reply_r->host);
+                               reply_r->proxy.host);
                        return FALSE;
                }
        }
@@ -446,12 +396,13 @@ proxy_redirect_reauth_callback(struct auth_client_request *request,
                        break;
                }
 
-               if (!reply.proxy) {
+               if (!reply.proxy.proxy) {
                        error = "Redirect authentication is missing proxy field";
                        break;
                }
                login_proxy_redirect_finish(client->login_proxy,
-                                           &reply.host_ip, reply.port);
+                                           &reply.proxy.host_ip,
+                                           reply.proxy.port);
                return;
        case AUTH_REQUEST_STATUS_INTERNAL_FAIL:
                error = "Internal authentication failure";
@@ -592,24 +543,24 @@ proxy_check_start(struct client *client, struct event *event,
                  const struct client_auth_reply *reply,
                  const struct dsasl_client_mech **sasl_mech_r)
 {
-       i_assert(reply->password != NULL);
-       i_assert(reply->host != NULL && reply->host[0] != '\0');
-       i_assert(reply->host_ip.family != 0);
+       i_assert(reply->proxy.password != NULL);
+       i_assert(reply->proxy.host != NULL && reply->proxy.host[0] != '\0');
+       i_assert(reply->proxy.host_ip.family != 0);
 
-       if (reply->proxy_mech != NULL) {
-               *sasl_mech_r = dsasl_client_mech_find(reply->proxy_mech);
+       if (reply->proxy.sasl_mechanism != NULL) {
+               *sasl_mech_r = dsasl_client_mech_find(reply->proxy.sasl_mechanism);
                if (*sasl_mech_r == NULL) {
                        e_error(event, "Unsupported SASL mechanism %s",
-                               reply->proxy_mech);
+                               reply->proxy.sasl_mechanism);
                        return FALSE;
                }
-       } else if (reply->master_user != NULL) {
+       } else if (reply->proxy.master_user != NULL) {
                /* have to use PLAIN authentication with master user logins */
                *sasl_mech_r = &dsasl_client_mech_plain;
        }
 
-       if (login_proxy_is_ourself(client, reply->host, reply->port,
-                                  reply->destuser)) {
+       if (login_proxy_is_ourself(client, reply->proxy.host, reply->proxy.port,
+                                  reply->proxy.username)) {
                e_error(event, "Proxying loops to itself");
                return FALSE;
        }
@@ -623,7 +574,7 @@ static int proxy_start(struct client *client,
        const struct dsasl_client_mech *sasl_mech = NULL;
        struct event *event;
 
-       i_assert(reply->destuser != NULL);
+       i_assert(reply->proxy.username != NULL);
        i_assert(client->refcount > 1);
        i_assert(!client->destroyed);
        i_assert(client->proxy_sasl_client == NULL);
@@ -643,34 +594,34 @@ static int proxy_start(struct client *client,
        }
 
        i_zero(&proxy_set);
-       proxy_set.host = reply->host;
-       proxy_set.ip = reply->host_ip;
-       if (reply->source_ip.family != 0) {
-               proxy_set.source_ip = reply->source_ip;
+       proxy_set.host = reply->proxy.host;
+       proxy_set.ip = reply->proxy.host_ip;
+       if (reply->proxy.source_ip.family != 0) {
+               proxy_set.source_ip = reply->proxy.source_ip;
        } else if (login_source_ips_count > 0) {
                /* select the next source IP with round robin. */
                proxy_set.source_ip = login_source_ips[login_source_ips_idx];
                login_source_ips_idx =
                        (login_source_ips_idx + 1) % login_source_ips_count;
        }
-       proxy_set.port = reply->port;
-       proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
+       proxy_set.port = reply->proxy.port;
+       proxy_set.connect_timeout_msecs = reply->proxy.timeout_msecs;
        if (proxy_set.connect_timeout_msecs == 0)
                proxy_set.connect_timeout_msecs = client->set->login_proxy_timeout;
        proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
-       proxy_set.ssl_flags = reply->ssl_flags;
+       proxy_set.ssl_flags = reply->proxy.ssl_flags;
        proxy_set.host_immediate_failure_after_secs =
                reply->proxy_host_immediate_failure_after_secs;
        proxy_set.rawlog_dir = client->set->login_proxy_rawlog_dir;
 
        client->proxy_mech = sasl_mech;
-       client->proxy_user = i_strdup(reply->destuser);
-       client->proxy_master_user = i_strdup(reply->master_user);
-       client->proxy_password = i_strdup(reply->password);
-       client->proxy_noauth = reply->proxy_noauth;
-       client->proxy_nopipelining = reply->proxy_nopipelining;
-       client->proxy_not_trusted = reply->proxy_not_trusted;
-       client->proxy_redirect_reauth = reply->proxy_redirect_reauth;
+       client->proxy_user = i_strdup(reply->proxy.username);
+       client->proxy_master_user = i_strdup(reply->proxy.master_user);
+       client->proxy_password = i_strdup(reply->proxy.password);
+       client->proxy_nopipelining = reply->proxy.nopipelining;
+       client->proxy_noauth = reply->proxy.noauth;
+       client->proxy_not_trusted = reply->proxy.remote_not_trusted;
+       client->proxy_redirect_reauth = reply->proxy.redirect_reauth;
 
        if (login_proxy_new(client, event, &proxy_set, proxy_input,
                            client->v.proxy_failed, proxy_redirect) < 0) {
@@ -707,7 +658,7 @@ client_auth_handle_reply(struct client *client,
                client->alt_usernames = alt;
        }
 
-       if (reply->proxy) {
+       if (reply->proxy.proxy) {
                /* we want to proxy the connection to another server.
                   don't do this unless authentication succeeded. with
                   master user proxying we can get FAIL with proxy still set.
@@ -726,7 +677,7 @@ client_auth_handle_reply(struct client *client,
                return TRUE;
        }
 
-       if (reply->host != NULL) {
+       if (reply->proxy.host != NULL) {
                const char *reason;
 
                if (reply->reason != NULL)
index b3e7d720190fafb2260c2d0ff102bb0b772c1b9a..7ad29cc929fc50ec39f9f2cdd2697e7bc70dd41f 100644 (file)
@@ -94,28 +94,17 @@ enum client_list_type {
 };
 
 struct client_auth_reply {
-       const char *master_user, *reason;
+       const char *reason;
        enum client_auth_fail_code fail_code;
        ARRAY_TYPE(const_string) alt_usernames;
 
-       /* for proxying */
-       const char *host;
-       struct ip_addr source_ip, host_ip;
-       const char *destuser, *password, *proxy_mech;
-       in_port_t port;
-       unsigned int proxy_timeout_msecs;
+       struct auth_proxy_settings proxy;
        unsigned int proxy_refresh_secs;
        unsigned int proxy_host_immediate_failure_after_secs;
-       enum login_proxy_ssl_flags ssl_flags;
 
        /* all the key=value fields returned by passdb */
        const char *const *all_fields;
 
-       bool proxy:1;
-       bool proxy_noauth:1;
-       bool proxy_nopipelining:1;
-       bool proxy_not_trusted:1;
-       bool proxy_redirect_reauth:1;
        bool nologin:1;
 };
 
index 643512e45e898ce30f6830520771ced23095f3ca..1d5b0055ed12c6c5e67ad058000a2086cfa400a3 100644 (file)
@@ -74,7 +74,7 @@ struct login_proxy {
        unsigned int notify_refresh_secs;
        unsigned int host_immediate_failure_after_secs;
        unsigned int reconnect_count;
-       enum login_proxy_ssl_flags ssl_flags;
+       enum auth_proxy_ssl_flags ssl_flags;
        char *rawlog_dir;
 
        login_proxy_input_callback_t *input_callback;
@@ -335,8 +335,8 @@ static void proxy_wait_connect(struct login_proxy *proxy)
        io_remove(&proxy->server_io);
        proxy_plain_connected(proxy);
 
-       if ((proxy->ssl_flags & PROXY_SSL_FLAG_YES) != 0 &&
-           (proxy->ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
+       if ((proxy->ssl_flags & AUTH_PROXY_SSL_FLAG_YES) != 0 &&
+           (proxy->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0) {
                if (login_proxy_starttls(proxy) < 0) {
                        /* proxy is already destroyed */
                }
@@ -805,7 +805,7 @@ in_port_t login_proxy_get_port(const struct login_proxy *proxy)
        return proxy->port;
 }
 
-enum login_proxy_ssl_flags
+enum auth_proxy_ssl_flags
 login_proxy_get_ssl_flags(const struct login_proxy *proxy)
 {
        return proxy->ssl_flags;
@@ -913,7 +913,7 @@ int login_proxy_starttls(struct login_proxy *proxy)
 
        master_service_ssl_client_settings_to_iostream_set(
                proxy->client->ssl_set, pool_datastack_create(), &ssl_set);
-       if ((proxy->ssl_flags & PROXY_SSL_FLAG_ANY_CERT) != 0)
+       if ((proxy->ssl_flags & AUTH_PROXY_SSL_FLAG_ANY_CERT) != 0)
                ssl_set.allow_invalid_cert = TRUE;
        /* NOTE: We're explicitly disabling ssl_client_ca_* settings for now
           at least. The main problem is that we're chrooted, so we can't read
index 48cf0bf629cc4a0cdd7727a6e4dfeaef8c3f8b0c..7cdc3beabca5efac90e0ce02329b0ff11d057603 100644 (file)
@@ -2,6 +2,7 @@
 #define LOGIN_PROXY_H
 
 #include "net.h"
+#include "auth-proxy.h"
 
 /* Max. number of embedded proxying connections until proxying fails.
    This is intended to avoid an accidental configuration where two proxies
 struct client;
 struct login_proxy;
 
-enum login_proxy_ssl_flags {
-       /* Use SSL/TLS enabled */
-       PROXY_SSL_FLAG_YES      = 0x01,
-       /* Don't do SSL handshake immediately after connected */
-       PROXY_SSL_FLAG_STARTTLS = 0x02,
-       /* Don't require that the received certificate is valid */
-       PROXY_SSL_FLAG_ANY_CERT = 0x04
-};
-
 enum login_proxy_failure_type {
        /* connect() failed or remote disconnected us. */
        LOGIN_PROXY_FAILURE_TYPE_CONNECT,
@@ -59,7 +51,7 @@ struct login_proxy_settings {
           every n seconds */
        unsigned int notify_refresh_secs;
        unsigned int host_immediate_failure_after_secs;
-       enum login_proxy_ssl_flags ssl_flags;
+       enum auth_proxy_ssl_flags ssl_flags;
        const char *rawlog_dir;
 };
 
@@ -121,7 +113,7 @@ const char *login_proxy_get_source_host(const struct login_proxy *proxy) ATTR_PU
 const char *login_proxy_get_host(const struct login_proxy *proxy) ATTR_PURE;
 const char *login_proxy_get_ip_str(const struct login_proxy *proxy) ATTR_PURE;
 in_port_t login_proxy_get_port(const struct login_proxy *proxy) ATTR_PURE;
-enum login_proxy_ssl_flags
+enum auth_proxy_ssl_flags
 login_proxy_get_ssl_flags(const struct login_proxy *proxy) ATTR_PURE;
 unsigned int
 login_proxy_get_connect_timeout_msecs(const struct login_proxy *proxy) ATTR_PURE;
index fd8dfcef936f710fa57a3e6d77bedad87cbe8a05..3eb2d1b1098720d1e7c57b0e67d6249820a5a14e 100644 (file)
@@ -145,7 +145,7 @@ int pop3_proxy_parse_line(struct client *client, const char *line)
 {
        struct pop3_client *pop3_client = (struct pop3_client *)client;
        struct ostream *output;
-       enum login_proxy_ssl_flags ssl_flags;
+       enum auth_proxy_ssl_flags ssl_flags;
 
        i_assert(!client->destroyed);
 
@@ -165,7 +165,7 @@ int pop3_proxy_parse_line(struct client *client, const char *line)
                        str_begins(line+3, " [XCLIENT]");
 
                ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
-               if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
+               if ((ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0) {
                        if (proxy_send_login(pop3_client, output) < 0)
                                return -1;
                } else {
index 0148c43556babf746be8a5627ede592efd02e8a5..600ff2e38b19fa85f409284bdb663ddc830d98e8 100644 (file)
@@ -32,10 +32,10 @@ submission_proxy_success_reply_sent(
 static int
 proxy_send_starttls(struct submission_client *client, struct ostream *output)
 {
-       enum login_proxy_ssl_flags ssl_flags;
+       enum auth_proxy_ssl_flags ssl_flags;
 
        ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
-       if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0)
+       if ((ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0)
                return 0;
 
        if ((client->proxy_capability & SMTP_CAPABILITY_STARTTLS) == 0) {