From 8ebb9d63fb328e4df8f20ad63b5f5cdb760d972b Mon Sep 17 00:00:00 2001 From: m_horde <m_horde@secure.mailbox.org> Date: Mon, 1 Dec 2014 00:36:23 +0100 Subject: [PATCH] Implementation of peer verification in TLS connections --- .../Socket_Client/lib/Horde/Socket/Client.php | 67 ++++++++++++++++++---- horde/config/conf.xml | 10 ++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/framework/Socket_Client/lib/Horde/Socket/Client.php b/framework/Socket_Client/lib/Horde/Socket/Client.php index 91a666a..1e2b09e 100644 --- a/framework/Socket_Client/lib/Horde/Socket/Client.php +++ b/framework/Socket_Client/lib/Horde/Socket/Client.php @@ -43,6 +43,13 @@ class Client protected $_params; /** + * TLS configuration parameters. + * + * @var array + */ + protected $_tls_params; + + /** * Is the connection secure? * * @var boolean @@ -67,11 +74,18 @@ class Client * - true (TLS if available/necessary) * </pre> * @param array $params Additional options. + * @param array $tls_params TLS options. + * <pre> + * - cafile (the certificate authority bundle) + * - ciphers (the cipher string to pass unto openssl) + * - depth (verification depth, only if cafile is set) + * - source (horde: use Horde's $GLOBALS; overwrite: use $tls_params; [empty]: use both, but $tls_params overrules $GLOBALS) + * </pre> * * @throws Horde\Socket\Client\Exception */ public function __construct( - $host, $port, $timeout = 30, $secure = false, array $params = array() + $host, $port, $timeout = 30, $secure = false, array $params = array(), array $tls_params = array() ) { if ($secure && !extension_loaded('openssl')) { @@ -83,6 +97,8 @@ class Client $this->_params = $params; + $this->_tls_params = $tls_params; + $this->_connect($host, $port, $timeout, $secure); } @@ -173,23 +189,52 @@ class Client $conn = 'tcp://'; break; } + + $stream_context_array = array( + 'ssl' => array( + 'verify_peer' => false, + 'verify_peer_name' => false, + 'ciphers' => 'ALL', + 'verify_depth' => 10, + ) + ); + if ((!empty($GLOBALS['conf']['openssl']['cafile']) && $GLOBALS['conf']['openssl']['verify'] && + ($this->_tls_params['source'] != 'overwrite')) || + (!empty($this->_tls_params['cafile']) && ($this->_tls_params['source'] != 'horde'))) { + $stream_context_array['ssl']['verify_peer'] = true; + $stream_context_array['ssl']['verify_peer_name'] = true; + } + /* Be aware that the order of the following if statements is + * important. $_tls_params has to be checked after $GLOBALS, + * because it overrules $GLOBALS. */ + if (!empty($GLOBALS['conf']['openssl']['cafile']) && ($this->_tls_params['source'] != 'overwrite')) { + $stream_context_array['ssl']['cafile'] = $GLOBALS['conf']['openssl']['cafile']; + } + if (!empty($GLOBALS['conf']['openssl']['ciphers']) && ($this->_tls_params['source'] != 'overwrite')) { + $stream_context_array['ssl']['ciphers'] = $GLOBALS['conf']['openssl']['ciphers']; + } + if (!empty($GLOBALS['conf']['openssl']['depth']) && ($this->_tls_params['source'] != 'overwrite')) { + $stream_context_array['ssl']['depth'] = $GLOBALS['conf']['openssl']['depth']; + } + if (!empty($this->_tls_params['cafile']) && ($this->_tls_params['source'] != 'horde')) { + $stream_context_array['ssl']['cafile'] = $this->_tls_params['cafile']; + } + if (!empty($this->_tls_params['ciphers']) && ($this->_tls_params['source'] != 'horde')) { + $stream_context_array['ssl']['ciphers'] = $this->_tls_params['ciphers']; + } + if (!empty($this->_tls_params['depth']) && ($this->_tls_params['source'] != 'horde')) { + $stream_context_array['ssl']['depth'] = $this->_tls_params['depth']; + } + $this->_stream = @stream_socket_client( $conn . $host . ':' . $port, $error_number, $error_string, $timeout, STREAM_CLIENT_CONNECT, - /* @todo: As of PHP 5.6, TLS connections require valid certs. - * However, this is BC-breaking to this library. For now, keep - * pre-5.6 behavior. */ - stream_context_create(array( - 'ssl' => array( - 'verify_peer' => false, - 'verify_peer_name' => false - ) - )) - ); + stream_context_create($stream_context_array) + ); if ($this->_stream === false) { /* From stream_socket_client() page: a function return of false, diff --git a/horde/config/conf.xml b/horde/config/conf.xml index 41a4cec..d9d1bfe 100644 --- a/horde/config/conf.xml +++ b/horde/config/conf.xml @@ -1555,6 +1555,16 @@ certificates bundle, e.g. /etc/ssl/certs. See http://www.php.net/manual/en/openssl.cert.verification.php for details."/> + <configboolean name="verify" required="false" desc="Should we set the ssl + context to verify the peer certificate with the given certificate bundle. + This option has no effect when cafile is not set. + See https://php.net/manual/en/context.ssl.php for details."/> + <configstring name="depth" required="false" desc="The depth for + certificate verification. The default is 10."/> + <configstring name="ciphers" required="false" desc="Limit the used cipers + for secure connections. The default is to enable all ciphers except those + without encryption. See + https://www.openssl.org/docs/apps/ciphers.html for details."/> <configstring name="path" required="false" desc="The location of the OpenSSL binary on your system, e.g. /usr/bin/openssl. This program is REQUIRED to import personal S/MIME certificate information, as there is no native PHP -- 1.9.1