login_no_tls_networks setting to list networks for which we don't want to
advertise STARTTLS capability. Proper way to do this will be once
master/config rewrite is finished. Then you can change any settings based on
IP and whatever.

Index: src/imap-login/client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap-login/client.c,v
retrieving revision 1.38
diff -u -r1.38 client.c
--- src/imap-login/client.c	28 Oct 2004 15:22:35 -0000	1.38
+++ src/imap-login/client.c	5 Nov 2004 15:22:56 -0000
@@ -93,11 +93,26 @@
 static const char *get_capability(struct imap_client *client)
 {
 	const char *auths;
+	int starttls;
+
+	starttls = ssl_initialized && !client->common.tls;
+	if (starttls && no_tls_networks != NULL &&
+	    client->common.ip.family == AF_INET) {
+		const uint32_t *data = no_tls_networks->data;
+		unsigned int i, count = no_tls_networks->used / sizeof(*data);
+		uint32_t client_ip;
+
+		memcpy(&client_ip, &client->common.ip.ip, 4);
+		for (i = 0; i < count; i += 2) {
+			if (data[i] == (client_ip & data[i+1])) {
+				starttls = FALSE;
+				break;
+			}
+		}
+	}
 
 	auths = client_authenticate_get_capabilities(client->common.secured);
-	return t_strconcat(CAPABILITY_STRING,
-			   (ssl_initialized && !client->common.tls) ?
-			   " STARTTLS" : "",
+	return t_strconcat(CAPABILITY_STRING, starttls ? " STARTTLS" : "",
 			   disable_plaintext_auth && !client->common.secured ?
 			   " LOGINDISABLED" : "", auths, NULL);
 }
Index: src/login-common/common.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/common.h,v
retrieving revision 1.6
diff -u -r1.6 common.h
--- src/login-common/common.h	18 Oct 2004 23:07:01 -0000	1.6
+++ src/login-common/common.h	5 Nov 2004 15:22:56 -0000
@@ -11,6 +11,7 @@
 extern unsigned int max_logging_users;
 extern unsigned int login_process_uid;
 extern struct auth_client *auth_client;
+extern buffer_t *no_tls_networks;
 
 void main_ref(void);
 void main_unref(void);
Index: src/login-common/main.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/main.c,v
retrieving revision 1.23
diff -u -r1.23 main.c
--- src/login-common/main.c	18 Oct 2004 19:21:47 -0000	1.23
+++ src/login-common/main.c	5 Nov 2004 15:22:56 -0000
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "buffer.h"
 #include "ioloop.h"
 #include "lib-signals.h"
 #include "randgen.h"
@@ -24,6 +25,7 @@
 unsigned int max_logging_users;
 unsigned int login_process_uid;
 struct auth_client *auth_client;
+buffer_t *no_tls_networks;
 
 static struct ioloop *ioloop;
 static struct io *io_listen, *io_ssl_listen;
@@ -150,6 +152,46 @@
 	restrict_process_size((unsigned int)-1, 1);
 }
 
+static void parse_no_tls_networks(const char *value)
+{
+	const char *const *tmp, *addr, *prefix;
+	struct ip_addr ip;
+	uint32_t ipnum, mask;
+
+        no_tls_networks = buffer_create_dynamic(default_pool, 256);
+
+	t_push();
+	for (tmp = t_strsplit_spaces(value, " "); *tmp != NULL; tmp++) {
+		addr = *tmp;
+		prefix = strchr(addr, '/');
+		if (prefix != NULL) {
+			addr = t_strdup_until(addr, prefix);
+			prefix++;
+			if (!is_numeric(prefix, '\0')) {
+				i_error("no_tls_networks: Invalid prefix: %s",
+					prefix);
+				continue;
+			}
+			mask = atoi(prefix);
+		} else {
+			mask = 32;
+		}
+
+		if (net_addr2ip(addr, &ip) < 0 || ip.family != AF_INET) {
+			i_error("no_tls_networks: Invalid IPv4 address: %s",
+				addr);
+			continue;
+		}
+		mask = htonl(~((1U << (32 - mask))-1));
+		memcpy(&ipnum, &ip.ip, 4);
+		ipnum &= mask;
+
+		buffer_append(no_tls_networks, &ipnum, 4);
+		buffer_append(no_tls_networks, &mask, 4);
+	}
+	t_pop();
+}
+
 static void main_init(void)
 {
 	const char *value;
@@ -177,7 +219,11 @@
 	if (login_process_uid == 0)
 		i_fatal("BUG: PROCESS_UID environment is 0");
 
-        closing_down = FALSE;
+	value = getenv("NO_TLS_NETWORKS");
+	if (value != NULL && *value != '\0')
+		parse_no_tls_networks(value);
+
+	closing_down = FALSE;
 	main_refcount = 0;
 
 	auth_client = auth_client_new((unsigned int)getpid());
Index: src/master/login-process.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.61
diff -u -r1.61 login-process.c
--- src/master/login-process.c	19 Oct 2004 01:17:39 -0000	1.61
+++ src/master/login-process.c	5 Nov 2004 15:22:56 -0000
@@ -441,6 +441,8 @@
 	env_put(t_strconcat("GREETING=", set->login_greeting, NULL));
 	if (set->login_greeting_capability)
 		env_put("GREETING_CAPABILITY=1");
+	env_put(t_strconcat("NO_TLS_NETWORKS=",
+			    set->login_no_tls_networks, NULL));
 }
 
 static pid_t create_login_process(struct login_group *group)
Index: src/master/master-settings.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/master-settings.c,v
retrieving revision 1.75
diff -u -r1.75 master-settings.c
--- src/master/master-settings.c	21 Oct 2004 20:47:36 -0000	1.75
+++ src/master/master-settings.c	5 Nov 2004 15:22:57 -0000
@@ -65,6 +65,7 @@
 	DEF(SET_STR, login_executable),
 	DEF(SET_STR, login_user),
 	DEF(SET_STR, login_greeting),
+	DEF(SET_STR, login_no_tls_networks),
 
 	DEF(SET_BOOL, login_process_per_connection),
 	DEF(SET_BOOL, login_chroot),
@@ -231,6 +232,7 @@
 	MEMBER(login_executable) NULL,
 	MEMBER(login_user) "dovecot",
 	MEMBER(login_greeting) "Dovecot ready.",
+	MEMBER(login_no_tls_networks) NULL,
 
 	MEMBER(login_process_per_connection) TRUE,
 	MEMBER(login_chroot) TRUE,
Index: src/master/master-settings.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/master-settings.h,v
retrieving revision 1.49
diff -u -r1.49 master-settings.h
--- src/master/master-settings.h	21 Oct 2004 02:23:13 -0000	1.49
+++ src/master/master-settings.h	5 Nov 2004 15:22:57 -0000
@@ -38,6 +38,7 @@
 	const char *login_executable;
 	const char *login_user;
 	const char *login_greeting;
+	const char *login_no_tls_networks;
 
 	int login_process_per_connection;
 	int login_chroot;
Index: src/pop3-login/client-authenticate.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/pop3-login/client-authenticate.c,v
retrieving revision 1.39
diff -u -r1.39 client-authenticate.c
--- src/pop3-login/client-authenticate.c	29 Oct 2004 17:56:46 -0000	1.39
+++ src/pop3-login/client-authenticate.c	5 Nov 2004 15:22:57 -0000
@@ -24,6 +24,7 @@
 	const struct auth_mech_desc *mech;
 	unsigned int i, count;
 	string_t *str;
+	int stls;
 
 	str = t_str_new(128);
 	str_append(str, "SASL");
@@ -42,10 +43,25 @@
 		}
 	}
 
+	stls = ssl_initialized && !client->common.tls;
+	if (stls && no_tls_networks != NULL &&
+	    client->common.ip.family == AF_INET) {
+		const uint32_t *data = no_tls_networks->data;
+		unsigned int i, count = no_tls_networks->used / sizeof(*data);
+		uint32_t client_ip;
+
+		memcpy(&client_ip, &client->common.ip.ip, 4);
+		for (i = 0; i < count; i += 2) {
+			if (data[i] == (client_ip & data[i+1])) {
+				stls = FALSE;
+				break;
+			}
+		}
+	}
+
 	client_send_line(client,
 			 t_strconcat("+OK\r\n" POP3_CAPABILITY_REPLY,
-				     (ssl_initialized && !client->common.tls) ?
-				     "STLS\r\n" : "",
+				     stls ? "STLS\r\n" : "",
 				     str_c(str), "\r\n.", NULL));
 	return TRUE;
 }
