From f86e8f5faa0fb5926001f2dccd970e031e7cb59a Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Tue, 14 Apr 2009 03:35:12 -0400
Subject: [PATCH] - Support STARTTLS in IMAP connection (#1485284)

---
 CHANGELOG                  |    1 +
 program/include/rcmail.php |   10 ++++++----
 program/lib/imap.inc       |   39 ++++++++++++++++++++++++++++++++++-----
 config/main.inc.php.dist   |    2 +-
 4 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 832bc48..9c4a0a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG RoundCube Webmail
 ===========================
 
+- Support STARTTLS in IMAP connection (#1485284)
 - Fix DEL key problem in search boxes (#1485528)
 - Support several e-mail addresses per user from virtuser_file (#1485678)
 - Fix drag&drop with scrolling on IE (#1485786)
diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index b808403..850b2ba 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -51,7 +51,7 @@
 // the mail host chosen to perform the log-in
 // leave blank to show a textbox at login, give a list of hosts
 // to display a pulldown menu or set one host as string.
-// To use SSL connection, enter ssl://hostname:993
+// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
 $rcmail_config['default_host'] = '';
 
 // TCP port used for IMAP connections
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 71601b5..9aad25b 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -436,11 +436,13 @@
     if ($a_host['host']) {
       $host = $a_host['host'];
       $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
-      $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : $config['default_port']);
+      if(!empty($a_host['port']))
+        $imap_port = $a_host['port'];
+      else if ($imap_ssl && $imap_ssl != 'tls')
+        $imap_port = 993;
     }
-    else
-      $imap_port = $config['default_port'];
-
+    
+    $imap_port = $imap_port ? $imap_port : $config['default_port'];
 
     /* Modify username with domain if required  
        Inspired by Marco <P0L0_notspam_binware.org>
diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index d343564..995d82f 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -335,6 +335,7 @@
 	}
 	if ($bye && strncmp($string, '* BYE ', 6) == 0) {
 		return true;
+
 	}
 	return false;
 }
@@ -381,6 +382,12 @@
 	}
 
 	return false;
+}
+
+function iil_C_ClearCapability(&$conn)
+{
+	$conn->capability = array();
+	$conn->capability_readed = false;
 }
 
 function iil_C_Authenticate(&$conn, $user, $pass, $encChallenge) {
@@ -564,7 +571,7 @@
 		
 	$result = false;
 	
-	//initialize connection
+	// initialize connection
 	$conn              = new iilConnection;
 	$conn->error       = '';
 	$conn->errorNum    = 0;
@@ -598,16 +605,15 @@
 		$iil_errornum = -1;
 		return false;
 	}
+
 	if (!$ICL_PORT) {
 		$ICL_PORT = 143;
 	}
-    
 	//check for SSL
-	if ($ICL_SSL) {
+	if ($ICL_SSL && $ICL_SSL != 'tls') {
 		$host = $ICL_SSL . '://' . $host;
 	}
-	
-	//open socket connection
+
 	$conn->fp = fsockopen($host, $ICL_PORT, $errno, $errstr, 10);
 	if (!$conn->fp) {
     		$iil_error = "Could not connect to $host at port $ICL_PORT: $errstr";
@@ -625,6 +631,29 @@
 
 	$conn->message .= $line;
 
+	// TLS connection
+	if ($ICL_SSL == 'tls' && iil_C_GetCapability($conn, 'STARTTLS')) {
+        	if (version_compare(PHP_VERSION, '5.1.0', '>=')) {
+               		iil_PutLine($conn->fp, 'stls000 STARTTLS');
+
+			$line = iil_ReadLine($conn->fp, 4096);
+                	if (!iil_StartsWith($line, 'stls000 OK')) {
+				$iil_error = "Server responded to STARTTLS with: $line";
+				$iil_errornum = -2;
+                    		return false;
+                	}
+
+			if (!stream_socket_enable_crypto($conn->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+				$iil_error = "Unable to negotiate TLS";
+				$iil_errornum = -2;
+				return false;
+			}
+			
+			// Now we're authenticated, capabilities need to be reread
+			iil_C_ClearCapability($conn);
+        	}
+	}
+
 	if (strcasecmp($auth_method, "check") == 0) {
 		//check for supported auth methods
 		if (iil_C_GetCapability($conn, 'AUTH=CRAM-MD5') || iil_C_GetCapability($conn, 'AUTH=CRAM_MD5')) {

--
Gitblit v1.9.1