dovecot-2.0: login: Proxying supports now doing DNS lookups for ...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Jan 31 19:11:27 EET 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/23956a9b915b
changeset: 10616:23956a9b915b
user: Timo Sirainen <tss at iki.fi>
date: Sun Jan 31 19:11:21 2010 +0200
description:
login: Proxying supports now doing DNS lookups for host names.
diffstat:
4 files changed, 93 insertions(+), 51 deletions(-)
src/login-common/Makefile.am | 1
src/login-common/client-common-auth.c | 5 -
src/login-common/login-proxy.c | 135 +++++++++++++++++++++------------
src/login-common/login-proxy.h | 3
diffs (257 lines):
diff -r 8f9fc7fa7c73 -r 23956a9b915b src/login-common/Makefile.am
--- a/src/login-common/Makefile.am Sun Jan 31 19:10:38 2010 +0200
+++ b/src/login-common/Makefile.am Sun Jan 31 19:11:21 2010 +0200
@@ -4,6 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-dns \
-I$(top_srcdir)/src/lib-master \
-DPKG_STATEDIR=\""$(statedir)"\"
diff -r 8f9fc7fa7c73 -r 23956a9b915b src/login-common/client-common-auth.c
--- a/src/login-common/client-common-auth.c Sun Jan 31 19:10:38 2010 +0200
+++ b/src/login-common/client-common-auth.c Sun Jan 31 19:11:21 2010 +0200
@@ -12,6 +12,7 @@
#include <stdlib.h>
#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
+#define LOGIN_DNS_CLIENT_SOCKET_PATH "dns-client"
/* If we've been waiting auth server to respond for over this many milliseconds,
send a "waiting" message. */
@@ -255,11 +256,11 @@ static int proxy_start(struct client *cl
memset(&proxy_set, 0, sizeof(proxy_set));
proxy_set.host = reply->host;
proxy_set.port = reply->port;
+ proxy_set.dns_client_socket_path = LOGIN_DNS_CLIENT_SOCKET_PATH;
proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
proxy_set.ssl_flags = reply->ssl_flags;
- if (login_proxy_new(client, &proxy_set, proxy_input,
- &client->login_proxy) < 0) {
+ if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
PROXY_FAILURE_MSG);
return -1;
diff -r 8f9fc7fa7c73 -r 23956a9b915b src/login-common/login-proxy.c
--- a/src/login-common/login-proxy.c Sun Jan 31 19:10:38 2010 +0200
+++ b/src/login-common/login-proxy.c Sun Jan 31 19:11:21 2010 +0200
@@ -8,6 +8,7 @@
#include "str-sanitize.h"
#include "time-util.h"
#include "master-service.h"
+#include "dns-lookup.h"
#include "client-common.h"
#include "ssl-proxy.h"
#include "login-proxy-state.h"
@@ -16,6 +17,7 @@
#define MAX_PROXY_INPUT_SIZE 4096
#define OUTBUF_THRESHOLD 1024
#define LOGIN_PROXY_DIE_IDLE_SECS 2
+#define LOGIN_PROXY_DNS_WARN_MSECS 500
struct login_proxy {
struct login_proxy *prev, *next;
@@ -32,8 +34,10 @@ struct login_proxy {
struct timeout *to;
struct login_proxy_record *state_rec;
- char *host, *user;
+ struct ip_addr ip;
+ char *host;
unsigned int port;
+ unsigned int connect_timeout_msecs;
enum login_proxy_ssl_flags ssl_flags;
proxy_callback_t *callback;
@@ -189,63 +193,97 @@ static void proxy_connect_timeout(struct
login_proxy_free(&proxy);
}
-int login_proxy_new(struct client *client,
- const struct login_proxy_settings *set,
- proxy_callback_t *callback, struct login_proxy **proxy_r)
-{
- struct login_proxy *proxy;
+static int login_proxy_connect(struct login_proxy *proxy)
+{
struct login_proxy_record *rec;
- struct ip_addr ip;
- int fd;
-
- if (set->host == NULL) {
- i_error("proxy(%s): host not given", client->virtual_user);
- return -1;
- }
-
- if (net_addr2ip(set->host, &ip) < 0) {
- i_error("proxy(%s): %s is not a valid IP",
- client->virtual_user, set->host);
- return -1;
- }
-
- rec = login_proxy_state_get(proxy_state, &ip, set->port);
+
+ rec = login_proxy_state_get(proxy_state, &proxy->ip, proxy->port);
if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 &&
rec->num_waiting_connections != 0) {
/* the server is down. fail immediately */
- return -1;
- }
-
- fd = net_connect_ip(&ip, set->port, NULL);
- if (fd < 0) {
+ login_proxy_free(&proxy);
+ return -1;
+ }
+
+ proxy->server_fd = net_connect_ip(&proxy->ip, proxy->port, NULL);
+ if (proxy->server_fd == -1) {
i_error("proxy(%s): connect(%s, %u) failed: %m",
- client->virtual_user, set->host, set->port);
+ proxy->client->virtual_user, proxy->host, proxy->port);
+ login_proxy_free(&proxy);
return -1;
}
+ proxy->server_io = io_add(proxy->server_fd, IO_WRITE,
+ proxy_wait_connect, proxy);
+ if (proxy->connect_timeout_msecs != 0) {
+ proxy->to = timeout_add(proxy->connect_timeout_msecs,
+ proxy_connect_timeout, proxy);
+ }
+
+ proxy->state_rec = rec;
+ proxy->state_rec->num_waiting_connections++;
+ return 0;
+}
+
+static void login_proxy_dns_done(const struct dns_lookup_result *result,
+ struct login_proxy *proxy)
+{
+ if (result->ret != 0) {
+ i_error("proxy(%s): DNS lookup of %s failed: %s",
+ proxy->client->virtual_user, proxy->host,
+ result->error);
+ login_proxy_free(&proxy);
+ } else {
+ if (result->msecs > LOGIN_PROXY_DNS_WARN_MSECS) {
+ i_warning("proxy(%s): DNS lookup for %s took %u.%03u s",
+ proxy->client->virtual_user, proxy->host,
+ result->msecs/1000, result->msecs % 1000);
+ }
+
+ proxy->ip = result->ips[0];
+ (void)login_proxy_connect(proxy);
+ }
+}
+
+int login_proxy_new(struct client *client,
+ const struct login_proxy_settings *set,
+ proxy_callback_t *callback)
+{
+ struct login_proxy *proxy;
+ struct dns_lookup_settings dns_lookup_set;
+
+ i_assert(client->login_proxy == NULL);
+
+ if (set->host == NULL || *set->host == '\0') {
+ i_error("proxy(%s): host not given", client->virtual_user);
+ return -1;
+ }
proxy = i_new(struct login_proxy, 1);
+ proxy->client = client;
+ proxy->client_fd = -1;
+ proxy->server_fd = -1;
proxy->created = ioloop_timeval;
proxy->host = i_strdup(set->host);
- proxy->user = i_strdup(client->virtual_user);
proxy->port = set->port;
+ proxy->connect_timeout_msecs = set->connect_timeout_msecs;
proxy->ssl_flags = set->ssl_flags;
- proxy->client = client;
client_ref(client);
- proxy->server_fd = fd;
- proxy->server_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy);
- if (set->connect_timeout_msecs != 0) {
- proxy->to = timeout_add(set->connect_timeout_msecs,
- proxy_connect_timeout, proxy);
- }
+ memset(&dns_lookup_set, 0, sizeof(dns_lookup_set));
+ dns_lookup_set.dns_client_socket_path = set->dns_client_socket_path;
+ dns_lookup_set.timeout_msecs = set->connect_timeout_msecs;
+
+ if (net_addr2ip(set->host, &proxy->ip) < 0) {
+ if (dns_lookup(set->host, &dns_lookup_set,
+ login_proxy_dns_done, proxy) < 0)
+ return -1;
+ } else {
+ if (login_proxy_connect(proxy) < 0)
+ return -1;
+ }
+
proxy->callback = callback;
-
- proxy->client_fd = -1;
-
- proxy->state_rec = rec;
- rec->num_waiting_connections++;
-
- *proxy_r = proxy;
+ client->login_proxy = proxy;
return 0;
}
@@ -282,7 +320,7 @@ void login_proxy_free(struct login_proxy
ipstr = net_ip2addr(&proxy->client->ip);
i_info("proxy(%s): disconnecting %s",
- str_sanitize(proxy->user, 80),
+ proxy->client->virtual_user,
ipstr != NULL ? ipstr : "");
if (proxy->client_io != NULL)
@@ -294,15 +332,16 @@ void login_proxy_free(struct login_proxy
i_assert(proxy->client_io == NULL);
i_assert(proxy->client_output == NULL);
- proxy->callback(proxy->client);
- }
-
- net_disconnect(proxy->server_fd);
+ if (proxy->callback != NULL)
+ proxy->callback(proxy->client);
+ }
+
+ if (proxy->server_fd != -1)
+ net_disconnect(proxy->server_fd);
if (proxy->ssl_server_proxy != NULL)
ssl_proxy_free(&proxy->ssl_server_proxy);
i_free(proxy->host);
- i_free(proxy->user);
i_free(proxy);
client->login_proxy = NULL;
diff -r 8f9fc7fa7c73 -r 23956a9b915b src/login-common/login-proxy.h
--- a/src/login-common/login-proxy.h Sun Jan 31 19:10:38 2010 +0200
+++ b/src/login-common/login-proxy.h Sun Jan 31 19:11:21 2010 +0200
@@ -15,6 +15,7 @@ enum login_proxy_ssl_flags {
struct login_proxy_settings {
const char *host;
+ const char *dns_client_socket_path;
unsigned int port;
unsigned int connect_timeout_msecs;
enum login_proxy_ssl_flags ssl_flags;
@@ -27,7 +28,7 @@ typedef void proxy_callback_t(struct cli
called when new input is available from proxy. */
int login_proxy_new(struct client *client,
const struct login_proxy_settings *set,
- proxy_callback_t *callback, struct login_proxy **proxy_r);
+ proxy_callback_t *callback);
/* Free the proxy. This should be called if authentication fails. */
void login_proxy_free(struct login_proxy **proxy);
More information about the dovecot-cvs
mailing list