I am using a PSP that recently switched to only support TLS 1.2 (as per PCI-DSS).
Within a php7 application, I can connect to their SOAP API. However, since their upgrade I am getting an SSL error indicating their server does not support my TLS version. I ran a wireshark and can confirm there is only a client hello, so server hello and it is on TLS 1.0.
I am using the following code:
$this->soapClient = new SoapClient('some/wsdl'), [
'location' => 'https://endpoint.of.server',
'soap_version' => SOAP_1_1,
'stream_context' => stream_context_create([
'ssl' => [
'local_cert' => '/path/to/client.crt',
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
],
])
]);
However, this code still uses TLS 1.0 and not the desired TLS 1.2.
Versions
OpenSSL 1.1.0h 27 Mar 2018
PHP 7.1.6-1~ubuntu16.04.1+deb.sury.org+1 (cli) ( NTS ).
As it turns out, the above code is 100% correct.
In my case, the error lay somewhere in the certificate. For still unknown reasons, our self-generated SSL client certificate did not cope well with TLS 1.2. After we generated a new certificate, everything worked like magic.
Things I've tried / verified
Make sure your have a supported openssl verion (>= 1.0.1)
Consider manually specifying the ciphers
Debug the connection using Wireshark to verify the protocol
Also, take a look at How to force a certain TLS version in a PHP stream context for the ssl:// transport?
Related
I am trying to make a simple file_get_contents(https://some.api) in my code, but, while the URL works in the browser, it doesn't in php. I always get the following error:
file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:0A000126:SSL routines::unexpected eof while reading
I already tried some suggestions from similar questions in Stack Overflown like using stream_context_create():
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$geoData = file_get_contents($requestUrl, false, stream_context_create($arrContextOptions));
But it still doesn't work. PHP SLL also seems to be ok:
~ » php -i | grep -i openssl user#localhost
SSL Version => OpenSSL/3.0.3
libSSH Version => libssh/0.9.6/openssl/zlib
libmongoc SSL library => OpenSSL
openssl
OpenSSL support => enabled
OpenSSL Library Version => OpenSSL 3.0.3 3 May 2022
OpenSSL Header Version => OpenSSL 3.0.2 15 Mar 2022
Openssl default config => /etc/pki/tls/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Native OpenSSL support => enabled
This is likely due to this issue: https://bugs.php.net/bug.php?id=79589
An IIS or equivalent non-compliant daemon is not following the SSL specification and OpenSSL is raising an error because of this. PHP does not provide any method to work around it and since you cannot pass the necessary SSL_OP_IGNORE_UNEXPECTED_EOF flag to OpenSSL the connection fails with an error.
For reference:
https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html
SSL_OP_IGNORE_UNEXPECTED_EOF
Some TLS implementations do not send the mandatory close_notify alert on shutdown. If the application tries to wait for the
close_notify alert but the peer closes the connection without sending
it, an error is generated. When this option is enabled the peer does
not need to send the close_notify alert and a closed connection will
be treated as if the close_notify alert was received.
I had a problem with PHPMailer suddenly saying my certificate had expired and refusing to connect properly to port 587 with TLS encryption, from Oct 1 2021.
Changing the ssl flags to not verify_peer and not verify_peer_name will temp fix the email issue.
$mail->SMTPOptions = array (
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
));
But its not an ideal solution.
If I go to the same server via port 80 and web there is nothing wrong with the certificate.
If I connect with OpenSSL command line it says the certificate expired on Sep 30 2021.
This problem also appears under the php command file_get_contents.
NOTE: This issue is PHPMailer and email specific and provides good information about PHPMailer, it should not be closed. It has nothing to do with docker or the other question its associated with other than the cause and fix being similar.
The issue here is a real expired authority cert embedded in the LetsEncrypt chain which really DID expire on Sep 30 2021.
From the openssl blog ...
The currently recommended certificate chain as presented to Let’s Encrypt ACME clients when new certificates are issued contains an intermediate certificate (ISRG Root X1) that is signed by an old DST Root CA X3 certificate that expires on 2021-09-30. In some cases the OpenSSL 1.0.2 version will regard the certificates issued by the Let’s Encrypt CA as having an expired trust chain.
Read more here ...
https://www.openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire/
It mainly affects OpenSSL 1.0.2. On my Mac with OpenSSL 1.1.1 I did not have the issue.
CentOS, and I'm sure others have provided fixes to this issue ...
Backup
cp -i /etc/pki/tls/certs/ca-bundle.crt ~/ca-bundle.crt-backup
Add certificate to blacklist directory
trust dump --filter "pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10" | openssl x509 | sudo tee /etc/pki/ca-trust/source/blacklist/DST-Root-CA-X3.pem
Update root store
sudo update-ca-trust extract
Verify removal
diff ~/ca-bundle.crt-backup /etc/pki/tls/certs/ca-bundle.crt
The CentOS specific steps above are from this post ...
https://blog.devgenius.io/rhel-centos-7-fix-for-lets-encrypt-change-8af2de587fe4#:~:text=So%2C%20DST%20Root%20CA%20X3%20needs%20to%20be,The%20manual%20steps%20below%20are%20no%20longer%20necessary.
This is quite a crazy issue that appeared out of nowhere (unless you follow the openSSL blog)
Took me approx 1 day to track down, all the while no emails are being sent and large pieces of the web site not appearing.
Hope this points people in the right direction.
UPDATE: As pointed out by #hakre you may be able to get away with just ...
yum upgrade ca-certificates
Simply edit the fullchain.pem file and remove the last certificate. - if using an OS different to the accepted answer
Similar questions have been answered before, but I haven't been able to solve this particular case.
On a PHP 5.6+ machine when I try to use fsockopen on a particular domain I receive the following (not the real domain):
$ php -r "var_dump(fsockopen(\"ssl://www.domain.net\", 9085, \$errnum, \$errstr, 5));"
PHP Warning: fsockopen(): Failed to enable crypto in Command line code on line 1
PHP Warning: fsockopen(): unable to connect to ssl://www.domain.net:9085 (Unknown error) in Command line code on line 1
bool(false)
This works fine on PHP 5.5, which points to it being by the change in 5.6 dealing with the way fsockopen verifies ssl certificates.
Other connections can be made without issue:
$ php -r "var_dump(fsockopen(\"ssl://www.google.com\", 443, \$errnum, \$errstr, 5));"
resource(4) of type (stream)
Based on other suggestions I've checked the default cert file
$ php -r "print_r(openssl_get_cert_locations());"
Array
(
[default_cert_file] => /usr/lib/ssl/cert.pem
[default_cert_file_env] => SSL_CERT_FILE
[default_cert_dir] => /usr/lib/ssl/certs
[default_cert_dir_env] => SSL_CERT_DIR
[default_private_dir] => /usr/lib/ssl/private
[default_default_cert_area] => /usr/lib/ssl
[ini_cafile] =>
[ini_capath] =>
)
The file /usr/lib/ssl/cert.pem was originally missing, I download the ca bundle from curl and renamed it to match. Still no luck.
I'm not receiving any additional information indicating that verifying the certificate fails. Are there any other ways to debug the issue?
After much head bashing, I finally discovered the cause.
PHP 5.6 implemented a default set of support ciphers, which removed support for older more vulnerable ones. http://php.net/manual/en/migration56.openssl.php
The default ciphers used by PHP have been updated to a more secure list based on the » Mozilla cipher recommendations, with two additional exclusions: anonymous Diffie-Hellman ciphers, and RC4. The domain I was attempting to connected currently supports TLSv1/SSLv3, Cipher RC4-MD5
Do work around the issue I switched to stream_socket_client instead of fsockopen. Added RC4-MD5 to stream cipher support in the context:
$context = stream_context_create(['ssl' => [
'ciphers' => 'RC4-MD5'
]]);
$socket = stream_socket_client('ssl://'.$host.':'.$port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
I have simple script connection call using PHP 5.2.10 to a Web service working with SOAP 1.2.
The same PHP installation is able to connect via Web service to another web server working with SOAP 1.1 without issues. In addition, the web services using 1.2 is working fine with another two servers using almost the same hard code.
However, every time I am using SOAP 1.2 on this server with PHP 5.2.10 I got the bellow error if I run the script from a batch file:
Warning: SoapClient::SoapClient(http://www.w3.org/2005/05/xmlmime): failed to open stream: HTTP request failed! HTTP/1.1 401 Authorization Required in C: \NewSimpleConnectionTest.php on line 10
If the script is running via Eclipse PHP with PHP 5.2 on a different computer, it does not have any error so the hard code seems fine, user and password are correct too because it is used on the others servers and on the Eclipse test:
My script is this:
<?php
$_endpoint = "http://server:8080/serverv/ServerAPI";
$_username = "userServer";
$_password = "123ABC!";
try
{
$client = new SoapClient($_endpoint."?WSDL", array('location' => $_endpoint, 'login' => $_username, 'password' => $_password, 'trace' => 1, 'features' => SOAP_USE_XSI_ARRAY_TYPE + SOAP_SINGLE_ELEMENT_ARRAYS, 'soap_version' => SOAP_1_2));
echo 'Connected to Web Services.';
}catch(Exception $e){
echo 'Failure to connect to WebServices.';
}
?>
This is the information in the SOAP and XML phpinfo.
SimpleXML
Simplexml support => enabled
Revision => $Revision: 1.151.2.22.2.46 $
Schema support => enabled
soap
Soap Client => enabled
Soap Server => enabled
Directive => Local Value => Master Value
soap.wsdl_cache => 1 => 1
soap.wsdl_cache_dir => /tmp => /tmp
soap.wsdl_cache_enabled => 1 => 1
soap.wsdl_cache_limit => 5 => 5
soap.wsdl_cache_ttl => 86400 => 86400
Any idea about what is missing or the problem on this PHP version to work with SOAP 1.2 in that server?
Thanks in advance!!
After some hours working around this problem, the solution was changing the version of PHP from 5.2.10 to 5.5.28.
There is some kind of bug on this old version and prevent the correct connection with SOAP 1.2.
I hope this help someone using this old version of PHP.
Please help me fix problem on Mac OS, when I type on my windows, It works.
I try on my mac, it shows "could not open socket".
Everybody could help me.
public function indexAction(){
$mail = new Mail\Message;
$mail->setFrom('paradise.losebaby#gmail.com','Flyoverfly Training');
$mail->addTo('thanhbvh#yahoo.com.vn','maithanh');
$mail->setSubject('Xác nhận việc phục hồi mật khẩu');
$mail->setBody('maithanh');
$transport = new SmtpTransport;
$option = new SmtpOptions(array(
'name' => 'smtp.gmail.com',
'host' => 'smtp.gmail.com',
'port' => 465,
'connection_class' => 'login',
'connection_config' => array(
'username' => 'myemail#gmail.com',
'password' => 'mypass',
'ssl' => 'ssl'
)
));
$transport->setOptions($option);
$transport->send($mail);
return new ViewModel;
}
May be a firewall issue. However I'm pretty sure php-openssl doesn't installed/enabled on your OS. Under the hood Zend will call stream_socket_client() in order to connect to remote server.
As sending email through gmail requires security layer (SSL/TLS), stream_socket_client() will require open ssl support (ssl://).
So you must have ssl support on OS, check:
Or getting the list of supported socket transports:
And here goes some useful links:
Roll your own PHP to support OpenSSL instead of Secure Transport (Mac)
How to upgrade OpenSSL in OS X?
Important note for curl users on OS X Mavericks 10.9
fsockopen() (go to hostname option for details)
Can't run Composer on my Mac Mountain Lion - openssl extension
OpenSSL support in PHP under MAMP
OpenSSL Version MacOSX Homebrew
Building OpenSSL on your Mac (MacOS X)
Zend Mail Abastract Protocol (stream_socket_client under the hoods)
stream_socket_client()
OpenSSL installation
Net Transports
stream_get_transports()