]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-dovecot - Generate and parse referral data as URI authority.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Sat, 20 Nov 2021 22:35:16 +0000 (23:35 +0100)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 17 Jan 2022 11:52:10 +0000 (13:52 +0200)
This makes sure special characters are escaped properly. Before, usernames with
special characters and IPv6 caused problems.

src/lib-smtp/smtp-dovecot.c
src/lib-smtp/smtp-dovecot.h
src/lmtp/lmtp-proxy.c
src/submission-login/client-authenticate.c

index 510091a41207cc624bdaca7191c4f31fe24a72fe..88e68a6099fe6a8c15e2eed36afff24372965249 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "lib.h"
 #include "str.h"
-#include "auth-proxy.h"
+#include "uri-util.h"
 #include "smtp-common.h"
 #include "smtp-reply.h"
 #include "smtp-server.h"
@@ -20,32 +20,55 @@ bool smtp_reply_is_proxy_redirect(const struct smtp_reply *reply)
                                      SMTP_PROXY_REDIRECT_ENH_CODE);
 }
 
-int smtp_proxy_redirect_parse(const char *target, const char **destuser_r,
+int smtp_proxy_redirect_parse(const char *resp, const char **destuser_r,
                              const char **host_r, struct ip_addr *ip_r,
                              in_port_t *port_r, const char **error_r)
 {
        const char *pend;
 
+       *destuser_r = NULL;
+       *host_r = NULL;
+       i_zero(ip_r);
+       *port_r = 0;
        *error_r = NULL;
 
        /* Skip <address> part of the reply if present (RCPT reply) */
-       pend = strchr(target, ' ');
-       if (*target == '<') {
-               if (pend == NULL) {
+       pend = strchr(resp, ' ');
+       if (*resp == '<') {
+               if (pend == NULL || *(pend - 1) != '>') {
                        *error_r = "Invalid path in redirect response";
                        return -1;
                }
-               target = pend + 1;
-               pend = strchr(target, ' ');
+               resp = pend + 1;
        }
-       if (pend != NULL)
-               target = t_strdup_until(target, pend);
 
-       if (!auth_proxy_parse_redirect(target, destuser_r, host_r,
-                                      ip_r, port_r)) {
-               *error_r = "Invalid redirect data";
+       struct uri_parser parser;
+       const char *destuser;
+       struct uri_authority uri_auth;
+
+       i_zero(&parser);
+       parser.pool = pool_datastack_create();
+       parser.begin = parser.cur = (const unsigned char *)resp;
+       parser.end = parser.begin + strlen(resp);
+       parser.parse_prefix = TRUE;
+
+       if (uri_parse_host_authority(&parser, &uri_auth) < 0 ||
+           !uri_data_decode(&parser, uri_auth.enc_userinfo, NULL, &destuser)) {
+               *error_r = parser.error;
                return -1;
+
        }
+       if (*parser.cur != '\0' && *parser.cur != ' ') {
+               *error_r = t_strdup_printf(
+                       "Invalid character %s in redirect target",
+                       uri_char_sanitize(*parser.cur));
+               return -1;
+       }
+
+       *destuser_r = destuser;
+       *host_r = uri_auth.host.name;
+       *ip_r = uri_auth.host.ip;
+       *port_r = uri_auth.port;
        return 0;
 }
 
@@ -55,12 +78,16 @@ smtp_create_redirect_reply(const struct smtp_proxy_redirect *predir,
 {
        string_t *referral = t_str_new(128);
 
+       struct uri_host host = {
+               .name = predir->host,
+               .ip = predir->host_ip,
+       };
        if (predir->username != NULL)
-               str_printfa(referral, "%s@", predir->username);
-       if (predir->port == default_port)
-               str_append(referral, predir->host);
-       else
-               str_printfa(referral, "%s:%u", predir->host, predir->port);
+               uri_append_userinfo(referral, predir->username);
+       uri_append_host(referral, &host);
+       if (predir->port != default_port)
+               uri_append_port(referral, predir->port);
+
        return str_c(referral);
 }
 
index 75352d325e9d14ddc9e8307e2593452343f5d9db..0757a892e091c789b006b84872f51e3d08f88d7f 100644 (file)
@@ -14,13 +14,14 @@ struct smtp_server_recipient;
 struct smtp_proxy_redirect {
        const char *username;
        const char *host;
+       struct ip_addr host_ip;
        in_port_t port;
 };
 
 bool smtp_reply_code_is_proxy_redirect(unsigned int code, const char *enh_code);
 bool smtp_reply_is_proxy_redirect(const struct smtp_reply *reply);
 
-int smtp_proxy_redirect_parse(const char *target, const char **destuser_r,
+int smtp_proxy_redirect_parse(const char *resp, const char **destuser_r,
                              const char **host_r, struct ip_addr *ip_r,
                              in_port_t *port_r, const char **error_r);
 
index f5ffdaf4dfe5dacbbb1c1955540bfb9d9d90147f..205acd21b89405d2748017b1c9c19b44746bd3b7 100644 (file)
@@ -846,6 +846,7 @@ lmtp_proxy_rcpt_handle_not_proxied(struct lmtp_proxy_recipient *lprcpt,
        const struct smtp_proxy_redirect predir = {
                .username = destuser,
                .host = set->set.host,
+               .host_ip = set->set.host_ip,
                .port = set->set.port,
        };
        smtp_server_recipient_reply_redirect(rcpt, 0, &predir);
index d9c03ff3b15193455ee654c50470168e77686265..afd086c9c752bdfd768243b4e1816bffc60a2cbc 100644 (file)
@@ -114,6 +114,7 @@ void submission_client_auth_result(struct client *client,
                const struct smtp_proxy_redirect predir = {
                        .username = reply->proxy.username,
                        .host = reply->proxy.host,
+                       .host_ip = reply->proxy.host_ip,
                        .port = reply->proxy.port,
                };
                smtp_server_reply_redirect(cmd, login_binary->default_port,