#include "smtp-client.h"
#include "smtp-client-connection.h"
#include "smtp-client-transaction.h"
+#include "auth-proxy.h"
#include "auth-master.h"
#include "master-service-ssl-settings.h"
#include "mail-storage-service.h"
#define LMTP_MAX_REPLY_SIZE 4096
#define LMTP_PROXY_DEFAULT_TIMEOUT_MSECS (1000*125)
-enum lmtp_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
-};
-
struct lmtp_proxy_redirect {
struct ip_addr ip;
in_port_t port;
};
struct lmtp_proxy_rcpt_settings {
+ struct auth_proxy_settings set;
enum smtp_protocol protocol;
- const char *host;
- struct ip_addr hostip, source_ip;
- in_port_t port;
- enum lmtp_proxy_ssl_flags ssl_flags;
- unsigned int timeout_msecs;
struct smtp_params_rcpt params;
-
- bool proxy_not_trusted:1;
};
struct lmtp_proxy_recipient {
*ssl_mode_r = SMTP_CLIENT_SSL_MODE_NONE;
- if ((conn->set.ssl_flags & PROXY_SSL_FLAG_YES) == 0) {
+ if ((conn->set.set.ssl_flags & AUTH_PROXY_SSL_FLAG_YES) == 0) {
i_zero(ssl_set_r);
return;
}
master_ssl_set = master_service_ssl_settings_get(master_service);
master_service_ssl_client_settings_to_iostream_set(
master_ssl_set, pool_datastack_create(), ssl_set_r);
- if ((conn->set.ssl_flags & PROXY_SSL_FLAG_ANY_CERT) != 0)
+ if ((conn->set.set.ssl_flags & AUTH_PROXY_SSL_FLAG_ANY_CERT) != 0)
ssl_set_r->allow_invalid_cert = TRUE;
- if ((conn->set.ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0)
+ if ((conn->set.set.ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0)
*ssl_mode_r = SMTP_CLIENT_SSL_MODE_IMMEDIATE;
else
*ssl_mode_r = SMTP_CLIENT_SSL_MODE_STARTTLS;
enum smtp_client_connection_ssl_mode ssl_mode;
struct ssl_iostream_settings ssl_set;
- i_assert(set->timeout_msecs > 0);
+ i_assert(set->set.timeout_msecs > 0);
array_foreach_elem(&proxy->connections, conn) {
if (conn->set.protocol == set->protocol &&
- conn->set.port == set->port &&
- strcmp(conn->set.host, set->host) == 0 &&
- (set->hostip.family == 0 ||
- net_ip_compare(&conn->set.hostip, &set->hostip)) &&
- net_ip_compare(&conn->set.source_ip, &set->source_ip) &&
- conn->set.ssl_flags == set->ssl_flags)
+ conn->set.set.port == set->set.port &&
+ strcmp(conn->set.set.host, set->set.host) == 0 &&
+ (set->set.host_ip.family == 0 ||
+ net_ip_compare(&conn->set.set.host_ip, &set->set.host_ip)) &&
+ net_ip_compare(&conn->set.set.source_ip, &set->set.source_ip) &&
+ conn->set.set.ssl_flags == set->set.ssl_flags)
return conn;
}
conn = i_new(struct lmtp_proxy_connection, 1);
conn->proxy = proxy;
conn->set.protocol = set->protocol;
- conn->set.hostip = set->hostip;
- conn->host = i_strdup(set->host);
- conn->set.host = conn->host;
- conn->set.source_ip = set->source_ip;
- conn->set.port = set->port;
- conn->set.ssl_flags = set->ssl_flags;
- conn->set.timeout_msecs = set->timeout_msecs;
+ conn->set.set.host_ip = set->set.host_ip;
+ conn->host = i_strdup(set->set.host);
+ conn->set.set.host = conn->host;
+ conn->set.set.source_ip = set->set.source_ip;
+ conn->set.set.port = set->set.port;
+ conn->set.set.ssl_flags = set->set.ssl_flags;
+ conn->set.set.timeout_msecs = set->set.timeout_msecs;
array_push_back(&proxy->connections, &conn);
lmtp_proxy_connection_init_ssl(conn, &ssl_set, &ssl_mode);
i_zero(&lmtp_set);
- lmtp_set.my_ip = conn->set.source_ip;
+ lmtp_set.my_ip = conn->set.set.source_ip;
lmtp_set.ssl = &ssl_set;
- lmtp_set.peer_trusted = !conn->set.proxy_not_trusted;
+ lmtp_set.peer_trusted = !conn->set.set.remote_not_trusted;
lmtp_set.forced_capabilities = SMTP_CAPABILITY__ORCPT;
lmtp_set.mail_send_broken_path = TRUE;
lmtp_set.verbose_user_errors = client->lmtp_set->lmtp_verbose_replies;
- if (conn->set.hostip.family != 0) {
+ if (conn->set.set.host_ip.family != 0) {
conn->lmtp_conn = smtp_client_connection_create_ip(
proxy->lmtp_client, set->protocol,
- &conn->set.hostip, conn->set.port,
- conn->set.host, ssl_mode, &lmtp_set);
+ &conn->set.set.host_ip, conn->set.set.port,
+ conn->set.set.host, ssl_mode, &lmtp_set);
} else {
conn->lmtp_conn = smtp_client_connection_create(
proxy->lmtp_client, set->protocol,
- conn->set.host, conn->set.port,
+ conn->set.set.host, conn->set.set.port,
ssl_mode, &lmtp_set);
}
smtp_client_connection_accept_extra_capability(conn->lmtp_conn,
smtp_client_transaction_start(conn->lmtp_trans,
lmtp_proxy_mail_cb, conn);
- if (proxy->max_timeout_msecs < set->timeout_msecs)
- proxy->max_timeout_msecs = set->timeout_msecs;
+ if (proxy->max_timeout_msecs < set->set.timeout_msecs)
+ proxy->max_timeout_msecs = set->set.timeout_msecs;
return conn;
}
const char *const *args, const char **address)
{
struct smtp_server_recipient *rcpt = lprcpt->rcpt->rcpt;
- const char *p, *key, *value;
- bool proxying = FALSE, port_set = FALSE;
+ const char *p, *key, *value, *error;
+ in_port_t orig_port = set->set.port;
+ int ret;
+
+ set->set.proxy = FALSE;
+ set->set.port = 0;
for (; *args != NULL; args++) {
p = strchr(*args, '=');
value = p + 1;
}
+ ret = auth_proxy_settings_parse(&set->set, NULL,
+ key, value, &error);
+ if (ret < 0) {
+ e_error(rcpt->event, "proxy: Invalid %s value '%s': %s",
+ key, value, error);
+ return -1;
+ }
+ if (ret > 0)
+ continue;
+
if (strcmp(key, "nologin") == 0)
lprcpt->nologin = TRUE;
- else 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) {
- e_error(rcpt->event,
- "proxy: Invalid hostip %s", value);
- return -1;
- }
- } else if (strcmp(key, "source_ip") == 0) {
- if (net_addr2ip(value, &set->source_ip) < 0) {
- e_error(rcpt->event,
- "proxy: Invalid source_ip %s", value);
- return -1;
- }
- } else if (strcmp(key, "port") == 0) {
- if (net_str2port(value, &set->port) < 0) {
- e_error(rcpt->event,
- "proxy: Invalid port number %s", value);
- return -1;
- }
- port_set = TRUE;
- } else if (strcmp(key, "proxy_timeout") == 0) {
- if (str_to_uint(value, &set->timeout_msecs) < 0) {
- e_error(rcpt->event,"proxy: "
- "Invalid proxy_timeout value %s", value);
- return -1;
- }
- set->timeout_msecs *= 1000;
- } else if (strcmp(key, "proxy_not_trusted") == 0) {
- set->proxy_not_trusted = TRUE;
- } else if (strcmp(key, "proxy_redirect_reauth") == 0) {
- lprcpt->proxy_redirect_reauth = TRUE;
- } else if (strcmp(key, "protocol") == 0) {
+ else if (strcmp(key, "protocol") == 0) {
if (strcmp(value, "lmtp") == 0) {
set->protocol = SMTP_PROTOCOL_LMTP;
- if (!port_set)
- set->port = 24;
+ if (set->set.port == 0)
+ set->set.port = 24;
} else if (strcmp(value, "smtp") == 0) {
set->protocol = SMTP_PROTOCOL_SMTP;
- if (!port_set)
- set->port = 25;
+ if (set->set.port == 0)
+ set->set.port = 25;
} else {
e_error(rcpt->event,
"proxy: Unknown protocol %s", value);
return -1;
}
- } else if (strcmp(key, "ssl") == 0) {
- set->ssl_flags |= PROXY_SSL_FLAG_YES;
- if (strcmp(value, "any-cert") == 0)
- set->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
- } else if (strcmp(key, "starttls") == 0) {
- set->ssl_flags |= PROXY_SSL_FLAG_YES |
- PROXY_SSL_FLAG_STARTTLS;
- if (strcmp(value, "any-cert") == 0)
- set->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
- } else if (strcmp(key, "user") == 0 ||
- strcmp(key, "destuser") == 0) {
+ } else if (strcmp(key, "user") == 0) {
/* Changing the username */
*address = value;
} else {
/* Just ignore it */
}
}
- if (proxying && set->host == NULL) {
+ if (set->set.username != NULL) {
+ /* "destuser" always overrides "user" */
+ *address = set->set.username;
+ }
+ if (set->set.port == 0)
+ set->set.port = orig_port;
+ if (!set->set.proxy)
+ return 0;
+
+ if (set->set.host == NULL) {
e_error(rcpt->event, "proxy: host not given");
return -1;
}
- return proxying ? 1 : 0;
+ if (set->set.redirect_reauth)
+ lprcpt->proxy_redirect_reauth = TRUE;
+ return 1;
}
static void
struct lmtp_proxy_connection *conn = lprcpt->conn;
const struct lmtp_proxy_redirect *redirect;
- i_assert(conn->set.hostip.family != 0);
+ i_assert(conn->set.set.host_ip.family != 0);
str_printfa(str, "%s:%u",
- net_ip2addr(&conn->set.hostip), conn->set.port);
+ net_ip2addr(&conn->set.set.host_ip), conn->set.set.port);
if (!array_is_created(&lprcpt->redirect_path))
return;
array_foreach(&lprcpt->redirect_path, redirect) {
const struct ip_addr *ip, in_port_t port)
{
struct lmtp_proxy_connection *conn = lprcpt->conn;
- const struct ip_addr *conn_ip = &conn->set.hostip;
- in_port_t conn_port = conn->set.port;
+ const struct ip_addr *conn_ip = &conn->set.set.host_ip;
+ in_port_t conn_port = conn->set.set.port;
const struct lmtp_proxy_redirect *redirect;
i_assert(ip->family != 0);
{
struct ip_addr ip;
- if (set->port != client->local_port)
+ if (set->set.port != client->local_port)
return FALSE;
- if (set->hostip.family != 0)
- ip = set->hostip;
+ if (set->set.host_ip.family != 0)
+ ip = set->set.host_ip;
else {
- if (net_addr2ip(set->host, &ip) < 0)
+ if (net_addr2ip(set->set.host, &ip) < 0)
return FALSE;
}
if (!net_ip_compare(&ip, &client->local_ip))
struct lmtp_recipient *lrcpt = lprcpt->rcpt;
struct client *client = lrcpt->client;
struct smtp_server_recipient *rcpt = lrcpt->rcpt;
- const struct ip_addr *ip = &set->hostip;
- in_port_t port = set->port;
+ const struct ip_addr *ip = &set->set.host_ip;
+ in_port_t port = set->set.port;
struct lmtp_proxy_redirect *redirect;
struct lmtp_proxy_connection *conn;
{
struct lmtp_recipient *lrcpt = lprcpt->rcpt;
struct smtp_server_recipient *rcpt = lrcpt->rcpt;
- const struct ip_addr *ip = &set->hostip;
- in_port_t port = set->port;
+ const struct ip_addr *ip = &set->set.host_ip;
+ in_port_t port = set->set.port;
struct auth_master_connection *auth_conn;
struct auth_user_info info;
const char *const *fields, *errstr, *username;
net_ip2addr(ip), port),
str_c(hosts_attempted),
t_strdup_printf("destuser=%s", str_tabescape(destuser)),
- t_strdup_printf("proxy_timeout=%u", lprcpt->conn->set.timeout_msecs),
+ t_strdup_printf("proxy_timeout=%u", lprcpt->conn->set.set.timeout_msecs),
};
t_array_init(&info.extra_fields, N_ELEMENTS(extra_fields));
array_append(&info.extra_fields, extra_fields,
}
set = conn->set;
- set.host = host;
- set.hostip = ip;
- set.port = port;
+ set.set.host = host;
+ set.set.host_ip = ip;
+ set.set.port = port;
if (lprcpt->proxy_redirect_reauth)
lmtp_proxy_rcpt_redirect_relookup(lprcpt, &set, destuser);
bool add_orcpt_param = FALSE, add_xrcptforward_param = FALSE;
pool_t param_pool;
- if (conn->set.hostip.family == 0) {
+ if (conn->set.set.host_ip.family == 0) {
smtp_client_connection_get_remote_ip(conn->lmtp_conn,
- &conn->set.hostip);
+ &conn->set.set.host_ip);
}
if (!lmtp_proxy_handle_reply(lprcpt, proxy_reply, &reply))
return 0;
}
- if (set->host == NULL) {
+ if (set->set.host == NULL) {
smtp_server_recipient_reply(rcpt, 550, "5.3.5",
"Login disabled");
return -1;
string_t *referral = t_str_new(128);
if (destuser != NULL)
str_printfa(referral, "%s@", destuser);
- str_printfa(referral, "%s:%u", set->host, set->port);
+ str_printfa(referral, "%s:%u", set->set.host, set->set.port);
smtp_server_recipient_reply(
rcpt, 550, LMTP_RCPT_PROXY_REDIRECT_ENH_CODE_STR,
"%s Referral", str_c(referral));
}
i_zero(&set);
- set.port = client->local_port;
+ set.set.port = client->local_port;
+ set.set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
set.protocol = SMTP_PROTOCOL_LMTP;
- set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
ret = lmtp_proxy_rcpt_parse_fields(lprcpt, &set, fields, &username);
if (ret < 0) {
str_append(msg, "Failed to send message to");
str_printfa(msg, " <%s> at %s:%u: %s (%u/%u at %u ms)",
smtp_address_encode(address),
- conn->set.host, conn->set.port,
+ conn->set.set.host, conn->set.set.port,
smtp_reply_log(proxy_reply),
rcpt_index + 1, array_count(&trans->rcpt_to),
timeval_diff_msecs(&ioloop_timeval, ×->started));