J'essaie de configurer une chaîne de certificats pour un serveur de laboratoire. J'ai créé ma propre autorité de certification racine, une autorité de certification intermédiaire et un certificat de serveur. J'ai fourni ces certificats avec la clé du serveur à la commande openssl s_server. Lorsque j'exécute openssl s_client et que je me connecte à ce serveur, openssl se plaint qu'il existe un certificat auto-signé dans la chaîne.
Cependant, lorsque je me connecte à un serveur Web public à l'aide de s_client, non seulement le serveur n'envoie pas tous les certificats de la chaîne (juste le certificat parent intermédiaire du certificat de serveur), mais openssl ne se plaint pas d'un certificat auto-signé , sans parler d'une chaîne de certificats incomplète.
Si j'utilise s_server avec un fichier CA contenant uniquement le certificat intermédiaire parent du serveur, s_client se plaint de ne pas pouvoir obtenir le certificat d'émetteur local. Je ne vois jamais cette erreur avec les serveurs Web publics même s'ils n'envoient pas toute la chaîne de certificats.
Dans aucun de ces tests (en utilisant mes propres certificats ou serveurs Web publics), j'utilise les options -CApath, -CAfile ou -verify avec la commande s_client.
Je ne sais pas ce que je fais mal. Pourquoi s_client se plaint-il de ma chaîne de certificats alors que je n'utilise pas -verify? Pourquoi se plaint-il que mon certificat racine (je suppose) est auto-signé alors que tous les certificats racine sont auto-signés?
Par exemple, voici ce que j'obtiens avec un serveur Web public:
openssl s_client -showcerts -servername security.stackexchange.com -connect security.stackexchange.com:443
CONNECTED(00000004)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = *.stackexchange.com
verify return:1
---
Mais en utilisant s_server avec ma chaîne de certificats complète, j'obtiens ceci:
openssl s_client -showcerts -servername server.domain.com -connect server.domain.com:443
CONNECTED(00000004)
depth=2 C = US, ST = State, L = City, O = Company, OU = Company CA
verify error:num=19:self signed certificate in certificate chain
---
Voici mes certificats. Et oui, j'ai les contraintes CA = TRUE, Signature numérique et Signature de certificat définies dans mon autorité de certification racine.
openssl x509 -in root_ca.cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
bc:e0:9f:2a:5d:25:6e:8f
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=State, L=City, O=Company, OU=Company CA
Validity
Not Before: May 30 22:35:50 2019 GMT
Not After : May 25 22:35:50 2039 GMT
Subject: C=US, ST=State, L=City, O=Company, OU=Company CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
.........
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
2A:0A:D6:EF:96:02:70:4F:89:7A:69:C5:3E:37:47:EE:B1:E1:92:C0
X509v3 Authority Key Identifier:
keyid:2A:0A:D6:EF:96:02:70:4F:89:7A:69:C5:3E:37:47:EE:B1:E1:92:C0
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
.........
racine CA:
-----BEGIN CERTIFICATE-----
MIIDjDCCAnSgAwIBAgIJALzgnypdJW6PMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEQMA4GA1UECgwH
Q29tcGFueTETMBEGA1UECwwKQ29tcGFueSBDQTAeFw0xOTA1MzAyMjM1NTBaFw0z
OTA1MjUyMjM1NTBaMFMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTENMAsG
A1UEBwwEQ2l0eTEQMA4GA1UECgwHQ29tcGFueTETMBEGA1UECwwKQ29tcGFueSBD
QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXCAU2fb4zNVGDryN5f
H4BozBizvkSp71e5NsYa/LW4R/sEedj2k+1szT2rMRrhbkinYCxjx+qMtZ0ZTmBB
y/zbI7XsTaApLZ9f2BMYkfWWi81Plvdg/Z7Z9S5oW3Bnr5ZzhFnAQkVnL5vSbFsG
5dFJMuCUHdGwaAb6ebJCyBxJST3kEd8aog/sdGwH6NPdjel7oc9aCcfp7+Dy7T0g
ThE6vbO4qisTlw+dV+fJ2dGt11vDHc3VnHSaFbb7iuDTG3LeWgF9AhuEkf5uxHQX
zNyx3AkCL9W1keoTTZaIYkHwyTxv/ghrRgLURe8XhC9fpC3cE+wO1Tvf8nmsLEQx
mKMCAwEAAaNjMGEwHQYDVR0OBBYEFCoK1u+WAnBPiXppxT43R+6x4ZLAMB8GA1Ud
IwQYMBaAFCoK1u+WAnBPiXppxT43R+6x4ZLAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
VR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAyoV6gqDAYWs/biVv/EZ52
QMjrF93gyx8xY7PKMCYOhnzl8qjro33mMjVJLzzvmtjSZ1DHhLk0kgqw2HJJ9kNY
tzXze9h97pWPvA/4g8wQa1Pc2xuVZ7ELxs5qk1Btkgqh3C2DwGU1Vkruch0wTjG+
r28UdvjVfRObg+qx7We7dRAqk3KjXUJvKCZMu0GBYuCrWFrMR6Xc1O47UiEbzzrC
lTeEP6iZKIZI8D1iasrQdjL4CCh3E5w97Hl/NHKPuxTVqs6AdOqDoCBwrQEajO4t
2qHzVBGvTI57PzPYnvc+0fG5n0vn1Dx5SWy7Dl4+51x5vx6tNbTjqhIJnzyuh1l3
-----END CERTIFICATE-----
cA intermédiaire:
-----BEGIN CERTIFICATE-----
MIIDmzCCAoOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMCVVMx
DjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5MRAwDgYDVQQKDAdDb21wYW55
MRMwEQYDVQQLDApDb21wYW55IENBMB4XDTE5MDUzMDIyMzYwMVoXDTI5MDUyNzIy
MzYwMVowZjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMRAwDgYDVQQKDAdD
b21wYW55MRMwEQYDVQQLDApDb21wYW55IENBMSAwHgYDVQQDDBdDb21wYW55IElu
dGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMS3
OdbP2p2vzCVL7MMlSszxefWbsuw/F3t2pgqZivxTebMS8GGVhYfG39wKnJOKi/Q8
i4vUxi7RjQT/enpOmTixrG+IrGK9bg0cJg9tM2FHAMr7uGeoqIY0/02dAX1ffrBI
KP+U5jk6JhEwqG23xXg22TEtmFwYBclTZE5m11tF15FCJEV9r3ljxJlusXcdOEFn
KSrSwYyU352p+WcDuyUbqIeUDzvGpQqmndbEHM3GIo0uvxmkCXr1/Bc6QkhfAJMj
A8y+wvmyZFr1QRhX5R0udyHiwWzjgmSsZ8rDpOlcWKsmon07h+iV5EfEu/fiO1OT
ddW9xSR3oxBTyCErdVkCAwEAAaNmMGQwHQYDVR0OBBYEFHdi+4NsPyB3yTBZnsti
8QKQngr5MB8GA1UdIwQYMBaAFCoK1u+WAnBPiXppxT43R+6x4ZLAMBIGA1UdEwEB
/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBD
AeasspCf6jpj0+HyMJ9+GyF/5utKy8KOHhNMUOe+sExHvPWnEbtpKZ2gqxQpoNbz
7yFDitLPyEPk2CUNwfMW+QRfy+cqW7ci1mFc8xMo1WP2VPmojCGydZ+9IYUqQ5UE
DcMSSiGneeWhJ71oZwqE9GikPHZfLq6SEeHD3SI9+0vvv0zbcykH+yOvsaDIq+bl
G8rqX1hCs+00L6yBJZHEdz3rKviJgxT3eYkfekd65p92Ehqtzd/ZehqR5P8dM+h/
qnpZOJAvtVhOArP7GwyPcqapToXVEppFhS1nSlxDauTa1VrvzkIgHOzOR/v8EGyH
lublY3WfPEBZxdE3zKln
-----END CERTIFICATE-----
certificat de serveur:
-----BEGIN CERTIFICATE-----
MIIEpDCCA4ygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCVVMx
DjAMBgNVBAgMBVN0YXRlMRAwDgYDVQQKDAdDb21wYW55MRMwEQYDVQQLDApDb21w
YW55IENBMSAwHgYDVQQDDBdDb21wYW55IEludGVybWVkaWF0ZSBDQTAeFw0xOTA1
MzAyMjM2MDhaFw0yNDA1MjgyMjM2MDhaMIGRMQswCQYDVQQGEwJVUzEOMAwGA1UE
CAwFU3RhdGUxDTALBgNVBAcMBENpdHkxEDAOBgNVBAoMB0NvbXBhbnkxEzARBgNV
BAsMCkNvbXBhbnkgQ0ExHjAcBgNVBAMMFXNlcnZuYW1lIDE5MDUzMDE3MzYwNDEc
MBoGCSqGSIb3DQEJARYNcm9vdEBzZXJ2bmFtZTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMDHXE+tXVz+vyj2gw8Fzy9QbNFj4Xgx9hUuvSnv5rDbdh1K
B0TtQ+JfGqD3onnRUZ6vOEe5m9yfc0Kw2QnyPbEwB3MKc61I0Ls3ve4I2v6auHS0
NDdZyUtTHGlF95XL9c+UqzaOn2eaHQM4VvhhVgDAswXR4Br6m+ID0cOCmS+YHWRG
HyvRKRdKn5w7MZ3CKJ7VDgYutREfw6lwoGvgWUTNDYbgLUY26AH0lhMrMjzrp1bx
SI+2nbliGBQd/81otWD9FjnbTqBIdDKQlTyrqHJWF0ZWCjZiVJuUC1hKzBySX59R
rD7gqARDeSbhlln6LGo31BsqwoYgvvXe/26pdxECAwEAAaOCAS4wggEqMAkGA1Ud
EwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NM
IEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFGSrkvKc5psT
2b+CXmOo1CCICw5OMHwGA1UdIwR1MHOAFHdi+4NsPyB3yTBZnsti8QKQngr5oVek
VTBTMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkx
EDAOBgNVBAoMB0NvbXBhbnkxEzARBgNVBAsMCkNvbXBhbnkgQ0GCAhAAMA4GA1Ud
DwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATATBgNVHREEDDAKgghzZXJ2
bmFtZTANBgkqhkiG9w0BAQsFAAOCAQEAwlOx4gPc7UPC/FRWtsjzeTNsXXXY4zLg
NnuBw1y3YCzInLV0w97QvK+QfZ6EANgou7Wl4q3k4SodkAL9GXnfecW2EN13geGa
SP+hPqT84jqSsk5mqOYhpyKZHjXTYPUYyQ9p0dIy/Dm9dNjOvHpefsK/DRHJPkyu
NS5oZE2CTmZwnNq6w5I/53Gd0dA54F2N3v169ygKCr6WlM95lEwZgZNTLNqyyZnO
P7Kbt4ufB7u76ky3X9YvAwSwqj4VzqAm4d/xKAilHEZYWlL2Mo6FqfuXij/avoUc
OoGt/A6yzFGLBrGEJf4iQR9Iwgwo3+yZqeMHykM/e44MwCVTA6MH1g==
-----END CERTIFICATE-----
Tout d'abord, il est tout à fait correct pour un serveur TLS/SSL d'envoyer le ou les certificats de chaîne aka intermédiaires, mais pas le certificat racine; voir rfc 5246 sec 7.4.2 ou la version légèrement plus détaillée dans rfc 8446 sec 4.4.2 .
Comme Z.T. commenté correctement, -verify
est le par défaut pour s_client
(vous n'avez pas besoin de le spécifier) et si vous ne spécifiez pas -CAfile
et/ou -CApath
par défaut (sauf pour les bogues dans certaines versions obsolètes), il utilise un magasin de confiance par défaut , configuré au moment de la compilation, qui peut inclure soit un seul fichier avec des certificats PEM concaténés ou un répertoire contenant des fichiers PEM séparés avec des noms ou des liens utilisant des hachages de sujet tronqués généralement créés par c_rehash
(ajouter) ou, comme indiqué, déterminé manuellement avec x509 -hash
; voir la page de manuel pour vérifier (1ssl) sur votre système ou sur le web . OpenSSL lui-même ne fournit les certificats racine qui vont dans un tel truststore; si vous utilisez une distribution ou une autre version packagée, le constructeur généralement configure OpenSSL pour utiliser un ensemble de certificats racine fourni par la distribution ou le package . (Sur les distributions que je connais, ce magasin de clés de confiance fourni par distribution est également utilisé pour autres logiciels comprenant NSS, GNUtls et Java; voir ci-dessous.) Si vous (ou quelqu'un) avez construit OpenSSL à la main, vous devez le faire vous-même. Étant donné que vous n'obtenez pas d'erreur de vérification sur les serveurs publics, votre build utilise probablement un magasin de clés de confiance qui a (au moins une partie) l'autorité de certification publique préinstallée; vous pouvez voir où cela se trouve avec openssl version -d
(plus les noms codés en dur cert.pem
et/ou certs
).
Vous pouvez ajouter votre racine ou autre ancre (voir ci-dessous) à ce magasin de clés de confiance par défaut, ou utiliser -CAfile
et/ou -CApath
pour spécifier une racine personnalisée contenant vos propres racine (s) ou ancre (s). Sur les distributions que je connais, et probablement sur d'autres, vous ne devriez PAS modifier manuellement les fichiers par défaut car ils sont générés automatiquement par un processus qui aussi définit les magasins de confiance utilisés par d'autres logiciels tels que NSS, GNUtls et Java; ceux-ci doivent contenir les mêmes données (certificats) mais dans des formats différents. Voir plutôt par exemple man update-ca-trust
pour la famille RedHat ou man update-ca-certificates
pour la famille Debian.
OpenSSL utilisera un certificat ou certificats intermédiaires (aka chaîne) dans le magasin de clés pour construire la chaîne de certificats si nécessaire, c'est-à-dire s'il n'est pas envoyé par le serveur (en violation du RFC, mais beaucoup le font ), mais historiquement, il ne fera que - accepter une chaîne - soit entièrement reçue du serveur ou (en partie) construite à partir du truststore local - si elle se termine à un root qui se trouve dans le truststore local. Pour les versions récentes, à savoir 1.0.2 et uniquement documentées depuis 1.1.0, il existe une option -partial_chain
qui accepte une chaîne se terminant par un intermédiaire (non root) qui se trouve dans le magasin de clés de confiance local.
Concernant la chaîne complète, j'ai généré la mienne pour une utilisation avec Apache2 en utilisant:
cat intermediateCA.crt rootCA.crt > fullchain.crt
Sans tester vos circonstances exactes, je ne peux pas suggérer plus que l'ordre dans lequel le serveur Web lit la chaîne de certificats.
Pour OpenSSL indiquant que votre rootCA est auto-signé. Cela peut être dû au fait que votre rootCA n'est pas installé dans votre magasin de certificats sur le système d'exploitation (ou même un navigateur Web). L'installation d'un fichier .crt
Sur les systèmes d'exploitation peut varier, Ajout de certificats racine de confiance au serveur expliquera comment. Gardez à l'esprit que Mozilla Firefox utilise son propre magasin de certificats.
Lorsque j'ai commencé à être ma propre autorité de certification, à des fins similaires, j'ai commencé à publier mon propre rootCA en utilisant un tutoriel par Jaime Linux qui peut être plus approprié étant donné que vous émettez pour un serveur de laboratoire, comme le tutoriel explique la création d'une base de données plate pour suivre les certificats signés.