diff src/imap-login/client-authenticate.c @ 2768:d344be0bb70f HEAD

Added IMAP and POP3 proxying support.
author Timo Sirainen <tss@iki.fi>
date Mon, 18 Oct 2004 22:21:40 +0300
parents 26a091f3add6
children e624a9ad6a30
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c	Mon Oct 18 11:17:31 2004 +0300
+++ b/src/imap-login/client-authenticate.c	Mon Oct 18 22:21:40 2004 +0300
@@ -13,6 +13,9 @@
 #include "auth-client.h"
 #include "client.h"
 #include "client-authenticate.h"
+#include "imap-proxy.h"
+
+#include <stdlib.h>
 
 const char *client_authenticate_get_capabilities(int secured)
 {
@@ -76,39 +79,85 @@
 	safe_memset(line, 0, strlen(line));
 }
 
-static int client_handle_success_args(struct imap_client *client,
-				      const char *const *args, int nologin)
+static int client_handle_args(struct imap_client *client,
+			      const char *const *args, int nologin)
 {
-	const char *reason = NULL, *referral = NULL;
+	const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
 	string_t *reply;
+	unsigned int port = 143;
+	int proxy = FALSE;
 
 	for (; *args != NULL; args++) {
 		if (strcmp(*args, "nologin") == 0)
 			nologin = TRUE;
+		else if (strcmp(*args, "proxy") == 0)
+			proxy = TRUE;
 		else if (strncmp(*args, "reason=", 7) == 0)
 			reason = *args + 7;
-		else  if (strncmp(*args, "referral=", 9) == 0)
-			referral = *args + 9;
+		else if (strncmp(*args, "host=", 5) == 0)
+			host = *args + 5;
+		else if (strncmp(*args, "port=", 5) == 0)
+			port = atoi(*args + 5);
+		else if (strncmp(*args, "destuser=", 9) == 0)
+			destuser = *args + 9;
+		else if (strncmp(*args, "pass=", 5) == 0)
+			pass = *args + 5;
 	}
 
-	if (!nologin && referral == NULL)
-		return FALSE;
+	if (destuser == NULL)
+		destuser = client->common.virtual_user;
+
+	if (proxy) {
+		/* we want to proxy the connection to another server.
 
-	reply = t_str_new(128);
-	str_append(reply, nologin ? "NO " : "OK ");
-	if (referral != NULL)
-		str_printfa(reply, "[REFERRAL %s] ", referral);
+		   proxy host=.. [port=..] [destuser=..] pass=.. */
+		if (imap_proxy_new(client, host, port, destuser, pass) < 0)
+			client_destroy_internal_failure(client);
+		else {
+			client_destroy(client, t_strconcat(
+				"Proxy: ", client->common.virtual_user, NULL));
+		}
+		return TRUE;
+	} else if (host != NULL) {
+		/* IMAP referral
+
+		   [nologin] referral host=.. [port=..] [destuser=..]
+		   [reason=..]
 
-	if (reason != NULL)
-		str_append(reply, reason);
-	else if (!nologin)
-		str_append(reply, "Logged in.");
-	else if (referral != NULL)
-		str_append(reply, "Try this server instead.");
-	else
-		str_append(reply, "Login disabled.");
+		   NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
+		   OK [...] Logged in, but you should use this server instead.
+		   .. [REFERRAL ..] (Reason from auth server)
+		*/
+		reply = t_str_new(128);
+		str_append(reply, nologin ? "NO " : "OK ");
+		str_printfa(reply, "[REFERRAL imap://%s;AUTH=%s@%s",
+			    destuser, client->common.auth_mech_name, host);
+		if (port != 143)
+			str_printfa(reply, ":%u", port);
+		str_append(reply, "/] ");
+		if (reason != NULL)
+			str_append(reply, reason);
+		else if (nologin)
+			str_append(reply, "Try this server instead.");
+		else {
+			str_append(reply, "Logged in, but you should use "
+				   "this server instead.");
+		}
+		client_send_tagline(client, str_c(reply));
+	} else if (nologin) {
+		/* Authentication went ok, but for some reason user isn't
+		   allowed to log in. Shouldn't probably happen. */
+		reply = t_str_new(128);
+		if (reason != NULL)
+			str_printfa(reply, "NO %s", reason);
+		else
+			str_append(reply, "NO Login not allowed.");
+		client_send_tagline(client, str_c(reply));
+	} else {
+		/* normal login/failure */
+		return FALSE;
+	}
 
-	client_send_tagline(client, str_c(reply));
 	if (!nologin) {
 		client_destroy(client, t_strconcat(
 			"Login: ", client->common.virtual_user, NULL));
@@ -133,7 +182,7 @@
 	switch (reply) {
 	case SASL_SERVER_REPLY_SUCCESS:
 		if (args != NULL) {
-			if (client_handle_success_args(client, args, FALSE))
+			if (client_handle_args(client, args, FALSE))
 				break;
 		}
 
@@ -143,7 +192,7 @@
 		break;
 	case SASL_SERVER_REPLY_AUTH_FAILED:
 		if (args != NULL) {
-			if (client_handle_success_args(client, args, TRUE))
+			if (client_handle_args(client, args, TRUE))
 				break;
 		}
 
@@ -161,11 +210,7 @@
 				    client_input, client);
 		break;
 	case SASL_SERVER_REPLY_MASTER_FAILED:
-		client_send_line(client, "* BYE Internal login failure. "
-				 "Refer to server log for more information.");
-		client_destroy(client, t_strconcat("Internal login failure: ",
-						   client->common.virtual_user,
-						   NULL));
+		client_destroy_internal_failure(client);
 		break;
 	case SASL_SERVER_REPLY_CONTINUE:
 		data_len = strlen(data);