I use Net::Jabber::Client
to send messages via XMPP.
The server I am connecting to uses self-signed certificate:
DEBUG: .../IO/Socket/SSL.pm:2853: new ctx 45728400
DEBUG: .../IO/Socket/SSL.pm:1540: start handshake
DEBUG: .../IO/Socket/SSL.pm:717: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:750: using SNI with hostname my.host.name
DEBUG: .../IO/Socket/SSL.pm:785: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:806: set socket to non-blocking to enforce timeout=10
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:832: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:842: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:862: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2754: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2707: ok=0 [0] /CN=my.host.name/CN=my.host.name
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:825: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:825: local error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:828: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1963: downgrading SSL only, not closing socket
DEBUG: .../IO/Socket/SSL.pm:2875: free ctx 45728400 open=
DEBUG: .../IO/Socket/SSL.pm:2879: free ctx 45728400 callback
DEBUG: .../IO/Socket/SSL.pm:2886: OK free ctx 45728400
I have found that I can pass SSL_fingerprint
and/or SSL_verifycn_name
to pass verification of self-signed certificate.
To make it just work I hack this
my %ssl_params = (
SSL_verify_mode => $self->{SIDS}->{newconnection}->{ssl_verify},
SSL_hostname => 'my.host.name',
SSL_verifycn_name => 'my.host.name',
);
without success =(
I try to use ->get_fingerprint
to obtain finger print and pass it to SSL_fingerprint
parameter, but:
IO::Socket::SSL->start_SSL(
$self->{SIDS}->{$sid}->{sock},
$self->{SIDS}->{$sid}->{ssl_params}
) or die "$IO::Socket::SSL::SSL_ERROR";
fail with error:
SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed at
Which option to pass to IO::Socket::SSL
to verify self-signed certificate?
Using the fingerprint is probably the easiest way to verify a self-signed certificate which is in your own control. When using SSL_fingerprint
it will not care about any other kind of validations, i.e. not check the name, revocation, expiration etc anymore - so if you want to have checks for this too you should not use SSL_fingerprint
.
Getting the fingerprint of a site can be done by connecting to the site once without validation (since you have no trust in the certificate yet) and getting the fingerprint or by getting the fingerprint from the certificate directly.
To get the fingerprint by asking the server, assuming that the connection is not intercepted so that you get the correct fingerprint:
use IO::Socket::SSL;
print IO::Socket::SSL->new(
PeerHost => 'example.com:443',
# switch off validation since the certificate is not trusted yet
SSL_verify_mode => SSL_VERIFY_NONE,
)->get_fingerprint,"\n";
This currently gives sha256$642de54d84c30494157f53f657bf9f89b4ea6c8b16351fd7ec258d556f821040
which can be directly used as argument for SSL_fingerprint
.
If you have instead the certificate for the site already you can compute the fingerprint directly on it:
# get the certificate
$ openssl s_client -connect example.com:443 -servername example.com
...
-----BEGIN CERTIFICATE-----
MIIF8jCCBNqgAwIBAgIQDmTF+8I2reFLFyrrQceMsDANBgkqhkiG9w0BAQsFADBw
...
-----END CERTIFICATE-----
# take this PEM certificate and get fingerprint
$ openssl x509 -fingerprint -sha256 -noout -in cert.pem
SHA256 Fingerprint=64:2D:E5:4D:84:C3:04:94:15:7F:53:F6:57:BF:9F:89:B4:EA:6C:8B:16:35:1F:D7:EC:25:8D:55:6F:82:10:40
The shown fingerprint is practically the same as before, only written in a different way. By removing all ':' (which are only there for readability) one gets 642DE5....1040
and by prefixing it with the used hash algorithm sha256
one gets something to be usable in SSL_fingerprint
: sha256$642DE5...1040
.
To use the fingerprint then to connect to the site:
my $cl = IO::Socket::SSL->new(
PeerHost => 'example.com:443',
SSL_fingerprint => 'sha256$642DE5...1040'
);