# Greeting message for clients.
#login_greeting = Dovecot ready.
+# Space separated list of trusted network ranges. Connections from these
+# IPs are allowed to override their IP addresses and ports (for logging and
+# for authentication checks). disable_plaintext_auth is also ignored for
+# these networks. Typically you'd specify your IMAP proxy servers here.
+#login_trusted_networks =
+
# Space-separated list of elements we want to log. The elements which have
# a non-empty variable value are joined together to form a comma-separated
# string.
return 1;
}
+static void
+client_update_info(struct imap_client *client, const struct imap_arg *args)
+{
+ const char *key, *value;
+
+ if (args->type != IMAP_ARG_LIST)
+ return;
+ args = IMAP_ARG_LIST_ARGS(args);
+
+ while (args->type == IMAP_ARG_STRING &&
+ args[1].type == IMAP_ARG_STRING) {
+ key = IMAP_ARG_STR_NONULL(&args[0]);
+ value = IMAP_ARG_STR_NONULL(&args[1]);
+ if (strcasecmp(key, "x-originating-ip") == 0)
+ (void)net_addr2ip(value, &client->common.ip);
+ else if (strcasecmp(key, "x-originating-port") == 0)
+ client->common.remote_port = atoi(value);
+ else if (strcasecmp(key, "x-local-ip") == 0)
+ (void)net_addr2ip(value, &client->common.local_ip);
+ else if (strcasecmp(key, "x-local-port") == 0)
+ client->common.local_port = atoi(value);
+ args += 2;
+ }
+}
+
static int cmd_id(struct imap_client *client, const struct imap_arg *args)
{
const char *env, *value;
if (!client->id_logged) {
client->id_logged = TRUE;
+ if (client->common.trusted)
+ client_update_info(client, args);
+
env = getenv("IMAP_ID_LOG");
value = imap_id_args_get_log_reply(args, env);
if (value != NULL) {
client = i_new(struct imap_client, 1);
client->created = ioloop_time;
client->refcount = 1;
- client->common.tls = ssl;
- client->common.secured = ssl || net_ip_compare(ip, local_ip);
client->common.local_ip = *local_ip;
client->common.ip = *ip;
client->common.fd = fd;
+ client->common.tls = ssl;
+ client->common.trusted = client_is_trusted(&client->common);
+ client->common.secured = ssl || client->common.trusted ||
+ net_ip_compare(ip, local_ip);
client_open_streams(client, fd);
client->io = io_add(fd, IO_READ, client_input, client);
#include "imap-quote.h"
#include "imap-proxy.h"
+static bool imap_banner_has_capability(const char *line, const char *capability)
+{
+ unsigned int capability_len = strlen(capability);
+
+ if (strncmp(line, "[CAPABILITY ", 12) != 0)
+ return FALSE;
+
+ line += 12;
+ while (strncmp(line, capability, capability_len) != 0 ||
+ (line[capability_len] != ' ' &&
+ line[capability_len] != '\0')) {
+ /* skip over the capability */
+ while (*line != ' ') {
+ if (*line == '\0')
+ return FALSE;
+ line++;
+ }
+ line++;
+ }
+ return TRUE;
+}
+
+static void proxy_write_id(struct imap_client *client, string_t *str)
+{
+ str_printfa(str, "I ID ("
+ "\"x-originating-ip\" \"%s\" "
+ "\"x-originating-port\" \"%u\" "
+ "\"x-local-ip\" \"%s\" "
+ "\"x-local-port\" \"%u\")\r\n",
+ net_ip2addr(&client->common.ip),
+ client->common.remote_port,
+ net_ip2addr(&client->common.local_ip),
+ client->common.local_port);
+}
+
static int proxy_input_line(struct imap_client *client,
struct ostream *output, const char *line)
{
return -1;
}
- /* send LOGIN command */
str = t_str_new(128);
+ if (imap_banner_has_capability(line + 5, "ID"))
+ proxy_write_id(client, str);
+
+ /* send LOGIN command */
str_append(str, "P LOGIN ");
imap_quote_append_string(str, client->proxy_user, FALSE);
str_append_c(str, ' ');
client_syslog_real(client, msg);
} T_END;
}
+
+bool client_is_trusted(struct client *client)
+{
+ const char *const *net;
+ struct ip_addr net_ip;
+ unsigned int bits;
+
+ if (trusted_networks == NULL)
+ return FALSE;
+
+ net = t_strsplit_spaces(trusted_networks, ", ");
+ for (; *net != NULL; net++) {
+ if (net_parse_range(*net, &net_ip, &bits) < 0) {
+ i_error("login_trusted_networks: "
+ "Invalid network '%s'", *net);
+ break;
+ }
+
+ if (net_is_in_network(&client->ip, &net_ip, bits))
+ return TRUE;
+ }
+ return FALSE;
+}
char *virtual_user;
unsigned int tls:1;
unsigned int secured:1;
+ unsigned int trusted:1;
unsigned int authenticating:1;
unsigned int auth_tried_disabled_plaintext:1;
/* ... */
unsigned int clients_get_count(void) ATTR_PURE;
void client_syslog(struct client *client, const char *msg);
+bool client_is_trusted(struct client *client);
void clients_notify_auth_connected(void);
void client_destroy_oldest(void);
extern const char *greeting, *log_format;
extern const char *const *log_format_elements;
extern const char *capability_string;
+extern const char *trusted_networks;
extern unsigned int max_connections;
extern unsigned int login_process_uid;
extern struct auth_client *auth_client;
bool verbose_proctitle, verbose_ssl, verbose_auth;
const char *greeting, *log_format;
const char *const *log_format_elements;
+const char *trusted_networks;
unsigned int max_connections;
unsigned int login_process_uid;
struct auth_client *auth_client;
if (log_format == NULL)
log_format = "%$: %s";
+ trusted_networks = getenv("TRUSTED_NETWORKS");
+
value = getenv("PROCESS_UID");
if (value == NULL)
i_fatal("BUG: PROCESS_UID environment not given");
set->imap_capability :
set->imap_generated_capability, NULL));
}
+ if (*set->login_trusted_networks != '\0') {
+ env_put(t_strconcat("TRUSTED_NETWORKS=",
+ set->login_trusted_networks, NULL));
+ }
}
static pid_t create_login_process(struct login_group *group)
DEF_BOOL(login_process_per_connection),
DEF_BOOL(login_chroot),
DEF_BOOL(login_greeting_capability),
+ DEF_STR(login_trusted_networks),
DEF_INT(login_process_size),
DEF_INT(login_processes_count),
MEMBER(login_process_per_connection) TRUE,
MEMBER(login_chroot) TRUE,
MEMBER(login_greeting_capability) FALSE,
+ MEMBER(login_trusted_networks) "",
MEMBER(login_process_size) 64,
MEMBER(login_processes_count) 3,
bool login_process_per_connection;
bool login_chroot;
bool login_greeting_capability;
+ const char *login_trusted_networks;
unsigned int login_process_size;
unsigned int login_processes_count;
client = i_new(struct pop3_client, 1);
client->created = ioloop_time;
client->refcount = 1;
- client->common.tls = ssl;
- client->common.secured = ssl || net_ip_compare(ip, local_ip);
client->common.local_ip = *local_ip;
client->common.ip = *ip;
client->common.fd = fd;
+ client->common.tls = ssl;
+ client->common.trusted = client_is_trusted(&client->common);
+ client->common.secured = ssl || client->common.trusted ||
+ net_ip_compare(ip, local_ip);
+
client_open_streams(client, fd);
client_link(&client->common);