noxxi / p5-io-socket-ssl

IO::Socket::SSL Perl Module
36 stars 60 forks source link

SSL_verify_callback sometimes gets the same cert multiple times. #27

Closed jpouellet closed 9 years ago

jpouellet commented 9 years ago

Not sure what causes it...

Versions of stuff:

Consider the following:

#!/usr/bin/env perl
use strict;
use warnings;
use File::Basename;
use IO::Socket::SSL;

die "Usage: ".basename($0)." host:port\n" unless @ARGV eq 1;
IO::Socket::SSL->new(
    PeerHost => $ARGV[0],
    SSL_verify_callback => sub {
        my $cert = $_[4];
        my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert));
        my $issuer  = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert));
        print "# $subject (issuer=$issuer)\n";
        print Net::SSLeay::PEM_get_string_X509($cert);
        return 1;
    }
) or die $SSL_ERROR||$!;
$ dump_cert_chain.pl bugs.otr.im:443
# /OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.otr.im (issuer=/C=FR/ST=Paris/L=Paris/O=Gandi/CN=Gandi Standard SSL CA 2)
-----BEGIN CERTIFICATE-----
MIIF6zCCBNOgAwIBAgIRAOHZg+yKPfZmVepOJPSBHowwDQYJKoZIhvcNAQELBQAw
XzELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBhcmlzMQ4wDAYDVQQHEwVQYXJpczEO
MAwGA1UEChMFR2FuZGkxIDAeBgNVBAMTF0dhbmRpIFN0YW5kYXJkIFNTTCBDQSAy
MB4XDTE1MDMwOTAwMDAwMFoXDTE2MDMyMzIzNTk1OVowXDEhMB8GA1UECxMYRG9t
YWluIENvbnRyb2wgVmFsaWRhdGVkMSQwIgYDVQQLExtHYW5kaSBTdGFuZGFyZCBX
aWxkY2FyZCBTU0wxETAPBgNVBAMUCCoub3RyLmltMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAxfZUm9e16vo+pVLyc0QIqKzpSuV/pYSWlEHlYHMMBGaq
j4jy584zenIigynw9pqfaLDnqxtWVoXXJpykWucOlM82kZL8nU/jgsbqxW9WqSkg
K3ZSlJlNn95g3vGjwHsZer6X32uIvaoyAafLgKQLQ7SP/AWIyHtN02B1AcjYcJAu
anX+QRSH/3qhKt8w2ahpzQi9Wbu3Y7WycHEAGCg9jAP6OeUL2eICZoV2b+JQv2ZH
GlrHpfZBl/eTCekB/geMBGxdfR4Kr5KMRjS5yiIxLguLR/RhlVaLMmvLQ8fPUF76
3+GVZLO1No3KA2m2AMDaQxOgFDboUTvgDzPKfZnsvU3yV91a1gnwHGR1c8YTgy9u
Iow7gJhuHzgPlYvES8vFEiu8vq+NJb5ZjpFkvQlIWEmUfQ4ghWd6s5TbMTC9Zn9R
U2XnfY5BFYj600CF42FTgFb8rANGFv8CRhBJ3TFWwrMXtZ2jGWhAWyvlKXjHj08k
SbyRUc33FJNJdPo1SNKLJWDoe0gxI7pdNpN/2gW8+DkcHiMA4Nebp5Px4ud2tEQ4
J3bimiRJGPKZbHOYPlZNTt5uRUyFcqcaZrb+9agC4/zCkoZ9Bc55hd7NZ5hLVIqd
oGcVOW4joXdfZrw1lJywB39HihzNgLmD2orZw7QNBfqFdd7RtUW6ojkQOJJ777UC
AwEAAaOCAaMwggGfMB8GA1UdIwQYMBaAFLOQp9jJr07NYTyffK1df0H9aTDqMB0G
A1UdDgQWBBSZNGT6DNmuu4sTNJoNe4I8S6xCQjAOBgNVHQ8BAf8EBAMCBaAwDAYD
VR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwSwYDVR0g
BEQwQjA2BgsrBgEEAbIxAQICGjAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nwcy51
c2VydHJ1c3QuY29tMAgGBmeBDAECATBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8v
Y3JsLnVzZXJ0cnVzdC5jb20vR2FuZGlTdGFuZGFyZFNTTENBMi5jcmwwcwYIKwYB
BQUHAQEEZzBlMDwGCCsGAQUFBzAChjBodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20v
R2FuZGlTdGFuZGFyZFNTTENBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3Nw
LnVzZXJ0cnVzdC5jb20wGwYDVR0RBBQwEoIIKi5vdHIuaW2CBm90ci5pbTANBgkq
hkiG9w0BAQsFAAOCAQEALMn5fjOcn8lHRIxZlQ5ZGgChQswOIBRhpaCtyiXzP5Yu
bEbCGjYt9pUKrQQ+qb+MSZKgYMyfZaaEJMCtgPk5V47zK8jFcqaSmL7uuWOT3RRH
e1aoRdpyCTW2SEq04RsxhajVhp2xnNspf6eKhMRzZAqsgYsTPQBs+kvbl7yLv8uT
B+oCdI3MJ92De6TqrI/Z00blNwd7I13TgvasUyGSPfbkGxu5THSNvCV1Dbu+9Oql
Hf97UBELSTQpcApYJzIQ9lksShH2kalN41l9dqVgiXD6OfWfW7EUTpGYd4BGa1yg
2lIHlKN15Echdzhu2o2BFhbJH978+wgZHBH6chhxJw==
-----END CERTIFICATE-----
# /OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.otr.im (issuer=/C=FR/ST=Paris/L=Paris/O=Gandi/CN=Gandi Standard SSL CA 2)
-----BEGIN CERTIFICATE-----
MIIF6zCCBNOgAwIBAgIRAOHZg+yKPfZmVepOJPSBHowwDQYJKoZIhvcNAQELBQAw
XzELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBhcmlzMQ4wDAYDVQQHEwVQYXJpczEO
MAwGA1UEChMFR2FuZGkxIDAeBgNVBAMTF0dhbmRpIFN0YW5kYXJkIFNTTCBDQSAy
MB4XDTE1MDMwOTAwMDAwMFoXDTE2MDMyMzIzNTk1OVowXDEhMB8GA1UECxMYRG9t
YWluIENvbnRyb2wgVmFsaWRhdGVkMSQwIgYDVQQLExtHYW5kaSBTdGFuZGFyZCBX
aWxkY2FyZCBTU0wxETAPBgNVBAMUCCoub3RyLmltMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAxfZUm9e16vo+pVLyc0QIqKzpSuV/pYSWlEHlYHMMBGaq
j4jy584zenIigynw9pqfaLDnqxtWVoXXJpykWucOlM82kZL8nU/jgsbqxW9WqSkg
K3ZSlJlNn95g3vGjwHsZer6X32uIvaoyAafLgKQLQ7SP/AWIyHtN02B1AcjYcJAu
anX+QRSH/3qhKt8w2ahpzQi9Wbu3Y7WycHEAGCg9jAP6OeUL2eICZoV2b+JQv2ZH
GlrHpfZBl/eTCekB/geMBGxdfR4Kr5KMRjS5yiIxLguLR/RhlVaLMmvLQ8fPUF76
3+GVZLO1No3KA2m2AMDaQxOgFDboUTvgDzPKfZnsvU3yV91a1gnwHGR1c8YTgy9u
Iow7gJhuHzgPlYvES8vFEiu8vq+NJb5ZjpFkvQlIWEmUfQ4ghWd6s5TbMTC9Zn9R
U2XnfY5BFYj600CF42FTgFb8rANGFv8CRhBJ3TFWwrMXtZ2jGWhAWyvlKXjHj08k
SbyRUc33FJNJdPo1SNKLJWDoe0gxI7pdNpN/2gW8+DkcHiMA4Nebp5Px4ud2tEQ4
J3bimiRJGPKZbHOYPlZNTt5uRUyFcqcaZrb+9agC4/zCkoZ9Bc55hd7NZ5hLVIqd
oGcVOW4joXdfZrw1lJywB39HihzNgLmD2orZw7QNBfqFdd7RtUW6ojkQOJJ777UC
AwEAAaOCAaMwggGfMB8GA1UdIwQYMBaAFLOQp9jJr07NYTyffK1df0H9aTDqMB0G
A1UdDgQWBBSZNGT6DNmuu4sTNJoNe4I8S6xCQjAOBgNVHQ8BAf8EBAMCBaAwDAYD
VR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwSwYDVR0g
BEQwQjA2BgsrBgEEAbIxAQICGjAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nwcy51
c2VydHJ1c3QuY29tMAgGBmeBDAECATBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8v
Y3JsLnVzZXJ0cnVzdC5jb20vR2FuZGlTdGFuZGFyZFNTTENBMi5jcmwwcwYIKwYB
BQUHAQEEZzBlMDwGCCsGAQUFBzAChjBodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20v
R2FuZGlTdGFuZGFyZFNTTENBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3Nw
LnVzZXJ0cnVzdC5jb20wGwYDVR0RBBQwEoIIKi5vdHIuaW2CBm90ci5pbTANBgkq
hkiG9w0BAQsFAAOCAQEALMn5fjOcn8lHRIxZlQ5ZGgChQswOIBRhpaCtyiXzP5Yu
bEbCGjYt9pUKrQQ+qb+MSZKgYMyfZaaEJMCtgPk5V47zK8jFcqaSmL7uuWOT3RRH
e1aoRdpyCTW2SEq04RsxhajVhp2xnNspf6eKhMRzZAqsgYsTPQBs+kvbl7yLv8uT
B+oCdI3MJ92De6TqrI/Z00blNwd7I13TgvasUyGSPfbkGxu5THSNvCV1Dbu+9Oql
Hf97UBELSTQpcApYJzIQ9lksShH2kalN41l9dqVgiXD6OfWfW7EUTpGYd4BGa1yg
2lIHlKN15Echdzhu2o2BFhbJH978+wgZHBH6chhxJw==
-----END CERTIFICATE-----
$

Note that it's the same cert twice. (Sometimes I get it 3 times.)

And for reference:

$ openssl s_client -showcerts -connect bugs.otr.im:443 < /dev/null
CONNECTED(00000003)
depth=0 OU = Domain Control Validated, OU = Gandi Standard Wildcard SSL, CN = *.otr.im
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, OU = Gandi Standard Wildcard SSL, CN = *.otr.im
verify error:num=21:unable to verify the first certificate
verify return:1

---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.otr.im
   i:/C=FR/ST=Paris/L=Paris/O=Gandi/CN=Gandi Standard SSL CA 2
-----BEGIN CERTIFICATE-----
MIIF6zCCBNOgAwIBAgIRAOHZg+yKPfZmVepOJPSBHowwDQYJKoZIhvcNAQELBQAw
XzELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBhcmlzMQ4wDAYDVQQHEwVQYXJpczEO
MAwGA1UEChMFR2FuZGkxIDAeBgNVBAMTF0dhbmRpIFN0YW5kYXJkIFNTTCBDQSAy
MB4XDTE1MDMwOTAwMDAwMFoXDTE2MDMyMzIzNTk1OVowXDEhMB8GA1UECxMYRG9t
YWluIENvbnRyb2wgVmFsaWRhdGVkMSQwIgYDVQQLExtHYW5kaSBTdGFuZGFyZCBX
aWxkY2FyZCBTU0wxETAPBgNVBAMUCCoub3RyLmltMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAxfZUm9e16vo+pVLyc0QIqKzpSuV/pYSWlEHlYHMMBGaq
j4jy584zenIigynw9pqfaLDnqxtWVoXXJpykWucOlM82kZL8nU/jgsbqxW9WqSkg
K3ZSlJlNn95g3vGjwHsZer6X32uIvaoyAafLgKQLQ7SP/AWIyHtN02B1AcjYcJAu
anX+QRSH/3qhKt8w2ahpzQi9Wbu3Y7WycHEAGCg9jAP6OeUL2eICZoV2b+JQv2ZH
GlrHpfZBl/eTCekB/geMBGxdfR4Kr5KMRjS5yiIxLguLR/RhlVaLMmvLQ8fPUF76
3+GVZLO1No3KA2m2AMDaQxOgFDboUTvgDzPKfZnsvU3yV91a1gnwHGR1c8YTgy9u
Iow7gJhuHzgPlYvES8vFEiu8vq+NJb5ZjpFkvQlIWEmUfQ4ghWd6s5TbMTC9Zn9R
U2XnfY5BFYj600CF42FTgFb8rANGFv8CRhBJ3TFWwrMXtZ2jGWhAWyvlKXjHj08k
SbyRUc33FJNJdPo1SNKLJWDoe0gxI7pdNpN/2gW8+DkcHiMA4Nebp5Px4ud2tEQ4
J3bimiRJGPKZbHOYPlZNTt5uRUyFcqcaZrb+9agC4/zCkoZ9Bc55hd7NZ5hLVIqd
oGcVOW4joXdfZrw1lJywB39HihzNgLmD2orZw7QNBfqFdd7RtUW6ojkQOJJ777UC
AwEAAaOCAaMwggGfMB8GA1UdIwQYMBaAFLOQp9jJr07NYTyffK1df0H9aTDqMB0G
A1UdDgQWBBSZNGT6DNmuu4sTNJoNe4I8S6xCQjAOBgNVHQ8BAf8EBAMCBaAwDAYD
VR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwSwYDVR0g
BEQwQjA2BgsrBgEEAbIxAQICGjAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nwcy51
c2VydHJ1c3QuY29tMAgGBmeBDAECATBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8v
Y3JsLnVzZXJ0cnVzdC5jb20vR2FuZGlTdGFuZGFyZFNTTENBMi5jcmwwcwYIKwYB
BQUHAQEEZzBlMDwGCCsGAQUFBzAChjBodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20v
R2FuZGlTdGFuZGFyZFNTTENBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3Nw
LnVzZXJ0cnVzdC5jb20wGwYDVR0RBBQwEoIIKi5vdHIuaW2CBm90ci5pbTANBgkq
hkiG9w0BAQsFAAOCAQEALMn5fjOcn8lHRIxZlQ5ZGgChQswOIBRhpaCtyiXzP5Yu
bEbCGjYt9pUKrQQ+qb+MSZKgYMyfZaaEJMCtgPk5V47zK8jFcqaSmL7uuWOT3RRH
e1aoRdpyCTW2SEq04RsxhajVhp2xnNspf6eKhMRzZAqsgYsTPQBs+kvbl7yLv8uT
B+oCdI3MJ92De6TqrI/Z00blNwd7I13TgvasUyGSPfbkGxu5THSNvCV1Dbu+9Oql
Hf97UBELSTQpcApYJzIQ9lksShH2kalN41l9dqVgiXD6OfWfW7EUTpGYd4BGa1yg
2lIHlKN15Echdzhu2o2BFhbJH978+wgZHBH6chhxJw==
-----END CERTIFICATE-----
 1 s:/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
   i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
-----BEGIN CERTIFICATE-----
MIIEozCCA4ugAwIBAgIQWrYdrB5NogYUx1U9Pamy3DANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
SGFyZHdhcmUwHhcNMDgxMDIzMDAwMDAwWhcNMjAwNTMwMTA0ODM4WjBBMQswCQYD
VQQGEwJGUjESMBAGA1UEChMJR0FOREkgU0FTMR4wHAYDVQQDExVHYW5kaSBTdGFu
ZGFyZCBTU0wgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2VD2l
2w0ieFBqWiOJP5eh1AcaqVgIm6AVwzK2t/HouaVvrTf2bnEbtHUtSF6fxhWqge/l
xIiVijpsd8y1zWXkZ+VzyVBSlMEnST6ga0EWQbaUmUGuPsviBkYJ6U2+yUxVqRh+
pt9u/UqyzGxO2chQFZOz8unjwmqtOtX7w3lQnyV5KbJHZHwgPuIITZMpFLY0bs9x
Rn52EPT9bKoB0sIG3pKDzFiQLpLeHmW3Yy89sutwjEzgvhWd3sFNVvgLxo4HuV3f
lfB7QB8aLNecK0t29Fn1Q8EsZhCenmaWYJ0cdBtOGFwIsG5symkaAum7ynjvZi7j
Mv1BXJV0gU302v5LAgMBAAGjggE+MIIBOjAfBgNVHSMEGDAWgBShcl8mGyiYQ5Vd
BzfVhZadS9LDRTAdBgNVHQ4EFgQUtqj/oqgv0KbNS7Fo8+dQEDGneSEwDgYDVR0P
AQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYDVR0gBBEwDzANBgsrBgEE
AbIxAQICGjBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vY3JsLnVzZXJ0cnVzdC5j
b20vVVROLVVTRVJGaXJzdC1IYXJkd2FyZS5jcmwwdAYIKwYBBQUHAQEEaDBmMD0G
CCsGAQUFBzAChjFodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVROQWRkVHJ1c3RT
ZXJ2ZXJfQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3Qu
Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAZU78DPZvia1r9ukkfT+zhxoI5PNIDBA+r
ez6CqYUQH/TeMq9YP/9w8zAdly1MmuLsDD4ULS+YSJ2uFmqsLUKqtWSkcLvrc5R7
RkznehR2W0wdhKEgdB8uS1xwiNy99xk97VkN4j8m4pyspDyVHPi+jAOu8OWcTbzH
m1gAv6+t+jducW0YNA7B6mr4Dd9pVFYV8iiz/qRj7MUEZGC7/irw9IehsK69quQv
4wMLL2ZfhaQye0btJQzn8bfnGf1gul+Hd96YB5bkXupjfajeVdphXDyQg0MEBzzd
8/ifBlIK3se2e4/hEfcEejX/arxbx1BJCHBvlEPNnsdw8dvQbdqP
-----END CERTIFICATE-----
 2 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
-----BEGIN CERTIFICATE-----
MIIEhjCCA26gAwIBAgIQUkIGSk83/kNpSHqWZ/9dJzANBgkqhkiG9w0BAQUFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
eHRlcm5hbCBDQSBSb290MB4XDTA1MDYwNzA4MDkxMFoXDTIwMDUzMDEwNDgzOFow
gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
LUhhcmR3YXJlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0
qH/POYJRZ9Btn9L/WPPnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjnt
KxPNZuuVCTOkbJex6MbswXV5nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdr
ooj7AN/+GjF3DJoBerEy4ysBBzhuw6VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgX
vIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4JM5spDUYPjMxJNLBpUb35Bs1orWZM
vD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9BupNAeFosU4XZEA39jrOTN
SZzFkvSrMqFIWwIDAQABo4H0MIHxMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8D
veAky1QaMB0GA1UdDgQWBBShcl8mGyiYQ5VdBzfVhZadS9LDRTAOBgNVHQ8BAf8E
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBgNVHSAECjAIMAYGBFUdIAAwewYDVR0f
BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQWRkVHJ1c3RFeHRl
cm5hbENBUm9vdC5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BZGRU
cnVzdEV4dGVybmFsQ0FSb290LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAYGQ5WaJD
ZS79+R/WrjO76FMTxIjuIxpszthkWVNTkOg239T88055L9XmjwzvKkFtcb2beDgj
03BLhgz9EqciYhLYzOBR7y3lzQxFoura7X7s9zKa5wU1Xm7CLGhonf+M8cpVh8Qv
sUAG3IQiXG2zzdGbGgozKGYWDL0zwvYH8eOheZTg+NDQ099Shj+p4ckdPoaEsdtf
7uRJQ8E5fc8vlqd1XX5nZ4TlWSBAvzcivwdDtDDhQ4rNA11tuSnZhKf1YmOEhtY3
vm9nu/9iVzmdDE2yKmE9HZzvmncgoC/uGnKdsJ2/eBMnBwpgEZP1Dy7J72skg/6b
kLRLaIHQwvrgPw==
-----END CERTIFICATE-----

---
Server certificate
subject=/OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.otr.im
issuer=/C=FR/ST=Paris/L=Paris/O=Gandi/CN=Gandi Standard SSL CA 2

---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits

---
SSL handshake has read 4825 bytes and written 474 bytes

---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: E67A63468B999C6CA41186D080ABA061A460160C222576E7FAE5B56679C53BB3
    Session-ID-ctx:
    Master-Key: 22DAF517196E6A24224A690554D569D60F1168DB27C62C23436C089DE9807F007A394E711B8476BF44167DC35633232F
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - dd ed 8f 5f 20 86 ba fe-f0 ab 3f 30 45 d5 63 59   ..._ .....?0E.cY
    0010 - b7 9a 45 b2 99 3b 8a 3a-d6 3c 16 48 9b a5 84 44   ..E..;.:.<.H...D
    0020 - c4 26 a8 e9 39 83 bc 54-08 55 fe 38 35 43 ab 42   .&..9..T.U.85C.B
    0030 - 48 42 f1 62 77 5f b6 5d-fe d3 2b 84 5e de ca ed   HB.bw_.]..+.^...
    0040 - c9 4e 0a 49 ed 1b 6c 72-d8 21 1e 86 7a 30 45 d3   .N.I..lr.!..z0E.
    0050 - c7 b9 2a 8f 4e 03 cb 42-0a c5 f4 d2 15 c4 a3 b0   ..*.N..B........
    0060 - 04 1c ed ac 20 7d 9f 4d-27 48 b3 6d 60 90 c5 1a   .... }.M'H.m`...
    0070 - 09 5c 21 02 20 c8 4d 87-c9 85 de 5c 90 32 bc 20   .\!. .M....\.2.
    0080 - b3 65 7d 3c ec dc 5b 9b-1a 17 c7 cb 4d 41 b3 d3   .e}<..[.....MA..
    0090 - 79 c6 10 6d 4f 0e 57 cc-f3 29 0d b4 bd 0d b2 d8   y..mO.W..)......
    00a0 - 59 2c 6e ca dc f1 70 ec-10 f9 dd 16 55 2a ae 35   Y,n...p.....U*.5
    00b0 - 3a c8 25 4b 31 de 4d cc-c7 0c 47 33 a2 bc 66 b1   :.%K1.M...G3..f.

    Start Time: 1427146263
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)

---
DONE
$
noxxi commented 9 years ago

The verify_callback is called whenever OpenSSL needs to verify the certificate. There are various places in the OpenSSL code where it needs to verify the certificate, that is not only when it validates the chain but also when it checks the purpose etc. For more specific information I must refer you to the source code of OpenSSL. But you can see from the openssl s_client output that calling the verify_callback multiple times is not specific to IO::Socket::SSL but happens with openssl s_client too:

depth=0 OU = Domain Control Validated, OU = Gandi Standard Wildcard SSL, CN = *.otr.im
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, OU = Gandi Standard Wildcard SSL, CN = *.otr.im
verify error:num=21:unable to verify the first certificate
verify return:1

Apart from that the leaf certificate does not match the sent certificate chain, that is something is messed up with the configuration of the server.