Getting info about a TLS connection in PHP - php

I'm successfully enabling encryption during an SMTP+STARTTLS transaction, but I'd like to find out some details about the TLS connection that was made. Encryption is enabled like this, after successfully opening the stream connection:
$encrypted = stream_socket_enable_crypto(
$smtp_conn,
true,
STREAM_CRYPTO_METHOD_TLS_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
);
$encrypted just contains true, which doesn't tell me much. I'm trying to find out where I can get at things like the TLS version, domain, public cert, key exchange mechanism, verification status, hash and cipher used in the connection. It must be a property of the stream the encryption is enabled on, so I've been looking in things like stream_get_meta_data but that only contains this:
[
'timed_out' => false,
'blocked' => true,
'eof' => false,
'stream_type' => 'tcp_socket/ssl',
'mode' => 'r+',
'unread_bytes' => 0,
'seekable' => false,
]
I've also looked in stream_context_get_params and stream_context_get_options but neither contain anything interesting.
In NodeJS the place to look would be in the TLS module, which contains exactly the kind of things I'm looking for.
Where might I find more TLS info from PHP?

Related

PHP SoapClient Doesn't Retrieve WSDL with Client Certificate

Other similar questions have not helped me resolve this.
I have to retrieve a WSDL file using a client certificate + private key combination from my webserver calling another external SOAP API.
$wsdl = 'https://www.example.com?wsdl';
$endpoint = 'https://www.example.com';
$sslContext = stream_context_create($contextOptions);
$options = [
'local_cert' => '/var/www/combo.pem',
'passphrase' => 'Pass1',
'cache_wsdl' => WSDL_CACHE_MEMORY,
'trace' => 1,
'stream_context' => stream_context_create([
'ssl' => [
'ciphers' => 'RC4-SHA',
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
])
];
try{
$soapClient = new SoapClient($wsdl, $options);
}
catch(Exception $e)
{
var_dump($e);
}
The error I'm getting is:
SOAP-ERROR: Parsing WSDL: Couldn't load from '..domain..' : failed to load external entity "..domain..?wsdl"
I tried numerous settings and none of them made any difference to this response. I tried no settings, empty array.
What has worked:
Establishing a raw connection via CURL, so the certificate file is fine
Retrieving WSDL information from SoapUI, so the WSDL destination is correct and the certificate file was okay
phpinfo() returns SoapClient is enabled, OpenSSL is enabled. What else could I try or check?
SOAP error could come from invalid character encoding or maybe some HTTP header missing like 'User-Agent' when you query the remote server.
Try to adding User-Agent to options like the sample below.
$options = array(
'http' => array(
'user_agent' => 'PHP_Embedded_Soap_Client'
)
);
PS: I would not recommend to strict ciphers to: RC4-SHA
I wanted to comment this but based on others' suggestions of using file_get_contents and your reply mentioning that it returned false, I'm now kind of sure it's more of a connection problem. Please check followings:
It's obvious that your actual $wsdl value is different than what is posted but please make sure that .com?wsdl is not happening in your code. it should be .com/?wsdl.
Check your DNS settings. A lookup through dnslookup can help identify problem.
Make sure date & time setting of server is correct. It can lead to SSL errors.
If none of above helped. You might consider downloading WSDL content with other tools (such as cURL) and on different machines to identify the cause of problem.

How to encrypt each soap request in php

I'm unable to make an encrypted SOAP request in PHP. As per the documentation, I encrypted each request to the payment gateway. I generated a CSR & sent it to the authority for the certificate. They sent back me the domain certificate & CA certificate. The biggest problem is that the documentation is not meant for PHP. As per the document:
The web service is protected with WS-Security Sign and encryption
policy
After searching a long time I found a helper class from Git but whenever I try to connect I get the following error:
General security error (No certificates were found for decryption (KeyId))
FaultCode : wsse:InvalidSecurity
I tried to set SSL header as follows:
$contextOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'cafile' => '../../certs/CA.cer',
'local_cert' => '../../certs/server.cer',
'local_pk' => '../../certs/private_key.key',
'verify_depth' => 0,
'allow_self_signed'=>true,
)
);
$sslContext = stream_context_create($contextOptions);
Update
I defined the keys as :
define('PRIVATE_KEY', 'server_prvate_key.key');
define('CERT_FILE', 'domain_cert.cer');
define('SERVICE_CERT', 'CA.cer');
Anything wrong with this definition (please see the above GIT link)?
Are you tried using curl?
Use the following option to set your certificate:
curl_setopt($ch,CURLOPT_CAINFO, 'CA.cer' );
curl_setopt($ch,CURLOPT_SSLCERT, 'domain_cert.cer' );
curl_setopt($ch,CURLOPT_SSLKEY, 'server_prvate_key.key' );
curl_setopt($ch,CURLOPT_SSLCERTPASSWD, 'certificate_password' ); //if have
I use encrypted connection to payment gateways and other services using curl and works like a charm.

Unable to obtain token using Abraham's TwitterOAuth for PHP; HTTP 500 returned

I am attempting to use #abraham's TwitterOAuth 0.5.3 library for PHP, but when I make a request to request a token for the 3-legged authorization, I receive an HTTP 500 as a response.
Here is how I have the code set up in PHP:
<?php
/* Start session and load library. */
session_start();
require_once('config.php');
require_once('twitteroauth/autoload.php');
use Abraham\TwitterOAuth\TwitterOAuth;
/* Build TwitterOAuth object with client credentials. */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
/* Get temporary credentials. */
// Error occurs on the following line, unable to dump $request_token
$request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));
//print_r($request_token); // <-- Never reached!!
I know that this problem is not within the Twitter API, as I have verified that I can access my Twitter account via the Dev console.
In addition, I have verified to some degree that the TwiterOAuth library is working, by following the Authorization flow example provided with the library. The example can also access my Twitter account.
I just can't figure out what is going on as I am unable to properly authorize my PHP application to have access to my Twitter account.
What am I doing wrong?
It turns out that a response was never obtained. As a result, attempting to process a response, when there was none resulted in errors on the server side.
One of the PHP functions that Twitter OAuth relies upon is curl. I had tested to see if curl_init existed:
print function_exists('curl_init') ? 'curl_init is enabled' : 'curl_init is disabled';
and I erroneously assumed that curl_exec was also enabled. (Why would you leave curl_init enabled, but only disable curl_exec?)
That assumption was incorrect as my web hosting provider has disabled curl_exec "due to security concerns" and I was unaware of this. In addition, my call to use the Twitter API has worked in the past, so this was new behavior.
It took me a while to come back to testing curl_exec. I verified that I was receiving a valid TwitterOauth object and eventually wound my way into the TwitterOauth class and into the request function.
I was receiving no curl error, but was the response from curl_exec was null (not TRUE or FALSE as expected). I thought that this was unusual and at first thought that curl was missing a configuration option.
However, it was not.
So, if you run into problems with this library (which has worked great for me in the past), it may be that your hosting provider disabled curl_exec.
You can test this scenario via the following PHP code:
print function_exists('curl_exec') ? 'curl_exec is enabled' : 'curl_exec is disabled';
My problem was fixed in another way. After checking (as per jhenderson2099 answer) that my hosting had curl_exec enabled (which it did). I found out that my problem was caused by two lines in src/TwitterOauth.php (TwitterOauth class):
$bundlePath = CaBundle::getSystemCaRootBundlePath(); <-- Comment this line
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
$this->curlCaOpt($bundlePath) => $bundlePath,<-- Comment this line
];
so that your code will look like this:
//$bundlePath = CaBundle::getSystemCaRootBundlePath();
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
//$this->curlCaOpt($bundlePath) => $bundlePath,
];

PHPCrawl fails to create SSL socket

I'm trying to use PHPCrawl (http://sourceforge.net/projects/phpcrawl/) to trawl a website delivered over HTTPS.
I can see that there is support for SSL in the PHPCrawlerHTTPRequest class (openSocket method):
// If ssl -> perform Server name indication
if ($this->url_parts["protocol"] == "https://")
{
$context = stream_context_create(array('ssl' => array('SNI_server_name' => $this->url_parts["host"])));
$this->socket = #stream_socket_client($protocol_prefix.$ip_address.":".$this->url_parts["port"], $error_code, $error_str,
$this->socketConnectTimeout, STREAM_CLIENT_CONNECT, $context);
}
The problem lies in the call to stream_socket_client - although it returns a zero error_code, and no error_str, this->socket is still false.
The documentation for the method states the following:
If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call.
(See http://php.net/manual/en/function.stream-socket-client.php)
So I've tried to use an example provided in the comments section to modify the stream context using 'stream_context_set_option' to set verify_host and verify_peer to false - neither of which seems to have any effect.
I'm not very proficient in PHP or the intricacies of web - does anyone know either:
What condition (specifically) can cause this call to fail?
OR
A workaround for the issue?
I should note - I am using Facebook (HTTPS) as the test server.
I've found the issue -
PHP versions 5.6.x turn peer verification on by default, and apparently the necesarry cert isn't found sometimes (see this bug report)
The workaround is to drop back to a PHP version prior to 5.6
Old topic, but I had the same problem using the PHPCrawler. What worked for me, is what an user wrote on sourceforge (Source: https://sourceforge.net/p/phpcrawl/bugs/86/#5993).
What you have to do, is to rewrite the stream_context_create call on line 547 in PHPCrawlerHTTPReqeust.class.php into the following:
$context = stream_context_create(array(
'ssl' => array(
'SNI_server_name' => $this->url_parts["host"],
'verify_peer' => false,
'verify_peer_name' => false,
)
));
Hope this helps someone in the future.

SOAP Request over https fails everytime

my first time doing a SOAP Request fails and fails again.
I have to send some Data via SOAP but i dont get a stable connection.
I use the SOAP Extension of PHP. My Code looks like the following.
$certificate = file_get_contents(DATA_PATH.'/modules/va/misc/CKTC.cer');
$options = array(
'uri' => 'https://data2.kroschke.net/service/MeinAutoUeberfuehrungen',
'allow_self_signed' => true,
'verify_peer' => true,
'local_cert' => $certificate,
'trace' => 1,
'exceptions' => true,
);
$wsdl = 'https://data2.kroschke.net/service/MeinAutoUeberfuehrungen?WSDL';
$SOAPClient = new SoapClient($wsdl, $options);
fb($SOAPClient->__getFunctions());
Now my Problem is, that the SOAP Request always runs into a timeout.
I checked my php settings and SOAP and OpenSSL are activated.
I also tried it with a .pem instead of a .cer File. Same Problem.
This is what i get all the time:
Warning: SoapClient::SoapClient(https://data2.kroschke.net/service/MeinAutoUeberfuehrungen?WSDL): failed to open stream: Connection timed out in
Anyone who can help?
PS: Dont mind the fb() Function. Just a function to print everything into FireBug.
just try to open https://data2.kroschke.net or https://data2.kroschke.net/service/MeinAutoUeberfuehrungen?WSDL in you browser: you'll get a timeout, too.
the best solution would be to get in contact with the provider of that soap-server (kroschke.com/kroschke.de ?) and ask them why their server is down or seems to hang.
EDIT:
this doesn't seem to be the problem, so your only option is to set the timeout to a higher value. for this, just add connection_timeout (value in seconds) to your options:
$options = array(
'uri' => 'https://data2.kroschke.net/service/MeinAutoUeberfuehrungen',
'allow_self_signed' => true,
'verify_peer' => true,
'local_cert' => $certificate,
'trace' => 1,
'exceptions' => true,
'connection_timeout'=> 30
);
if it still times out, set the value even higher - if it still times out then, try to test the soap-communication with a program like soapUI before implementing it with PHP - if you get problems with soapUI, too, contact the provider of that soap-server and ask why their methods take such a long time.
for more information, take a look at the soapclient and it's options.

Categories