]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp: Moved code relating to proxy from commands.c to lmtp-proxy.c.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 6 Nov 2016 16:34:25 +0000 (17:34 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Thu, 7 Dec 2017 23:08:14 +0000 (00:08 +0100)
src/lmtp/commands.c
src/lmtp/lmtp-proxy.c
src/lmtp/lmtp-proxy.h

index d4cc9144498a968131109ae540ed9dfc09543487..f7f12dec1e14abd2bd26ecb1b1d6da7e7f1de509 100644 (file)
@@ -16,7 +16,6 @@
 #include "iostream-ssl.h"
 #include "rfc822-parser.h"
 #include "message-date.h"
-#include "auth-master.h"
 #include "mail-storage-service.h"
 #include "index/raw/raw-storage.h"
 #include "lda-settings.h"
 #include "lmtp-proxy.h"
 
 #define ERRSTR_TEMP_MAILBOX_FAIL "451 4.3.0 <%s> Temporary internal error"
-#define ERRSTR_TEMP_USERDB_FAIL_PREFIX "451 4.3.0 <%s> "
-#define ERRSTR_TEMP_USERDB_FAIL \
-       ERRSTR_TEMP_USERDB_FAIL_PREFIX "Temporary user lookup failure"
-
-#define LMTP_PROXY_DEFAULT_TIMEOUT_MSECS (1000*125)
 
 int cmd_lhlo(struct client *client, const char *args)
 {
@@ -173,211 +167,6 @@ int cmd_mail(struct client *client, const char *args)
        return 0;
 }
 
-static bool
-client_proxy_rcpt_parse_fields(struct lmtp_proxy_rcpt_settings *set,
-                              const char *const *args, const char **address)
-{
-       const char *p, *key, *value;
-       bool proxying = FALSE, port_set = FALSE;
-
-       for (; *args != NULL; args++) {
-               p = strchr(*args, '=');
-               if (p == NULL) {
-                       key = *args;
-                       value = "";
-               } else {
-                       key = t_strdup_until(*args, p);
-                       value = p + 1;
-               }
-
-               if (strcmp(key, "proxy") == 0)
-                       proxying = TRUE;
-               else if (strcmp(key, "host") == 0)
-                       set->host = value;
-               else if (strcmp(key, "hostip") == 0) {
-                       if (net_addr2ip(value, &set->hostip) < 0) {
-                               i_error("proxy: Invalid hostip %s", value);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "port") == 0) {
-                       if (net_str2port(value, &set->port) < 0) {
-                               i_error("proxy: Invalid port number %s", value);
-                               return FALSE;
-                       }
-                       port_set = TRUE;
-               } else if (strcmp(key, "proxy_timeout") == 0) {
-                       if (str_to_uint(value, &set->timeout_msecs) < 0) {
-                               i_error("proxy: Invalid proxy_timeout value %s", value);
-                               return FALSE;
-                       }
-                       set->timeout_msecs *= 1000;
-               } else if (strcmp(key, "protocol") == 0) {
-                       if (strcmp(value, "lmtp") == 0) {
-                               set->protocol = SMTP_PROTOCOL_LMTP;
-                               if (!port_set)
-                                       set->port = 24;
-                       } else if (strcmp(value, "smtp") == 0) {
-                               set->protocol = SMTP_PROTOCOL_SMTP;
-                               if (!port_set)
-                                       set->port = 25;
-                       } else {
-                               i_error("proxy: Unknown protocol %s", value);
-                               return FALSE;
-                       }
-               } else if (strcmp(key, "user") == 0 ||
-                          strcmp(key, "destuser") == 0) {
-                       /* changing the username */
-                       *address = value;
-               } else {
-                       /* just ignore it */
-               }
-       }
-       if (proxying && set->host == NULL) {
-               i_error("proxy: host not given");
-               return FALSE;
-       }
-       return proxying;
-}
-
-static bool
-client_proxy_is_ourself(const struct client *client,
-                       const struct lmtp_proxy_rcpt_settings *set)
-{
-       struct ip_addr ip;
-
-       if (set->port != client->local_port)
-               return FALSE;
-
-       if (set->hostip.family != 0)
-               ip = set->hostip;
-       else {
-               if (net_addr2ip(set->host, &ip) < 0)
-                       return FALSE;
-       }
-       if (!net_ip_compare(&ip, &client->local_ip))
-               return FALSE;
-       return TRUE;
-}
-
-static bool client_proxy_rcpt(struct client *client,
-                             struct smtp_address *address,
-                             const char *username, const char *detail, char delim,
-                             struct smtp_params_rcpt *params)
-{
-       struct auth_master_connection *auth_conn;
-       struct lmtp_proxy_rcpt_settings set;
-       struct auth_user_info info;
-       struct mail_storage_service_input input;
-       const char *const *fields, *errstr, *orig_username = username;
-       struct smtp_address *user;
-       pool_t pool;
-       int ret;
-
-       i_zero(&input);
-       input.module = input.service = "lmtp";
-       mail_storage_service_init_settings(storage_service, &input);
-
-       i_zero(&info);
-       info.service = master_service_get_name(master_service);
-       info.local_ip = client->local_ip;
-       info.remote_ip = client->remote_ip;
-       info.local_port = client->local_port;
-       info.remote_port = client->remote_port;
-
-       pool = pool_alloconly_create("auth lookup", 1024);
-       auth_conn = mail_storage_service_get_auth_conn(storage_service);
-       ret = auth_master_pass_lookup(auth_conn, username, &info,
-                                     pool, &fields);
-       if (ret <= 0) {
-               errstr = ret < 0 && fields[0] != NULL ? t_strdup(fields[0]) :
-                       t_strdup_printf(ERRSTR_TEMP_USERDB_FAIL,
-                               smtp_address_encode(address));
-               pool_unref(&pool);
-               if (ret < 0) {
-                       client_send_line(client, "%s", errstr);
-                       return TRUE;
-               } else {
-                       /* user not found from passdb. try userdb also. */
-                       return FALSE;
-               }
-       }
-
-       i_zero(&set);
-       set.port = client->local_port;
-       set.protocol = SMTP_PROTOCOL_LMTP;
-       set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
-       set.params = *params;
-
-       if (!client_proxy_rcpt_parse_fields(&set, fields, &username)) {
-               /* not proxying this user */
-               pool_unref(&pool);
-               return FALSE;
-       }
-       if (strcmp(username, orig_username) != 0) {
-               if (smtp_address_parse_username(pool_datastack_create(),
-                                               username, &user, &errstr) < 0) {
-                       i_error("%s: Username `%s' returned by passdb lookup is not a valid SMTP address",
-                               orig_username, username);
-                       client_send_line(client, "550 5.3.5 <%s> "
-                               "Internal user lookup failure",
-                               smtp_address_encode(address));
-                       pool_unref(&pool);
-                       return FALSE;
-               }
-               /* username changed. change the address as well */
-               if (*detail == '\0') {
-                       address = user;
-               } else {
-                       address = smtp_address_add_detail_temp(user, detail, delim);
-               }
-       } else if (client_proxy_is_ourself(client, &set)) {
-               i_error("Proxying to <%s> loops to itself", username);
-               client_send_line(client, "554 5.4.6 <%s> "
-                                "Proxying loops to itself",
-                                smtp_address_encode(address));
-               pool_unref(&pool);
-               return TRUE;
-       }
-
-       if (client->proxy_ttl <= 1) {
-               i_error("Proxying to <%s> appears to be looping (TTL=0)",
-                       username);
-               client_send_line(client, "554 5.4.6 <%s> "
-                                "Proxying appears to be looping (TTL=0)",
-                                username);
-               pool_unref(&pool);
-               return TRUE;
-       }
-       if (array_count(&client->state.rcpt_to) != 0) {
-               client_send_line(client, "451 4.3.0 <%s> "
-                       "Can't handle mixed proxy/non-proxy destinations",
-                       smtp_address_encode(address));
-               pool_unref(&pool);
-               return TRUE;
-       }
-       if (client->proxy == NULL) {
-               struct lmtp_proxy_settings proxy_set;
-
-               i_zero(&proxy_set);
-               proxy_set.my_hostname = client->my_domain;
-               proxy_set.dns_client_socket_path = dns_client_socket_path;
-               proxy_set.session_id = client->state.session_id;
-               proxy_set.source_ip = client->remote_ip;
-               proxy_set.source_port = client->remote_port;
-               proxy_set.proxy_ttl = client->proxy_ttl-1;
-
-               client->proxy = lmtp_proxy_init(&proxy_set, client->output);
-               lmtp_proxy_mail_from(client->proxy, client->state.mail_from,
-                       &client->state.mail_params);
-       }
-       if (lmtp_proxy_add_rcpt(client->proxy, address, &set) < 0)
-               client_send_line(client, "451 4.4.0 Remote server not answering");
-       else
-               client_send_line(client, "250 2.1.5 OK");
-       pool_unref(&pool);
-       return TRUE;
-}
-
 int cmd_rcpt(struct client *client, const char *args)
 {
        struct mail_recipient *rcpt;
index 95cb868d461d52730be10731436aef9c2593a371..63667919f2405d6ee72cd00cbb15de350f6c8879 100644 (file)
 #include "smtp-client.h"
 #include "smtp-client-connection.h"
 #include "smtp-client-transaction.h"
+#include "auth-master.h"
+#include "master-service.h"
+#include "mail-storage-service.h"
+#include "client.h"
+#include "main.h"
 #include "lmtp-proxy.h"
 
 #define LMTP_MAX_LINE_LEN 1024
+#define LMTP_PROXY_DEFAULT_TIMEOUT_MSECS (1000*125)
+
+#define ERRSTR_TEMP_USERDB_FAIL_PREFIX "451 4.3.0 <%s> "
+#define ERRSTR_TEMP_USERDB_FAIL \
+       ERRSTR_TEMP_USERDB_FAIL_PREFIX "Temporary user lookup failure"
 
 struct lmtp_proxy_recipient {
        struct lmtp_proxy_connection *conn;
@@ -380,6 +390,211 @@ lmtp_proxy_data_dummy_cb(const struct smtp_reply *proxy_reply ATTR_UNUSED,
        /* nothing */
 }
 
+static bool
+client_proxy_rcpt_parse_fields(struct lmtp_proxy_rcpt_settings *set,
+                              const char *const *args, const char **address)
+{
+       const char *p, *key, *value;
+       bool proxying = FALSE, port_set = FALSE;
+
+       for (; *args != NULL; args++) {
+               p = strchr(*args, '=');
+               if (p == NULL) {
+                       key = *args;
+                       value = "";
+               } else {
+                       key = t_strdup_until(*args, p);
+                       value = p + 1;
+               }
+
+               if (strcmp(key, "proxy") == 0)
+                       proxying = TRUE;
+               else if (strcmp(key, "host") == 0)
+                       set->host = value;
+               else if (strcmp(key, "hostip") == 0) {
+                       if (net_addr2ip(value, &set->hostip) < 0) {
+                               i_error("proxy: Invalid hostip %s", value);
+                               return FALSE;
+                       }
+               } else if (strcmp(key, "port") == 0) {
+                       if (net_str2port(value, &set->port) < 0) {
+                               i_error("proxy: Invalid port number %s", value);
+                               return FALSE;
+                       }
+                       port_set = TRUE;
+               } else if (strcmp(key, "proxy_timeout") == 0) {
+                       if (str_to_uint(value, &set->timeout_msecs) < 0) {
+                               i_error("proxy: Invalid proxy_timeout value %s", value);
+                               return FALSE;
+                       }
+                       set->timeout_msecs *= 1000;
+               } else if (strcmp(key, "protocol") == 0) {
+                       if (strcmp(value, "lmtp") == 0) {
+                               set->protocol = SMTP_PROTOCOL_LMTP;
+                               if (!port_set)
+                                       set->port = 24;
+                       } else if (strcmp(value, "smtp") == 0) {
+                               set->protocol = SMTP_PROTOCOL_SMTP;
+                               if (!port_set)
+                                       set->port = 25;
+                       } else {
+                               i_error("proxy: Unknown protocol %s", value);
+                               return FALSE;
+                       }
+               } else if (strcmp(key, "user") == 0 ||
+                          strcmp(key, "destuser") == 0) {
+                       /* changing the username */
+                       *address = value;
+               } else {
+                       /* just ignore it */
+               }
+       }
+       if (proxying && set->host == NULL) {
+               i_error("proxy: host not given");
+               return FALSE;
+       }
+       return proxying;
+}
+
+static bool
+client_proxy_is_ourself(const struct client *client,
+                       const struct lmtp_proxy_rcpt_settings *set)
+{
+       struct ip_addr ip;
+
+       if (set->port != client->local_port)
+               return FALSE;
+
+       if (set->hostip.family != 0)
+               ip = set->hostip;
+       else {
+               if (net_addr2ip(set->host, &ip) < 0)
+                       return FALSE;
+       }
+       if (!net_ip_compare(&ip, &client->local_ip))
+               return FALSE;
+       return TRUE;
+}
+
+bool client_proxy_rcpt(struct client *client,
+                      struct smtp_address *address,
+                      const char *username, const char *detail, char delim,
+                      struct smtp_params_rcpt *params)
+{
+       struct auth_master_connection *auth_conn;
+       struct lmtp_proxy_rcpt_settings set;
+       struct auth_user_info info;
+       struct mail_storage_service_input input;
+       const char *const *fields, *errstr, *orig_username = username;
+       struct smtp_address *user;
+       pool_t pool;
+       int ret;
+
+       i_zero(&input);
+       input.module = input.service = "lmtp";
+       mail_storage_service_init_settings(storage_service, &input);
+
+       i_zero(&info);
+       info.service = master_service_get_name(master_service);
+       info.local_ip = client->local_ip;
+       info.remote_ip = client->remote_ip;
+       info.local_port = client->local_port;
+       info.remote_port = client->remote_port;
+
+       pool = pool_alloconly_create("auth lookup", 1024);
+       auth_conn = mail_storage_service_get_auth_conn(storage_service);
+       ret = auth_master_pass_lookup(auth_conn, username, &info,
+                                     pool, &fields);
+       if (ret <= 0) {
+               errstr = ret < 0 && fields[0] != NULL ? t_strdup(fields[0]) :
+                       t_strdup_printf(ERRSTR_TEMP_USERDB_FAIL,
+                               smtp_address_encode(address));
+               pool_unref(&pool);
+               if (ret < 0) {
+                       client_send_line(client, "%s", errstr);
+                       return TRUE;
+               } else {
+                       /* user not found from passdb. try userdb also. */
+                       return FALSE;
+               }
+       }
+
+       i_zero(&set);
+       set.port = client->local_port;
+       set.protocol = SMTP_PROTOCOL_LMTP;
+       set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
+       set.params = *params;
+
+       if (!client_proxy_rcpt_parse_fields(&set, fields, &username)) {
+               /* not proxying this user */
+               pool_unref(&pool);
+               return FALSE;
+       }
+       if (strcmp(username, orig_username) != 0) {
+               if (smtp_address_parse_username(pool_datastack_create(),
+                                               username, &user, &errstr) < 0) {
+                       i_error("%s: Username `%s' returned by passdb lookup is not a valid SMTP address",
+                               orig_username, username);
+                       client_send_line(client, "550 5.3.5 <%s> "
+                               "Internal user lookup failure",
+                               smtp_address_encode(address));
+                       pool_unref(&pool);
+                       return FALSE;
+               }
+               /* username changed. change the address as well */
+               if (*detail == '\0') {
+                       address = user;
+               } else {
+                       address = smtp_address_add_detail_temp(user, detail, delim);
+               }
+       } else if (client_proxy_is_ourself(client, &set)) {
+               i_error("Proxying to <%s> loops to itself", username);
+               client_send_line(client, "554 5.4.6 <%s> "
+                                "Proxying loops to itself",
+                                smtp_address_encode(address));
+               pool_unref(&pool);
+               return TRUE;
+       }
+
+       if (client->proxy_ttl <= 1) {
+               i_error("Proxying to <%s> appears to be looping (TTL=0)",
+                       username);
+               client_send_line(client, "554 5.4.6 <%s> "
+                                "Proxying appears to be looping (TTL=0)",
+                                username);
+               pool_unref(&pool);
+               return TRUE;
+       }
+       if (array_count(&client->state.rcpt_to) != 0) {
+               client_send_line(client, "451 4.3.0 <%s> "
+                       "Can't handle mixed proxy/non-proxy destinations",
+                       smtp_address_encode(address));
+               pool_unref(&pool);
+               return TRUE;
+       }
+       if (client->proxy == NULL) {
+               struct lmtp_proxy_settings proxy_set;
+
+               i_zero(&proxy_set);
+               proxy_set.my_hostname = client->my_domain;
+               proxy_set.dns_client_socket_path = dns_client_socket_path;
+               proxy_set.session_id = client->state.session_id;
+               proxy_set.source_ip = client->remote_ip;
+               proxy_set.source_port = client->remote_port;
+               proxy_set.proxy_ttl = client->proxy_ttl-1;
+
+               client->proxy = lmtp_proxy_init(&proxy_set, client->output);
+               lmtp_proxy_mail_from(client->proxy, client->state.mail_from,
+                       &client->state.mail_params);
+       }
+       if (lmtp_proxy_add_rcpt(client->proxy, address, &set) < 0)
+               client_send_line(client, "451 4.4.0 Remote server not answering");
+       else
+               client_send_line(client, "250 2.1.5 OK");
+       pool_unref(&pool);
+       return TRUE;
+}
+
 void lmtp_proxy_start(struct lmtp_proxy *proxy, struct istream *data_input,
                      lmtp_proxy_finish_callback_t *callback, void *context)
 {
index 05c7a0515976acc4847a96035ffe55159bac0e3c..f10e73bb500cb237c4816bd7439213c0fca592bd 100644 (file)
@@ -8,6 +8,9 @@
 
 #define LMTP_PROXY_DEFAULT_TTL 5
 
+struct smtp_address;
+struct client;
+
 struct lmtp_proxy_settings {
        const char *my_hostname;
        const char *dns_client_socket_path;
@@ -44,9 +47,16 @@ void lmtp_proxy_mail_from(struct lmtp_proxy *proxy,
 int lmtp_proxy_add_rcpt(struct lmtp_proxy *proxy,
                        const struct smtp_address *address,
                        const struct lmtp_proxy_rcpt_settings *set);
+
+bool client_proxy_rcpt(struct client *client,
+                      struct smtp_address *address,
+                      const char *username, const char *detail, char delim,
+                      struct smtp_params_rcpt *params);
+
 /* Start proxying */
 void lmtp_proxy_start(struct lmtp_proxy *proxy, struct istream *data_input,
                      lmtp_proxy_finish_callback_t *callback, void *context)
        ATTR_NULL(3);
 
+
 #endif