php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #33192 failure to pass certificate in handshake of openssl related transport sockets
Submitted: 2005-05-31 03:36 UTC Modified: 2005-06-03 19:52 UTC
From: justin dot d dot allen at gmail dot com Assigned:
Status: Not a bug Package: Sockets related
PHP Version: 5.0.4(latest snapshot) OS: linux(slackware)
Private report: No CVE-ID: None
 [2005-05-31 03:36 UTC] justin dot d dot allen at gmail dot com
Description:
------------
Have been unable to get a socket_stream_client() to pass the certificate whose path is specified by stream_context_create().

also stream_socket_enable_crypto() is an unknown function.

Reproduce code:
---------------
<?php
ini_set("display_errors",1);
$fc = stream_context_create(array(
  'tls'=>array(
     'passphrase'=>'*******',
     'allow_self_signed'=>'TRUE',
     'local_cert'=>'sec.pem'
  )
));
if (!$fp = stream_socket_client("tls://host:port",$errno,$errstr,30,STREAM_CLIENT_CONNECT/*|STREAM_CLIENT_ASYNC_CONNE$
    echo "$errstr ($errno)<br />\n";
} else {   //stream_socket_enable_crypto($fp,true,STREAM_SOCKET_CRYPTO_METHOD_TLS_CLIENT);
  sleep(30);
}
?>

Expected result:
----------------
expect to get successful connection to my ssl server software and it waits for a command until sleep is complete

the sec.pem file is the result of cat cert.pem pk.pem
  this may not be the specified file format(if so docs weren't clear enough for me)

I am able to connect to my server using 
openssl s_client -connect host:port -cert cert.pem -key pk.pem
successfully

Actual result:
--------------
from the php connector I recieve 
Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure in /home/ebay/test/ssl.conector.php on line 17

from the server(which for debugging is openssl s_server -accept port -cert cert.pem -key pk.pem -Verify 1) I recieve
19447:error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate:s3_srvr.c:2004:
  get same result from custom server

the commented out stream_socket_enable_crypto call gives me
Fatal error: Call to undefined function stream_socket_enable_crypto() in /home/ebay/test/ssl.conector.php on line 20
  which I imagine is the problem 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-05-31 05:36 UTC] justin dot d dot allen at gmail dot com
line that was truncated on exapmle source is 
if (!fp = stream_sockect_client("tls://host:port",$errno,$errstr,30,STREAM_CLIENT_CONNECT/*|STREAM_CLIENT_ASYNC_CONNECT*/,$fc)) {
 [2005-05-31 07:22 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5-win32-latest.zip

stream_socket_enable_crypto() was added in PHP 5.1-dev,
it's not (and will not be) in PHP 5.0.x

 [2005-06-01 00:35 UTC] justin dot d dot allen at gmail dot com
installed php5-latest.tar.gz
am now getting the same error from server

but error from client is the same SSL error with added warnings
Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure in ssl.conector.php on line 17

Warning: stream_socket_client(): Failed to enable crypto in ssl.conector.php on line 17

Warning: stream_socket_client(): unable to connect to tls://host:port (Unknown error) in ssl.conector.php on line 17
 (0)<br />


still no certificate passed


stream_socket_enable_crypto makes no difference
 [2005-06-02 20:12 UTC] justin dot d dot allen at gmail dot com
am also able to connect with c code
#include <iostream>
#include <string>

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <openssl/ssl.h>
#include <openssl/err.h>

#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>

static int password_callback(char* buf, int num, int verify, void* data) {
   strncpy(buf, (char*)(data),num);
   buf[num -1] = '\0';
   return (strlen(buf));
}

int main() {
   char *certfile = "sec.pem";

   SSL_METHOD* meth;
   SSL_CTX* ctx;

   SSL_library_init();
   SSL_load_error_strings();

   meth=TLSv1_method();
   ctx=SSL_CTX_new(meth);

   SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
   SSL_CTX_set_cipher_list(ctx, "DEFAULT");

   if (SSL_CTX_use_certificate_chain_file(ctx,certfile) != 1)
     perror("error loading cert");

   if (SSL_CTX_use_PrivateKey_file(ctx, certfile,SSL_FILETYPE_PEM) != 1)
     perror("error loading key");

   SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)"qwerty");
   SSL_CTX_set_default_passwd_cb(ctx, password_callback);

   SSL* ssl = SSL_new(ctx);

   int sd = socket(AF_INET, SOCK_STREAM, 0);
   struct sockaddr_in sa;
   memset(&sa, '\0', sizeof(sa));
   sa.sin_family      = AF_INET;
   sa.sin_addr.s_addr = inet_addr("206.127.2.49");
   sa.sin_port        = htons(1234);
   connect(sd, (struct sockaddr*) &sa, sizeof(sa));
   getpeername(sd,(struct sockaddr*) &sa,(socklen_t*)(sizeof(sa)));

   SSL_set_fd(ssl, sd);

   SSL_set_connect_state(ssl);

   int state = SSL_do_handshake(ssl);
   if (state!=1) {
      SSL_get_error(ssl,state);
      ERR_print_errors_fp(stderr);
      return 0;
   }
   sleep(15);
   return 1;
}

which if I'm right in assuming SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) in /ext/openssl/openssl.c is the context creator should be logically the same thing.

actually I looked at the methods and if I take out the SSL_set_connect_state() and switch the method to TSLv1_client_method() I get the errors out of C... so it looks like it's in my openssl libraries...
I'm running 0.9.7g, which is the latest stable... I'll try the snapshot and see if that helps... I'll let you know if it does but after that, if it doesn't, I'll probably bug openSSL about it cause it seems to be their deal...

I will say my workaround(which I had previously thought was just different syntax) worked for me in C... but I can see where you would want to keep all CTX settings in php_SSL_new_from_context and not put them in php_openssl_setup_crypto where you set up the methods... it's alot cleaner that way
 [2005-06-02 20:48 UTC] justin dot d dot allen at gmail dot com
crap... ignore that... forgot to change SSL_do_handshake() to SSL_connect() when took out SSL_set_connect_state()... so I can connect using what seems to be the same connection method in C.
 [2005-06-03 02:54 UTC] justin dot d dot allen at gmail dot com
so I added php_error_docref displays to the certfile and passphrase GET_VER_OPT sections of php_SSL_new_from_context and recieved no display from either.

It seems that the variables aren't getting parsed, but truthfuly, I'm hacking with very broad swings on that one... and, I haven't at all looked at the inner workings of the GET_VER_OPT macro.
 [2005-06-03 07:12 UTC] wez@php.net
Looks to me like you want to be using sslv3:// instead of tls:// there (just based on your server output).
Use ssl:// for automatic v2 or v3 support.  Only use tls:// when the server can only speak tls; it's a different dialect of SSL.

The context options for openssl, including tls, are all bundled under the name "ssl".

I think your code should probably look more like this:

$c = stream_context_create(array(
   "ssl" => array(
       "local_cert" => "sec.pem",
       ... other options ...
   )
);
$s = stream_socket_client("sslv3://.....", ....., $c);


 [2005-06-03 19:04 UTC] justin dot d dot allen at gmail dot com
my testing server is 
openssl s_server -accept port -cert sec.pem -Verify 1

and my actual server was first set up to accept only tls, I changed it during testing to accept all three hoping that the problem was me being too strict

I have tried tls:// ssl:// and sslv3:// -- they all return the same error 

sslv2: returns no actual SSL error on the client, just the warnings about failed to enable crypto and unable to connect
and returns 
12058:error:140710CA:SSL routines:REQUEST_CERTIFICATE:peer error no certificate:s2_pkt.c:675:
from the server -- same error but for the sslv2 functions

I tried adding -tls1 to the end of my openssl s_server but that didn't make any difference in what happened.

I'm actually pretty sure that tls uses the sslv3 handshake functions.
 [2005-06-03 19:52 UTC] justin dot d dot allen at gmail dot com
%$#*@ so I didn't listen to you about the context settings.... that was it... I was trying to use the transport name and not ssl... it works that way for all of them... I must have forgot to change it for m tls when I tested ssl://

that was it usage error thanks though.
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Wed Jul 06 22:05:44 2022 UTC