Skip to content
Permalink
Browse files

Move SSL context options into CakeSocket.

Having all the options consolidated in one places enables all the SSL
context options to be used in the SmtpTransport instead of just allowing
self_signed as proposed in #7496
  • Loading branch information...
markstory committed Oct 13, 2015
1 parent 5dfb780 commit cc3531d2886c96afb9c53e363cd4eaa04f92b2f3
@@ -134,6 +134,7 @@ public function connect() {
$scheme = $this->config['protocol'] . '://';
}
$this->_setSslContext($this->config['host']);
if (!empty($this->config['context'])) {
$context = stream_context_create($this->config['context']);
} else {
@@ -195,6 +196,46 @@ public function connect() {
return $this->connected;
}
/**
* Configure the SSL context options.
*
* @param string $host The host name being connected to.
*/
protected function _setSslContext($host)
{
foreach ($this->config as $key => $value) {
if (substr($key, 0, 4) !== 'ssl_') {
continue;
}
$contextKey = substr($key, 4);
if (empty($this->config['context']['ssl'][$contextKey])) {
$this->config['context']['ssl'][$contextKey] = $value;
}
unset($this->config[$key]);
}
if (version_compare(PHP_VERSION, '5.3.2', '>=')) {
if (!isset($this->config['context']['ssl']['SNI_enabled'])) {
$this->config['context']['ssl']['SNI_enabled'] = true;
}
if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
if (empty($this->config['context']['ssl']['peer_name'])) {
$this->config['context']['ssl']['peer_name'] = $host;
}
} else {
if (empty($this->config['context']['ssl']['SNI_server_name'])) {
$this->config['context']['ssl']['SNI_server_name'] = $host;
}
}
}
if (empty($this->config['context']['ssl']['cafile'])) {
$this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem';
}
if (!empty($this->config['context']['ssl']['verify_host'])) {
$this->config['context']['ssl']['CN_match'] = $host;
}
unset($this->config['context']['ssl']['verify_host']);
}
/**
* socket_stream_client() does not populate errNum, or $errStr when there are
* connection errors, as in the case of SSL verification failure.
@@ -72,7 +72,7 @@ class HttpSocket extends CakeSocket {
* Contain information about the last response (read only)
*
* @var array
*/
*/
public $response = null;
/**
@@ -361,8 +361,6 @@ public function request($request = array()) {
return false;
}
$this->_configContext($this->request['uri']['host']);
$this->request['raw'] = '';
if ($this->request['line'] !== false) {
$this->request['raw'] = $this->request['line'];
@@ -374,6 +372,8 @@ public function request($request = array()) {
$this->request['raw'] .= "\r\n";
$this->request['raw'] .= $this->request['body'];
// SSL context is set during the connect() method.
$this->write($this->request['raw']);
$response = null;
@@ -700,47 +700,6 @@ protected function _configUri($uri = null) {
return true;
}
/**
* Configure the socket's context. Adds in configuration
* that can not be declared in the class definition.
*
* @param string $host The host you're connecting to.
* @return void
*/
protected function _configContext($host) {
foreach ($this->config as $key => $value) {
if (substr($key, 0, 4) !== 'ssl_') {
continue;
}
$contextKey = substr($key, 4);
if (empty($this->config['context']['ssl'][$contextKey])) {
$this->config['context']['ssl'][$contextKey] = $value;
}
unset($this->config[$key]);
}
if (version_compare(PHP_VERSION, '5.3.2', '>=')) {
if (!isset($this->config['context']['ssl']['SNI_enabled'])) {
$this->config['context']['ssl']['SNI_enabled'] = true;
}
if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
if (empty($this->config['context']['ssl']['peer_name'])) {
$this->config['context']['ssl']['peer_name'] = $host;
}
} else {
if (empty($this->config['context']['ssl']['SNI_server_name'])) {
$this->config['context']['ssl']['SNI_server_name'] = $host;
}
}
}
if (empty($this->config['context']['ssl']['cafile'])) {
$this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem';
}
if (!empty($this->config['context']['ssl']['verify_host'])) {
$this->config['context']['ssl']['CN_match'] = $host;
}
unset($this->config['context']['ssl']['verify_host']);
}
/**
* Takes a $uri array and turns it into a fully qualified URL string
*
@@ -379,7 +379,37 @@ public function testGetContext() {
$this->Socket = new CakeSocket($config);
$this->Socket->connect();
$result = $this->Socket->context();
$this->assertEquals($config['context'], $result);
$this->assertSame($config['context']['ssl']['capture_peer'], $result['ssl']['capture_peer']);
}
/**
* test configuring the context from the flat keys.
*
* @return void
*/
public function testConfigContext() {
$this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.');
$config = array(
'host' => 'smtp.gmail.com',
'port' => 465,
'timeout' => 5,
'ssl_verify_peer' => true,
'ssl_allow_self_signed' => false,
'ssl_verify_depth' => 5,
'ssl_verify_host' => true,
);
$this->Socket = new CakeSocket($config);
$this->Socket->connect();
$result = $this->Socket->context();
$this->assertTrue($result['ssl']['verify_peer']);
$this->assertFalse($result['ssl']['allow_self_signed']);
$this->assertEquals(5, $result['ssl']['verify_depth']);
$this->assertEquals('smtp.gmail.com', $result['ssl']['CN_match']);
$this->assertArrayNotHasKey('ssl_verify_peer', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_allow_self_signed', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_verify_host', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_verify_depth', $this->Socket->config);
}
}
@@ -314,23 +314,6 @@ public function testRequest() {
$response = $this->Socket->request(true);
$this->assertFalse($response);
$context = array(
'ssl' => array(
'verify_peer' => true,
'allow_self_signed' => false,
'verify_depth' => 5,
'SNI_enabled' => true,
'CN_match' => 'www.cakephp.org',
'cafile' => CAKE . 'Config' . DS . 'cacert.pem'
)
);
if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
$context['ssl']['peer_name'] = 'www.cakephp.org';
} else {
$context['ssl']['SNI_server_name'] = 'www.cakephp.org';
}
$tests = array(
array(
'request' => 'http://www.cakephp.org/?foo=bar',
@@ -341,7 +324,10 @@ public function testRequest() {
'protocol' => 'tcp',
'port' => 80,
'timeout' => 30,
'context' => $context,
'ssl_verify_peer' => true,
'ssl_allow_self_signed' => false,
'ssl_verify_depth' => 5,
'ssl_verify_host' => true,
'request' => array(
'uri' => array(
'scheme' => 'http',
@@ -1843,27 +1829,6 @@ public function testPartialReset() {
$this->assertEquals(true, $return);
}
/**
* test configuring the context from the flat keys.
*
* @return void
*/
public function testConfigContext() {
$this->Socket->expects($this->any())
->method('read')->will($this->returnValue(false));
$this->Socket->reset();
$this->Socket->request('http://example.com');
$this->assertTrue($this->Socket->config['context']['ssl']['verify_peer']);
$this->assertFalse($this->Socket->config['context']['ssl']['allow_self_signed']);
$this->assertEquals(5, $this->Socket->config['context']['ssl']['verify_depth']);
$this->assertEquals('example.com', $this->Socket->config['context']['ssl']['CN_match']);
$this->assertArrayNotHasKey('ssl_verify_peer', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_allow_self_signed', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_verify_host', $this->Socket->config);
$this->assertArrayNotHasKey('ssl_verify_depth', $this->Socket->config);
}
/**
* Test that requests fail when peer verification fails.
*

0 comments on commit cc3531d

Please sign in to comment.
You can’t perform that action at this time.