J'utilise Net::Jabber::Client pour envoyer des messages via XMPP.

Le serveur auquel je me connecte utilise un certificat auto-signé:

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

J'ai constaté que je pouvais réussir SSL_fingerprint et / ou SSL_verifycn_name pour réussir la vérification du certificat auto-signé.

Pour que cela fonctionne, je pirate ceci

my %ssl_params = (
    SSL_verify_mode => $self->{SIDS}->{newconnection}->{ssl_verify},
    SSL_hostname    => 'my.host.name',
    SSL_verifycn_name => 'my.host.name',
);

Sans succès = (

J'essaye d'utiliser ->get_fingerprint pour obtenir l'empreinte digitale et la passer au paramètre SSL_fingerprint, mais:

IO::Socket::SSL->start_SSL(
    $self->{SIDS}->{$sid}->{sock},
    $self->{SIDS}->{$sid}->{ssl_params}
) or die "$IO::Socket::SSL::SSL_ERROR";

Échouer avec erreur:

SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed at

Quelle option transmettre à IO::Socket::SSL pour vérifier le certificat auto-signé?

1
Eugen Konkov 20 nov. 2018 à 22:30

3 réponses

Meilleure réponse

L'utilisation de l'empreinte digitale est probablement le moyen le plus simple de vérifier un certificat auto-signé qui est sous votre contrôle. Lorsque vous utilisez SSL_fingerprint, il ne se souciera pas des autres types de validations, c'est-à-dire ne plus vérifier le nom, la révocation, l'expiration, etc.

Obtenir l'empreinte digitale d'un site peut être fait en se connectant au site une fois sans validation (puisque vous n'avez pas encore confiance dans le certificat) et en obtenant l'empreinte digitale ou en obtenant l'empreinte digitale directement du certificat.

Pour obtenir l'empreinte digitale en demandant au serveur, en supposant que la connexion n'est pas interceptée afin que vous obteniez l'empreinte digitale correcte:

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";

Cela donne actuellement sha256$642de54d84c30494157f53f657bf9f89b4ea6c8b16351fd7ec258d556f821040 qui peut être directement utilisé comme argument pour SSL_fingerprint.

Si vous avez déjà le certificat du site, vous pouvez directement calculer l'empreinte digitale dessus:

# 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

L'empreinte digitale affichée est pratiquement la même qu'avant, mais écrite d'une manière différente. En supprimant tous les ':' (qui ne sont là que pour la lisibilité), on obtient 642DE5....1040 et en le préfixant avec l'algorithme de hachage utilisé sha256, on obtient que quelque chose soit utilisable dans SSL_fingerprint: {{ X3}}.

Pour utiliser l'empreinte digitale puis pour vous connecter au site:

my $cl = IO::Socket::SSL->new(
    PeerHost => 'example.com:443',
    SSL_fingerprint => 'sha256$642DE5...1040'
);
2
Steffen Ullrich 23 nov. 2018 à 04:14

Cela se produit généralement lors du chiffrement via localhost, où un certificat en soi ne joue pratiquement aucun rôle.

Les modules qui impliquent IO :: Socket :: SSL peuvent être utilisés avec un paramètre supplémentaire pour éviter de planter avec «échec de la vérification du certificat».

Pour résoudre ce problème à long terme, en haut, ajoutez cette ligne:

use IO::Socket::SSL qw(SSL_VERIFY_NONE);

$smtp = Net::SMTPS->new('localhost',
   doSSL => 'starttls',
   Port => 587,
   SSL_verify_mode => SSL_VERIFY_NONE
);
0
Reto Schär 16 févr. 2020 à 22:36

IO::Socket::SSL ne peut vérifier le certificat auto-signé que s'il fait confiance au fichier d'autorité de certification que vous utilisez pour auto-signez le certificat.

Je pense que vous devez passer correctement SSL_ca_file ou SSL_ca_path à IO::Socket::SSL pour que le fichier d'autorité de certification lui soit accessible. C'est la première chose mentionnée dans les erreurs d'utilisation courantes section de IO::Socket::SSL docs.

1
pii_ke 20 nov. 2018 à 20:17