user3010474 user3010474 - 4 months ago 46
PHP Question

Codeigniter 2x Email Class SMTP SSL verification bug on PHP 5.6

I don't know how many of you work with Codeigniter 2x on PHP 5.6, but this latest PHP version has brought changes that Codeigniter hasn't been adapted to. One of these changes is about OpenSSL:


All encrypted client streams now enable peer verification by default. By default, this will use OpenSSL's default CA bundle to verify the peer certificate. In most cases, no changes will need to be made to communicate with servers with valid SSL certificates, as distributors generally configure OpenSSL to use known good CA bundles. - OpenSSL changes in PHP 5.6.x (PHP Manual)






It appears that in PHP 5.6.0 (at least the version in Debian jessie, with openssl 1.0.1h-3), this function is now validating SSL certificates (in a variety of ways). First, it appears to fail for untrusted certificates (i.e. no matching CA trusted locally), and secondly, it appears to fail for mismatched hostnames in the request and certificate.






"PHP 5.6 now verifies SSL certificates, the "fsockopen" function fails in the "ConnectToHost" method due to mismatched certificate CN (expects host name, but IP is given instead)." - Klemen (PHP 5.6 compatibility)


The problem is that this change is resulting in an error on Email Class SMTP protocol:


fsockopen(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed


I am using Windows's IIS 7 local server and when I switch PHP's version to 5.3, the email is successfully sent. Now when I switch it back to 5.6, the SSL verification occurs. That being said, it is really a problem of PHP's latest, 5.6, version.

Here is the code I am using to send the e-mail via SMTP:

$config = array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://smtp.googlemail.com',
'smtp_port' => 465,
'smtp_user' => 'xxxx@gmail.com', // change it to yours
'smtp_pass' => 'xxxx', // change it to yours
'mailtype' => 'html',
'charset' => 'iso-8859-1',
'wordwrap' => TRUE,
);
$message = 'When they give you the eys!!!!';
$this->load->library('email', $config);
$this->email->set_newline("\r\n");
$this->email->from('xxxx@xxxx.com','Insert Name'); // change it to yours
$this->email->to('xxxxx@xxxxxx.com');// change it to yours
$this->email->subject('Bye, bye, pretty baby!');
$this->email->message($message);
if($this->email->send())
{
echo 'Email sent.';
}
else
{
show_error($this->email->print_debugger());
}


Here's a Email library's method to send email with SMTP:

protected function _smtp_connect()
{
$ssl = NULL;
if ($this->smtp_crypto == 'ssl')
$ssl = 'ssl://';
$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
$this->smtp_port,
$errno,
$errstr,
$this->smtp_timeout);
if ( ! is_resource($this->_smtp_connect))
{
$this->_set_error_message('lang:email_smtp_error', $errno." ".$errstr);
return FALSE;
}
$this->_set_error_message($this->_get_smtp_data());
if ($this->smtp_crypto == 'tls')
{
$this->_send_command('hello');
$this->_send_command('starttls');
stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
}
return $this->_send_command('hello');
}


Do you know how can I make it work on 5.6? Thanks!

Answer

First, your email config are ok! Don't worry about this...
When you update to PHP 5.6+ the "CA Root" have to be set, or OpenSSL certificate verify don't work correctly.

Step One: Install CA_Root (In my case, on FreeBSD 10, via Ports)
/usr/ports/security/ca_root_nss

After install, the Pem Cert will be located at:
/usr/local/etc/ssl/cert.pem


Step Two: Add to php.ini the openssl.cafile

openssl.cafile = /usr/local/etc/ssl/cert.pem

Restart your HTTP Server, and verify with phpinfo() enter image description here

More details about this, my Blog on PT-BR language

PS: Sometimes... Don't forget to authorize your device to access Gmail at: Settings/Other Config Account.../Devices

Comments