[prev in list] [next in list] [prev in thread] [next in thread]
List: squirrelmail-cvs
Subject: [SM-CVS] SF.net SVN: squirrelmail:[14530] branches/SM-1_4-STABLE/squirrelmail/class/ deliver/Deliver
From: pdontthink () users ! sourceforge ! net
Date: 2015-11-30 23:23:08
Message-ID: E1a3Xmp-0005Ym-Hg () sfs-ml-1 ! v29 ! ch3 ! sourceforge ! com
[Download RAW message or body]
Revision: 14530
http://sourceforge.net/p/squirrelmail/code/14530
Author: pdontthink
Date: 2015-11-30 23:23:07 +0000 (Mon, 30 Nov 2015)
Log Message:
-----------
Add STARTTLS support for SMTP connections
Modified Paths:
--------------
branches/SM-1_4-STABLE/squirrelmail/class/deliver/Deliver_SMTP.class.php
Modified: branches/SM-1_4-STABLE/squirrelmail/class/deliver/Deliver_SMTP.class.php
===================================================================
--- branches/SM-1_4-STABLE/squirrelmail/class/deliver/Deliver_SMTP.class.php 2015-11-30 \
22:54:16 UTC (rev 14529)
+++ branches/SM-1_4-STABLE/squirrelmail/class/deliver/Deliver_SMTP.class.php 2015-11-30 \
23:23:07 UTC (rev 14530) @@ -20,6 +20,29 @@
*/
class Deliver_SMTP extends Deliver {
+ /**
+ * Array keys are uppercased ehlo keywords
+ * array key values are ehlo params. If ehlo-param contains space, it is \
splitted into array. + * @var array ehlo
+ * @since 1.4.23 and 1.5.1
+ */
+ var $ehlo = array();
+
+ /**
+ * @var string domain
+ * @since 1.4.23 and 1.5.1
+ */
+ var $domain = '';
+
+ /**
+ * SMTP STARTTLS rfc: "Both the client and the server MUST know if there
+ * is a TLS session active."
+ * Variable should be set to true, when encryption is turned on.
+ * @var boolean
+ * @since 1.4.23 and 1.5.1
+ */
+ var $tls_enabled = false;
+
function preWriteToStream(&$s) {
if ($s) {
if ($s{0} == '.') $s = '.' . $s;
@@ -55,32 +78,52 @@
$from->mailbox = '';
}
+ // for backward compatibility: boolean $use_smtp_tls set
+ // to TRUE means to use plain TLS (as opposed to STARTTLS)
+ //
+ if ($use_smtp_tls === TRUE)
+ $use_smtp_tls = 1;
+
// NB: Using "ssl://" ensures the highest possible TLS version
// will be negotiated with the server (whereas "tls://" only
// uses TLS version 1.0)
//
- if (($use_smtp_tls == true) and (check_php_version(4,3)) and \
(extension_loaded('openssl'))) {
- if (function_exists('stream_socket_client')) {
- $server_address = 'ssl://' . $host . ':' . $port;
- $ssl_context = @stream_context_create($stream_options);
- $connect_timeout = ini_get('default_socket_timeout');
- // null timeout is broken
- if ($connect_timeout == 0)
- $connect_timeout = 30;
- $stream = @stream_socket_client($server_address, $errorNumber, \
$errorString, $connect_timeout, STREAM_CLIENT_CONNECT, $ssl_context); + if \
($use_smtp_tls == 1) { + if ((check_php_version(4,3)) && \
(extension_loaded('openssl'))) { + if \
(function_exists('stream_socket_client')) { + $server_address = \
'ssl://' . $host . ':' . $port; + $ssl_context = \
@stream_context_create($stream_options); + $connect_timeout = \
ini_get('default_socket_timeout'); + // null timeout is broken
+ if ($connect_timeout == 0)
+ $connect_timeout = 30;
+ $stream = @stream_socket_client($server_address, $errorNumber, \
$errorString, $connect_timeout, STREAM_CLIENT_CONNECT, $ssl_context); + \
} else { + $stream = @fsockopen('ssl://' . $host, $port, \
$errorNumber, $errorString); + }
+ $this->tls_enabled = true;
} else {
- $stream = @fsockopen('ssl://' . $host, $port, $errorNumber, \
$errorString); + /**
+ * don't connect to server when user asks for smtps and
+ * PHP does not support it.
+ */
+ $errorNumber = '';
+ $errorString = _("Secure SMTP (TLS) is enabled in SquirrelMail \
configuration, but used PHP version does not support it."); }
} else {
$stream = @fsockopen($host, $port, $errorNumber, $errorString);
}
if (!$stream) {
+ // reset tls state var to default value, if connection fails
+ $this->tls_enabled = false;
+ // set error messages
$this->dlv_msg = $errorString;
$this->dlv_ret_nr = $errorNumber;
$this->dlv_server_msg = _("Can't open SMTP stream.");
return(0);
}
+ // get server greeting
$tmp = fgets($stream, 1024);
if ($this->errorCheck($tmp, $stream)) {
return(0);
@@ -110,7 +153,8 @@
/* Lets introduce ourselves */
fputs($stream, "EHLO $helohost\r\n");
- $tmp = fgets($stream,1024);
+ // Read ehlo response
+ $tmp = $this->parse_ehlo_response($stream);
if ($this->errorCheck($tmp,$stream)) {
// fall back to HELO if EHLO is not supported (error 5xx)
if ($this->dlv_ret_nr{0} == '5') {
@@ -124,6 +168,60 @@
}
}
+ /**
+ * Implementing SMTP STARTTLS (rfc2487) in php 5.1.0+
+ * http://www.php.net/stream-socket-enable-crypto
+ */
+ if ($use_smtp_tls === 2) {
+ if (function_exists('stream_socket_enable_crypto')) {
+ // don't try starting tls, when client thinks that it is already \
active + if ($this->tls_enabled) {
+ $this->dlv_msg = _("TLS session is already activated.");
+ return 0;
+ } elseif (!array_key_exists('STARTTLS',$this->ehlo)) {
+ // check for starttls in ehlo response
+ $this->dlv_msg = _("SMTP STARTTLS is enabled in SquirrelMail \
configuration, but used SMTP server does not support it"); + \
return 0; + }
+
+ // issue starttls command
+ fputs($stream, "STARTTLS\r\n");
+ // get response
+ $tmp = fgets($stream,1024);
+ if ($this->errorCheck($tmp,$stream)) {
+ return 0;
+ }
+
+ // start crypto on connection. suppress function errors.
+ if (@stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT)) \
{ + // starttls was successful (rfc2487 5.2 Result of the STARTTLS \
Command) + // get new EHLO response
+ fputs($stream, "EHLO $helohost\r\n");
+ // Read ehlo response
+ $tmp = $this->parse_ehlo_response($stream);
+ if ($this->errorCheck($tmp,$stream)) {
+ // don't revert to helo here. server must support ESMTP
+ return 0;
+ }
+ // set information about started tls
+ $this->tls_enabled = true;
+ } else {
+ /**
+ * stream_socket_enable_crypto() call failed.
+ */
+ $this->dlv_msg = _("Unable to start TLS.");
+ return 0;
+ // Bug: can't get error message. See comments in \
sqimap_create_stream(). + }
+ } else {
+ // php install does not support stream_socket_enable_crypto() \
function + $this->dlv_msg = _("SMTP STARTTLS is enabled in \
SquirrelMail configuration, but used PHP version does not support functions that \
allow to enable encryption on open socket."); + return 0;
+ }
+ }
+
+ // FIXME: check ehlo response before using authentication
+
// Try authentication by a plugin
//
// NOTE: there is another hook in functions/auth.php called "smtp_auth"
@@ -389,5 +487,66 @@
fclose($popConnection);
}
}
+
+ /**
+ * Parses ESMTP EHLO response (rfc1869)
+ *
+ * Reads SMTP response to EHLO command and fills class variables
+ * (ehlo array and domain string). Returns last line.
+ * @param stream $stream smtp connection stream.
+ * @return string last ehlo line
+ * @since 1.4.23 and 1.5.1
+ */
+ function parse_ehlo_response($stream) {
+ // don't cache ehlo information
+ $this->ehlo=array();
+ $ret = '';
+ $firstline = true;
+ /**
+ * ehlo mailclient.example.org
+ * 250-mail.example.org
+ * 250-PIPELINING
+ * 250-SIZE 52428800
+ * 250-DATAZ
+ * 250-STARTTLS
+ * 250-AUTH LOGIN PLAIN
+ * 250 8BITMIME
+ */
+ while ($line=fgets($stream, 1024)){
+ // match[1] = first symbol after 250
+ // match[2] = domain or ehlo-keyword
+ // match[3] = greeting or ehlo-param
+ // match space after keyword in ehlo-keyword CR LF
+ if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)\r\n/",$line,$match)||
+ preg_match("/^250(-|\s)(\S*)\s*\r\n/",$line,$match)) {
+ if ($firstline) {
+ // first ehlo line (250[-\ ]domain SP greeting)
+ $this->domain = $match[2];
+ $firstline=false;
+ } elseif (!isset($match[3])) {
+ // simple one word extension
+ $this->ehlo[strtoupper($match[2])]='';
+ } elseif (!preg_match("/\s/",trim($match[3]))) {
+ // extension with one option
+ // yes, I know about ctype extension. no, i don't want to depend \
on it + $this->ehlo[strtoupper($match[2])]=trim($match[3]);
+ } else {
+ // ehlo-param with spaces
+ $this->ehlo[strtoupper($match[2])]=explode(' ',trim($match[3]));
+ }
+ if ($match[1]==' ') {
+ // stop while cycle, if we reach last 250 line
+ $ret = $line;
+ break;
+ }
+ } else {
+ // this is not 250 response
+ $ret = $line;
+ break;
+ }
+ }
+ return $ret;
+ }
+
}
This was sent by the SourceForge.net collaborative development platform, the world's \
largest Open Source development site.
------------------------------------------------------------------------------
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741911&iu=/4140
-----
squirrelmail-cvs mailing list
List address: squirrelmail-cvs@lists.sourceforge.net
List info (subscribe/unsubscribe/change options): \
https://lists.sourceforge.net/lists/listinfo/squirrelmail-cvs
Repository: http://squirrelmail.org/svn
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic