Comment puis-je faire apache demander un certificat SSL client sans avoir besoin de le vérifier par rapport à une autorité de certification connue?

9

J'utilise apache2 (2.2.3) pour servir un site où j'aimerais que les clients s'authentifient avec des certificats. Étant donné que je dois seulement vérifier qu'un utilisateur présentant un certificat particulier est le même utilisateur qui a présenté ce certificat dans le passé, l'autorité de certification qui signe le certificat n'est pas pertinente. Il semble cependant que l'utilisation de SSLVerifyClient requirerequiert SSLCACertificateFile ...(ou SSLCACertificatePath ...), puis apache n'acceptera que les certificats signés par une autorité de certification dans ce fichier / chemin. Existe-t-il un moyen pour apache d'accepter un certificat client, quelle que soit l'autorité de certification émettrice / chantante? (c.-à-d. vérifier que le client possède la clé privée correspondante à la clé publique présentée, mais pas la peine de vérifier l'AC émettrice / signataire)

Isaac
la source
Comment prévoyez-vous de suivre les certificats authentifiés?
Shane Madden
@ShaneMadden: quelque chose comme une table mappant les certificats aux ID utilisateur internes. La mécanique de la cryptographie à clé publique remplacerait un échange de mots de passe.
Isaac
2
Droit - ce que je veux dire est que Apache n'a pas fait un certificat de mappage de table à ID utilisateur internes. Si vous voulez que les utilisateurs s'authentifient avec des certificats clients, pourquoi ne pas donner aux utilisateurs les certificats que vous signez? Comme vous l'avez mentionné, il existe des fournisseurs OpenID qui font exactement cela. Apache a mod_sslété conçu pour authentifier les utilisateurs sur la base d'une relation de signature de certificat; si vous préférez ignorer cela pour une raison quelconque, vous devrez implémenter l'authentification par certificat dans votre propre code qui gère également votre mappage certificat-utilisateur.
Shane Madden
@ShaneMadden: J'espérais éviter d'émettre des certificats et si j'accepte seulement les certificats que j'ai émis, alors les certificats basés sur la carte à puce sont supprimés. Peu importe ce que je fais, une partie du système va se dérouler au niveau de l'application, mais comme il y a toute la mod_sslmachinerie là-bas, j'espérais qu'il pourrait s'occuper d'une partie du travail pour moi.
Isaac
1
@ShaneMadden L'un des avantages optional_no_caest que cela peut être meilleur pour l'interface utilisateur, car vous pouvez afficher un message d'erreur HTTP si quelque chose ne va pas avec le certificat (vous ne pourriez pas autrement, car un mauvais certificat client arrêterait la connexion avant la couche HTTP ). Il est également utile si vous souhaitez essayer d'autres méthodes de vérification d'un certificat (par exemple WebID ). Vous avez raison, vous voudriez que quelque chose fasse la vérification, et cela ne fonctionnerait vraiment que lorsque la demande est traitée par du code (par exemple dans PHP / CGI / Java), pas tellement avec des fichiers.
Bruno

Réponses:

10

Comme vous l'avez constaté, vous pouvez désactiver la vérification de certificat au niveau de la négociation SSL / TLS dans Apache Httpd à l'aide de SSLVerifyCLient optional_no_ca.

Le deuxième problème auquel vous allez être confronté avec ce que vous essayez de faire est d'amener le client à envoyer le certificat. Étant donné que vos certificats ne sont pas destinés à faire partie d'une infrastructure à clé publique, ils peuvent être auto-signés et avoir différents émetteurs.

Lors de la demande d'un certificat client, le serveur envoie un CertificateRequestmessage TLS au client pendant le handhsake. Ce message contient la certificate_authoritiesliste:

Une liste des noms distinctifs des autorités de certification acceptables. Ces noms distinctifs peuvent spécifier un nom distinctif souhaité pour une autorité de certification racine ou pour une autorité de certification subordonnée; ainsi, ce message peut être utilisé pour décrire à la fois des racines connues et un espace d'autorisation souhaité. Si la liste certificate_authorities est vide, le client PEUT envoyer tout certificat du ClientCertificateType approprié, sauf s'il existe un arrangement externe contraire.

Les navigateurs l'utilisent pour choisir le certificat client à envoyer (le cas échéant).

(Notez que la partie sur la liste vide est uniquement dans la spécification à partir de TLS 1.1. SSL 3.0 et TLS 1.0 sont silencieux à ce sujet, et en pratique, cela fonctionnera également.)

Vous avez deux options pour cela.

  • Si les certificats clients que vous attendez vont être auto-signés, ils auront tous des émetteurs différents. Parce que vous ne savez pas à quoi vous attendre, le serveur devra envoyer une liste vide. Pour ce faire, utilisez la SSLCADNRequestFiledirective et pointez-la vers un fichier qui ne contient qu'une ligne vide (si je me souviens bien, cela ne fonctionne pas avec un fichier complètement vide).

  • La deuxième option (moins propre). Est de convenir d'un DN émetteur commun à tous les certificats clients que vous attendez, qu'ils aient effectivement été émis ou non par ce certificat CA (ou que cette CA existe ou non). Ce faisant, vous briseriez considérablement le modèle PKI (plus).

    Si vous êtes d'accord sur un DN émetteur comme CN=Dummy CA(par exemple). Tout le monde peut créer un certificat auto-signé en utilisant CN=Dummy CAcomme DN d'objet (et DN d'émetteur), éventuellement avec des clés différentes. Bien que la SSLCADNRequestFiledirective s'attende à être configurée avec des certificats pour construire la liste, ceux-ci ne sont pas du tout utilisés pour vérifier le certificat client, c'est juste une manière compliquée (mais naturelle dans le contexte des autres directives) de configurer la certificate_authoritiesliste. Si vous, en tant que service, placez un certificat auto-signé avec ces noms SSLCADNRequestFile, cela fera que le CertificateRequestmessage TLS sera utilisé CN=Dummy CAdans la certificate_authoritiesliste (ce ne sont que des noms, pas des certificats à ce stade). Le client pourra alors récupérer son propre certificat auprès de l'émetteur DNCN=Dummy CA, que sa signature puisse ou non être vérifiée par ce certificat (mêmes clés), car aucune vérification de signature n'est de toute façon impliquée dans ces étapes.

Cela étant dit, n'oubliez pas qu'avec SSLVerifyCLient optional_no_ca, aucune vérification de certificat réelle n'est effectuée (je suppose que vous pouvez vérifier la SSL_CLIENT_VERIFYvariable si votre vérification manuelle n'est qu'une solution de secours à une PKI que vous avez configurée de toute façon). Tout ce que vous saurez à ce stade, c'est que le client possède la clé privée du certificat de clé publique qu'il a présenté (garanti par le CertificateVerifymessage TLS ): vous devrez effectuer une certaine forme de vérification si vous voulez qu'il y ait authentification de certains Trier. (Vous ne pouvez pas faire confiance au contenu du certificat, c'est-à-dire à la liaison entre sa clé publique et les noms / attributs qu'il contient.)

Cela ne fonctionnera pas bien pour les fichiers, mais vous pouvez le faire pour une application (par exemple PHP / CGI / ... même Java si vous passez le certificat au serveur Java mandaté). Une façon de base serait d'avoir une liste pré-connue de clés publiques, ou vous pouvez regarder les idées dans FOAF + SSL / WebID .

Bruno
la source
2

L'utilisation SSLVerifyCLient optional_no_ca(au lieu de require) empêche Apache de vérifier l'autorité de certification émettrice (et donc de ne pas avoir besoin d'un fichier ou d'un chemin de certificat d'autorité de certification). Cela permet au client / utilisateur de ne pas soumettre de certificat, donc la vérification qu'un certificat a été utilisé doit être effectuée séparément.

(Apparemment, je n'ai tout simplement pas lu attentivement la mod_ssldocumentation.)

Isaac
la source