From ac492d8f1e7ef3420ebaee35131e342a39dfda10 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Mon, 22 Aug 2011 23:33:34 +0200 Subject: [PATCH 1/2] [ticket/10076] Move EHLO/HELO code into its own method. PHPBB3-10076 --- phpBB/includes/functions_messenger.php | 62 ++++++++++++++++---------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 13d9b6a5cb..ccc17865f6 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -1286,30 +1286,10 @@ class smtp_class } } - // Try EHLO first - $this->server_send("EHLO {$local_host}"); - if ($err_msg = $this->server_parse('250', __LINE__)) + $hello_result = $this->hello($local_host); + if (!is_null($hello_result)) { - // a 503 response code means that we're already authenticated - if ($this->numeric_response_code == 503) - { - return false; - } - - // If EHLO fails, we try HELO - $this->server_send("HELO {$local_host}"); - if ($err_msg = $this->server_parse('250', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - } - - foreach ($this->responses as $response) - { - $response = explode(' ', $response); - $response_code = $response[0]; - unset($response[0]); - $this->commands[$response_code] = implode(' ', $response); + return $hello_result; } // If we are not authenticated yet, something might be wrong if no username and passwd passed @@ -1355,6 +1335,42 @@ class smtp_class return $this->$method($username, $password); } + /** + * SMTP EHLO/HELO + * + * @return mixed Null if the authentication process is supposed to continue + * False if already authenticated + * Error message (string) otherwise + */ + protected function hello($hostname) + { + // Try EHLO first + $this->server_send("EHLO $hostname"); + if ($err_msg = $this->server_parse('250', __LINE__)) + { + // a 503 response code means that we're already authenticated + if ($this->numeric_response_code == 503) + { + return false; + } + + // If EHLO fails, we try HELO + $this->server_send("HELO $hostname"); + if ($err_msg = $this->server_parse('250', __LINE__)) + { + return ($this->numeric_response_code == 503) ? false : $err_msg; + } + } + + foreach ($this->responses as $response) + { + $response = explode(' ', $response); + $response_code = $response[0]; + unset($response[0]); + $this->commands[$response_code] = implode(' ', $response); + } + } + /** * Pop before smtp authentication */ From 237ddf9d22e0aeccad5e1db022de3a890871849f Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Mon, 22 Aug 2011 23:50:02 +0200 Subject: [PATCH 2/2] [ticket/10076] STARTTLS support for SMTP via smtp_class. PHPBB3-10076 --- phpBB/includes/functions_messenger.php | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index ccc17865f6..f4e49b1b18 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -1136,6 +1136,7 @@ class smtp_class { var $server_response = ''; var $socket = 0; + protected $socket_tls = false; var $responses = array(); var $commands = array(); var $numeric_response_code = 0; @@ -1292,6 +1293,25 @@ class smtp_class return $hello_result; } + // SMTP STARTTLS (RFC 3207) + if (!$this->socket_tls) + { + $this->socket_tls = $this->starttls(); + + if ($this->socket_tls) + { + // Switched to TLS + // RFC 3207: "The client MUST discard any knowledge obtained from the server, [...]" + // So say hello again + $hello_result = $this->hello($local_host); + + if (!is_null($hello_result)) + { + return $hello_result; + } + } + } + // If we are not authenticated yet, something might be wrong if no username and passwd passed if (!$username || !$password) { @@ -1371,6 +1391,43 @@ class smtp_class } } + /** + * SMTP STARTTLS (RFC 3207) + * + * @return bool Returns true if TLS was started + * Otherwise false + */ + protected function starttls() + { + if (!function_exists('stream_socket_enable_crypto')) + { + return false; + } + + if (!isset($this->commands['STARTTLS'])) + { + return false; + } + + $this->server_send('STARTTLS'); + + if ($err_msg = $this->server_parse('220', __LINE__)) + { + return false; + } + + $result = false; + $stream_meta = stream_get_meta_data($this->socket); + + if (socket_set_blocking($this->socket, 1)); + { + $result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + socket_set_blocking($this->socket, (int) $stream_meta['blocked']); + } + + return $result; + } + /** * Pop before smtp authentication */