Vérifier le code d'erreur = 20 : impossible d'obtenir le certificat de l'émetteur local
J'ai une chaîne de certificats du serveur:
Certificate chain
0 s:/******/O=Foobar International BV/OU****
i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5
2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
Et mon certificat CA racine est:
s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5
Et je suis à l'aide de cet extrait de code pour vérifier le certificat:
//gcc -lssl -lcrypto -o certverify certverify.c
#include <openssl/ssl.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <string.h>
int main() {
const char ca_bundlestr[] = "./ca-bundle.pem";
const char cert_filestr[] = "./cert-file.pem";
BIO *certbio = NULL;
BIO *outbio = NULL;
X509 *error_cert = NULL;
X509 *cert = NULL;
X509_NAME *certsubject = NULL;
X509_STORE *store = NULL;
X509_STORE_CTX *vrfy_ctx = NULL;
int ret;
/* ---------------------------------------------------------- *
* These function calls initialize openssl for correct work. *
* ---------------------------------------------------------- */
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
/* ---------------------------------------------------------- *
* Create the Input/Output BIO's. *
* ---------------------------------------------------------- */
certbio = BIO_new(BIO_s_file());
outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
/* ---------------------------------------------------------- *
* Initialize the global certificate validation store object. *
* ---------------------------------------------------------- */
if (!(store=X509_STORE_new()))
BIO_printf(outbio, "Error creating X509_STORE_CTX object\n");
/* ---------------------------------------------------------- *
* Create the context structure for the validation operation. *
* ---------------------------------------------------------- */
vrfy_ctx = X509_STORE_CTX_new();
/* ---------------------------------------------------------- *
* Load the certificate and cacert chain from file (PEM). *
* ---------------------------------------------------------- */
ret = BIO_read_filename(certbio, cert_filestr);
if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
BIO_printf(outbio, "Error loading cert into memory\n");
exit(-1);
}
ret = X509_STORE_load_locations(store, ca_bundlestr, NULL);
if (ret != 1)
BIO_printf(outbio, "Error loading CA cert or chain file\n");
/* ---------------------------------------------------------- *
* Initialize the ctx structure for a verification operation: *
* Set the trusted cert store, the unvalidated cert, and any *
* potential certs that could be needed (here we set it NULL) *
* ---------------------------------------------------------- */
X509_STORE_CTX_init(vrfy_ctx, store, cert, NULL);
/* ---------------------------------------------------------- *
* Check the complete cert chain can be build and validated. *
* Returns 1 on success, 0 on verification failures, and -1 *
* for trouble with the ctx object (i.e. missing certificate) *
* ---------------------------------------------------------- */
ret = X509_verify_cert(vrfy_ctx);
BIO_printf(outbio, "Verification return code: %d\n", ret);
if(ret == 0 || ret == 1)
BIO_printf(outbio, "Verification result text: %s\n",
X509_verify_cert_error_string(vrfy_ctx->error));
/* ---------------------------------------------------------- *
* The error handling below shows how to get failure details *
* from the offending certificate. *
* ---------------------------------------------------------- */
if(ret == 0) {
/* get the offending certificate causing the failure */
error_cert = X509_STORE_CTX_get_current_cert(vrfy_ctx);
certsubject = X509_NAME_new();
certsubject = X509_get_subject_name(error_cert);
BIO_printf(outbio, "Verification failed cert:\n");
X509_NAME_print_ex(outbio, certsubject, 0, XN_FLAG_MULTILINE);
BIO_printf(outbio, "\n");
}
/* ---------------------------------------------------------- *
* Free up all structures *
* ---------------------------------------------------------- */
X509_STORE_CTX_free(vrfy_ctx);
X509_STORE_free(store);
X509_free(cert);
BIO_free_all(certbio);
BIO_free_all(outbio);
exit(0);
}
Mais ce code de retour de sortie suivants:
Verification return code: 0
Verification result text: unable to get issuer certificate
Verification failed cert:
countryName = US
organizationName = Symantec Corporation
organizationalUnitName = Symantec Trust Network
commonName = Symantec Class 3 Secure Server CA - G4
Quel est le problème ici?
OriginalL'auteur Kaidul | 2014-12-22
Vous devez vous connecter pour publier un commentaire.
Votre autorité de certification racine utilise probablement la même clé publique comme la première autorité de certification intermédiaire dans la chaîne (ci-dessous les certificats de l'ordinateur hôte) et vous avez probablement pas de racine-CA qui peut être utilisé pour de fiducie le dernier de la chaîne de certificats. De telles installations ne sont pas très commun, mais en fait se produire. Malheureusement OpenSSL a des problèmes avec cette configuration, et ne vous essayez de vérifier le plus long de la chaîne, même si une plus courte chaîne fournit déjà la confiance nécessaire.
Il est un bug entrée pour cette OpenSSL problème, mais personne ne le OpenSSL développeurs jamais pris soin de lui. Vous pouvez également trouver un patch si vous êtes à la recherche pour X509_V_FLAG_TRUSTED_FIRST. Il semble que OpenSSL 1.0.2 (pas encore publié) ont cette option.
À partir de ma compréhension seulement OpenSSL a ce genre de problème, c'est à dire ni NSS (Firefox, Chrome sur le Bureau), ni SChannel (Microsoft).
Je suis en mesure de vérifier la date de péremption, hotname de vérification et est signé par le certificat d'autorité de certification. Mais comment puis-je obtenir des listes de révocation de certificats et de vérifier si mon serveur de certificat a été révoqué ou non. Pouvez-vous me donner des code de travail ?
Pour obtenir des listes de révocation de certificats, vous devez extraire les points de distribution CRL du certificat et ensuite faire des requêtes HTTP ne charge ces liste de révocation de certificats. Après vous avez fait cela, vous pouvez les charger et les ajouter à la vérification CTX. Et non, je n'ai pas de code de travail pour cela. En dehors de cela c'est une autre question et ainsi de mieux poser une nouvelle question.
OriginalL'auteur Steffen Ullrich
Je pense que Steffen a probablement aidé à résoudre le problème. Mais voici un petit pinaille qui peuvent avoir laissé tomber le côté bug que vous rencontrez et l'amélioration de votre posture de sécurité.
Vous n'avez pas besoin de CA bundle. Vous avez seulement besoin de Verisign Class 3 Primaire Publique de l'Autorité de Certification (G5). Vous pouvez obtenir un CA cert besoin de Verisign à L'utilisation de Certificats Racine.
Son une amélioration de votre posture de sécurité, parce que vous êtes en permettant à toute autorité de certification pour certifier que le certificat du serveur (même mal), et ne pas utiliser celui qui est connu pour certifier que le certificat du serveur (Verisign).
Si vous voulez voir un exemple d'un simple client TLS, puis vérifier SSL/TLS Client sur OpenSSL wiki. Il fournit un exemple de l'extraction de nombres aléatoires à partir de
random.org
. Il ne prendra pas beaucoup de travail pour changer enexample.com
.Notez bien: OpenSSL ne pas effectuer le nom d'hôte correspondant en cours de validation. Vous avez encore besoin de le faire vous-même si vous utilisez OpenSSL 1.0.2, 1.0.1, la version 1.0.0 et versions inférieures. OpenSSL fournit le nom d'hôte correspondant dans la version 1.1.0, mais ce n'est pas encore disponible.
L'exemple de code pour extraire les noms d'hôte du Nom Commun (CN) et sous réserve Alt Noms (SAN) dans le X. 509 certificat est fourni dans le SSL/TLS Client, mais vous aurez à condition que le réel de code correspondant.
Sur la base des informations dans les commentaires, vous avez besoin du certificat: "Symantec Classe 3 Serveur Sécurisé de CA - G5". Ci-dessous est à quoi il ressemble quand il fournit la bonne ancre, il se termine par une
Verify return code: 0 (ok)
(et pas l'erreur 20).La "Symantec Classe 3 Serveur Sécurisé de CA - G5" est l'un avec l'empreinte digitale
4e b6 d5 78 49 9b 1c cf 5f 58 1e ad 56 be 3d 9b 67 44 a5 e5
. Vous pouvez le récupérer à partir de Verisign L'utilisation de Certificats Racine.La
CAfile
option utilisée pars_client
(ci-dessous) est placé à l'intérieur des_client.c
avec un appel àSSL_CTX_load_verify_locations
. Pour un CA de certification le certificat du serveur, et non la CA Zoo (c'est à dire,cacerts.pem
).Vous pouvez vérifier les Noms autre Objet (SAN) dans le certificat avec
$ openssl s_client -connect www.smartbabymonitor.ugrow.example.com:443 | openssl x509 -text -noout
. Vous allez être OK parce que l'hôtewww.smartbabymonitor.ugrow.example.com
est répertorié dans le SAN. Vous pouvez même ajouter le-servername
option à la commande à utiliser SNI (Server Name Indication).cert-file.pem
contenir?0 s:/******/O=Foobar International BV/OU**** i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
?Par réglage de la 0e certificat de
const char cert_filestr[] = "./cert-file.pem"
et de Verisign Class 3 Primaire Publique de l'Autorité de Certification (G5)const char ca_bundlestr[] = "./ca-bundle.pem"
, le code renvoie toujoursunable to get local issuer certificate
.voir mise à jour de réponse. Je ne peux pas en double lors de l'utilisation de l'autorité de certification Verisign (G5). Vous devez utiliser
SSL_CTX_load_verify_locations
pour définir la Verisgn CA comme l'ancre de confiance de votre client.J'ai oublié de mentionner que j'ai déjà utiliser ce morceau de code - etutorials.org/Programming/secure+programmation/... pour le nom d'hôte de vérification. Donc, je pense que cette partie est d'accord 🙂 Pouvez-vous me donner quelques bon
./ca-bundle.pem
et./cert-file.pem
fichier pour travailler avec mon code ci-dessus avec quelques explications?Je garde le certificat verisign dans mon bureau et exécuté cette commande à partir du bureau
openssl s_client -showcerts -connect www.smartbabymonitor.ugrow.mysite.com:443 -CAfile VeriSign-Class3-Public-Primary-Certification-Authority-G5.pem
mais il renvoie toujourserrorcode = 20 : unable to get local issuer certificate
. Pouvez-vous s'il vous plaît dites-moi ce qui s'est passé? Aussi le chargement verisgn du certificat parSSL_CTX_load_verify_locations
devrait travailler avec le code ci-dessus?OriginalL'auteur jww