[dovecot-cvs] dovecot/src/login-common common.h, 1.5, 1.6 login-proxy.c, 1.1, 1.2 login-proxy.h, 1.1, 1.2

cras at dovecot.org cras at dovecot.org
Tue Oct 19 02:07:04 EEST 2004


Update of /var/lib/cvs/dovecot/src/login-common
In directory talvi:/tmp/cvs-serv14845/login-common

Modified Files:
	common.h login-proxy.c login-proxy.h 
Log Message:
More smart IMAP and POP3 proxies. Now if remote login fails, it just
destroys the proxy and allows trying another username which can go elsewhere.
Also now replies with the same old "Authentication failed" error message
instead of showing remote server's failure message.



Index: common.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/common.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- common.h	5 Oct 2004 16:00:18 -0000	1.5
+++ common.h	18 Oct 2004 23:07:01 -0000	1.6
@@ -3,6 +3,8 @@
 
 #include "lib.h"
 
+#define AUTH_FAILED_MSG "Authentication failed."
+
 extern int disable_plaintext_auth, process_per_connection, greeting_capability;
 extern int verbose_proctitle, verbose_ssl, verbose_auth;
 char *greeting;

Index: login-proxy.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/login-proxy.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- login-proxy.c	18 Oct 2004 19:21:47 -0000	1.1
+++ login-proxy.c	18 Oct 2004 23:07:01 -0000	1.2
@@ -4,29 +4,30 @@
 #include "ioloop.h"
 #include "istream.h"
 #include "ostream.h"
-#include "safe-memset.h"
 #include "hash.h"
 #include "client-common.h"
 #include "login-proxy.h"
 
-#define MAX_INBUF_SIZE 4096
+#define MAX_PROXY_INPUT_SIZE 4096
 #define OUTBUF_THRESHOLD 1024
 
 struct login_proxy {
-	struct client *client;
-
 	int client_fd, proxy_fd;
 	struct io *client_io, *proxy_io;
+	struct istream *proxy_input;
 	struct ostream *client_output, *proxy_output;
 
 	char *host, *user, *login_cmd;
 	unsigned int port;
+
+	proxy_callback_t *callback;
+	void *context;
+
+	unsigned int destroying:1;
 };
 
 static struct hash_table *login_proxies;
 
-static void login_proxy_free(struct login_proxy *proxy);
-
 static void proxy_input(void *context)
 {
 	struct login_proxy *proxy = context;
@@ -112,42 +113,9 @@
 static void proxy_prelogin_input(void *context)
 {
 	struct login_proxy *proxy = context;
-	unsigned char buf[1024];
-	ssize_t ret;
 
-	ret = net_receive(proxy->proxy_fd, buf, sizeof(buf));
-	if (ret < 0) {
-		/* disconnected */
-		login_proxy_free(proxy);
-		return;
-	}
-
-	/* we just want to eat away the first banner line. be dummy and don't
-	   check any errors, so we don't need any IMAP/POP3-specific things
-	   here (except for assuming the banner line..) */
-	if (buf[ret-1] != '\n')
-		return;
-
-	/* send LOGIN command */
-	(void)o_stream_send_str(proxy->proxy_output, proxy->login_cmd);
-
-	safe_memset(proxy->login_cmd, 0, strlen(proxy->login_cmd));
-	i_free(proxy->login_cmd);
-        proxy->login_cmd = NULL;
-
-	/* from now on, just do dummy proxying */
-	io_remove(proxy->proxy_io);
-	proxy->proxy_io = io_add(proxy->proxy_fd, IO_READ, proxy_input, proxy);
-	proxy->client_io = io_add(proxy->client_fd, IO_READ,
-				  proxy_client_input, proxy);
-
-	proxy->client_output =
-		o_stream_create_file(proxy->client_fd, default_pool,
-				     (size_t)-1, FALSE);
-
-	o_stream_set_flush_callback(proxy->client_output,
-				    proxy_client_output, proxy);
-	o_stream_set_flush_callback(proxy->proxy_output, proxy_output, proxy);
+	proxy->callback(proxy->proxy_input, proxy->proxy_output,
+			proxy->context);
 }
 
 static void proxy_wait_connect(void *context)
@@ -163,7 +131,10 @@
 		return;
 	}
 
-	/* initialize proxy's streams */
+	/* connect successful */
+	proxy->proxy_input =
+		i_stream_create_file(proxy->proxy_fd, default_pool,
+				     MAX_PROXY_INPUT_SIZE, FALSE);
 	proxy->proxy_output =
 		o_stream_create_file(proxy->proxy_fd, default_pool,
 				     (size_t)-1, FALSE);
@@ -173,8 +144,9 @@
 		io_add(proxy->proxy_fd, IO_READ, proxy_prelogin_input, proxy);
 }
 
-int login_proxy_new(struct client *client, const char *host,
-		    unsigned int port, const char *login_cmd)
+struct login_proxy *
+login_proxy_new(struct client *client, const char *host, unsigned int port,
+		proxy_callback_t *callback, void *context)
 {
 	struct login_proxy *proxy;
 	struct ip_addr ip;
@@ -182,74 +154,104 @@
 
 	if (host == NULL) {
 		i_error("proxy(%s): host not given", client->virtual_user);
-		return -1;
+		return NULL;
 	}
 
 	if (net_addr2ip(host, &ip) < 0) {
 		i_error("proxy(%s): %s is not a valid IP",
 			client->virtual_user, host);
-		return -1;
+		return NULL;
 	}
 
 	fd = net_connect_ip(&ip, port, NULL);
 	if (fd < 0) {
 		i_error("proxy(%s): connect(%s, %u) failed: %m",
 			client->virtual_user, host, port);
-		return -1;
+		return NULL;
 	}
 
 	proxy = i_new(struct login_proxy, 1);
 	proxy->host = i_strdup(host);
-	proxy->login_cmd = i_strdup(login_cmd);
 	proxy->port = port;
 
 	proxy->proxy_fd = fd;
 	proxy->proxy_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy);
 
-	/* move client fd */
-	proxy->client_fd = client->fd;
-	client->fd = -1;
-
-	if (login_proxies == NULL) {
-		login_proxies = hash_create(default_pool, default_pool,
-					    0, NULL, NULL);
-	}
-	hash_insert(login_proxies, proxy, proxy);
+	proxy->callback = callback;
+	proxy->context = context;
 
-	proxy->client = client;
-	main_ref();
-	return 0;
+	proxy->client_fd = -1;
+	return proxy;
 }
 
-static void login_proxy_free(struct login_proxy *proxy)
+void login_proxy_free(struct login_proxy *proxy)
 {
-	main_unref();
+	if (proxy->destroying)
+		return;
 
-	hash_remove(login_proxies, proxy);
+	if (proxy->client_fd != -1) {
+		/* detached proxy */
+		main_unref();
+		hash_remove(login_proxies, proxy);
+
+		if (proxy->client_io != NULL)
+			io_remove(proxy->client_io);
+		if (proxy->client_output != NULL)
+			o_stream_unref(proxy->client_output);
+		net_disconnect(proxy->client_fd);
+	} else {
+		proxy->destroying = TRUE;
+		proxy->callback(NULL, NULL, proxy->context);
+	}
 
 	if (proxy->proxy_io != NULL)
 		io_remove(proxy->proxy_io);
+	if (proxy->proxy_input != NULL)
+		i_stream_unref(proxy->proxy_input);
 	if (proxy->proxy_output != NULL)
 		o_stream_unref(proxy->proxy_output);
-
-	if (proxy->client_io != NULL)
-		io_remove(proxy->client_io);
-	if (proxy->client_output != NULL)
-		o_stream_unref(proxy->client_output);
-
 	net_disconnect(proxy->proxy_fd);
-	net_disconnect(proxy->client_fd);
-
-	if (proxy->login_cmd != NULL) {
-		safe_memset(proxy->login_cmd, 0, strlen(proxy->login_cmd));
-		i_free(proxy->login_cmd);
-	}
 
 	i_free(proxy->host);
-	i_free(proxy->user);
 	i_free(proxy);
 }
 
+void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
+			struct ostream *client_output)
+{
+	const unsigned char *data;
+	size_t size;
+
+	proxy->client_fd = i_stream_get_fd(client_input);
+	proxy->client_output = client_output;
+
+	o_stream_set_max_buffer_size(client_output, (size_t)-1);
+	o_stream_set_flush_callback(client_output, proxy_client_output, proxy);
+
+	/* send all pending client input to proxy and get rid of the stream */
+	data = i_stream_get_data(client_input, &size);
+	if (size != 0)
+		(void)o_stream_send(proxy->proxy_output, data, size);
+	i_stream_unref(client_input);
+
+	/* from now on, just do dummy proxying */
+	io_remove(proxy->proxy_io);
+	proxy->proxy_io = io_add(proxy->proxy_fd, IO_READ, proxy_input, proxy);
+	proxy->client_io = io_add(proxy->client_fd, IO_READ,
+				  proxy_client_input, proxy);
+	o_stream_set_flush_callback(proxy->proxy_output, proxy_output, proxy);
+
+	i_stream_unref(proxy->proxy_input);
+        proxy->proxy_input = NULL;
+
+	if (login_proxies == NULL) {
+		login_proxies = hash_create(default_pool, default_pool,
+					    0, NULL, NULL);
+	}
+	hash_insert(login_proxies, proxy, proxy);
+	main_ref();
+}
+
 void login_proxy_deinit(void)
 {
 	struct hash_iterate_context *iter;

Index: login-proxy.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/login-proxy.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- login-proxy.h	18 Oct 2004 19:21:47 -0000	1.1
+++ login-proxy.h	18 Oct 2004 23:07:01 -0000	1.2
@@ -1,10 +1,24 @@
 #ifndef __LOGIN_PROXY_H
 #define __LOGIN_PROXY_H
 
-/* Create a proxy to given host. Returns -1 if failed, or 0 if ok.
-   In any case the client should be destroyed after this call. */
-int login_proxy_new(struct client *client, const char *host,
-		    unsigned int port, const char *login_cmd);
+struct login_proxy;
+
+/* Called when new input comes from proxy. */
+typedef void proxy_callback_t(struct istream *input, struct ostream *output,
+			      void *context);
+
+/* Create a proxy to given host. Returns NULL if failed. Given callback is
+   called when new input is available from proxy. */
+struct login_proxy *
+login_proxy_new(struct client *client, const char *host, unsigned int port,
+		proxy_callback_t *callback, void *context);
+/* Free the proxy. This should be called if authentication fails. */
+void login_proxy_free(struct login_proxy *proxy);
+
+/* Detach proxy from client. This is done after the authentication is
+   successful and all that is left is the dummy proxying. */
+void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
+			struct ostream *client_output);
 
 void login_proxy_deinit(void);
 



More information about the dovecot-cvs mailing list