¿Cómo puedo hacer que Apache solicite un certificado SSL de cliente sin necesidad de verificarlo con una CA conocida?

9

Estoy usando apache2 (2.2.3) para servir un sitio donde me gustaría que los clientes se autentiquen con certificados. Como solo necesito verificar que un usuario que presente un certificado en particular sea el mismo usuario que lo haya presentado en el pasado, la CA que firma el certificado es irrelevante. Sin embargo, parece que el uso SSLVerifyClient requirerequiere SSLCACertificateFile ...(o SSLCACertificatePath ...), y luego apache solo aceptará certificados firmados por una CA en ese archivo / ruta. ¿Hay alguna manera de hacer que apache acepte cualquier certificado de cliente, independientemente de la CA emisora ​​/ cantante? (es decir, verificar que el cliente tenga la clave privada correspondiente a la clave pública presentada, pero no se moleste en verificar la CA emisora ​​/ firmante)

Isaac
fuente
¿Cómo planea rastrear qué certificados se han autenticado?
Shane Madden
@ShaneMadden: algo así como una tabla que asigna certificados a ID de usuario internos. La mecánica de la criptografía de clave pública tomaría el lugar de un intercambio de contraseña.
Isaac
2
Correcto: a lo que me refiero es que Apache no hace certificados de asignación de tablas a ID de usuario internos. Si va a hacer que los usuarios se autentiquen con certificados de cliente, ¿por qué no les da a los usuarios los certificados que firma? Como mencionó, hay proveedores de OpenID que hacen exactamente eso. Apache's mod_sslfue diseñado para autenticar usuarios en función de una relación de firma de certificado; si prefiere ignorar eso por algún motivo, deberá implementar la autenticación de certificado en su propio código que también maneja su mapeo de certificado a usuario.
Shane Madden
@ShaneMadden: esperaba evitar la emisión de certificados y si solo acepto los certificados que emití, entonces los certificados basados ​​en tarjetas inteligentes están fuera. No importa lo que haga, alguna parte del sistema tendrá lugar a nivel de aplicación, pero como hay toda la mod_sslmaquinaria allí, esperaba que pudiera encargarse de parte del trabajo por mí.
Isaac
1
@ShaneMadden Una de las ventajas optional_no_caes que puede ser mejor para la interfaz de usuario, ya que puede mostrar un mensaje de error HTTP si algo está mal con el certificado (de lo contrario no podría, ya que un certificado de cliente incorrecto detendría la conexión antes de la capa HTTP ) También es útil si desea probar formas alternativas de verificar un certificado (por ejemplo, WebID ). Sin embargo, tiene razón, desearía que algo hiciera la verificación, y eso solo funcionaría realmente cuando la solicitud se maneje por código (por ejemplo, dentro de PHP / CGI / Java), no tanto con archivos.
Bruno

Respuestas:

10

Como ha encontrado, puede deshabilitar la verificación del certificado en el nivel de protocolo de enlace SSL / TLS dentro de Apache Httpd mediante SSLVerifyCLient optional_no_ca.

El segundo problema que enfrentará con lo que intenta hacer es hacer que el cliente envíe el certificado. Dado que su certificado no está destinado a estar dentro de una PKI, podrían estar autofirmados y tener varios emisores.

Al solicitar un certificado de cliente, el servidor envía un CertificateRequestmensaje TLS al cliente durante el reconocimiento. Este mensaje contiene la certificate_authoritieslista:

Una lista de los nombres distinguidos de las autoridades de certificación aceptables. Estos nombres distinguidos pueden especificar un nombre distinguido deseado para una CA raíz o para una CA subordinada; por lo tanto, este mensaje se puede usar para describir tanto las raíces conocidas como el espacio de autorización deseado. Si la lista de certificados_autoridades está vacía, el cliente PUEDE enviar cualquier certificado del ClientCertificateType apropiado, a menos que exista algún acuerdo externo en contrario.

Los navegadores usan esto para elegir qué certificado de cliente enviar (si lo hay).

(Tenga en cuenta que la parte sobre la lista vacía está solo en la especificación de TLS 1.1 en adelante. SSL 3.0 y TLS 1.0 no dicen nada al respecto, y en la práctica, también funcionará).

Tienes dos opciones para esto.

  • Si los certificados de cliente que espera serán autofirmados, todos tendrán diferentes emisores. Como no sabrá qué esperar, el servidor deberá enviar una lista vacía. Para hacer esto, use la SSLCADNRequestFiledirectiva y apúntela a un archivo que contenga solo una línea vacía (si no recuerdo mal, no funciona con un archivo completamente vacío).

  • La segunda opción (menos limpia). Es acordar un DN del Emisor común a todos los certificados de cliente que espera, independientemente de que hayan sido emitidos o no por ese certificado de CA (o de si esa CA existe o no). Al hacerlo, estaría rompiendo el modelo PKI considerablemente (más).

    Si está de acuerdo con un DN del emisor como CN=Dummy CA(por ejemplo). Cualquiera puede crear un certificado autofirmado utilizando el CN=Dummy CADN del sujeto (y el DN del emisor), posiblemente con diferentes claves. Aunque la SSLCADNRequestFiledirectiva espera configurarse con certificados para construir la lista, estos no se utilizan para verificar el certificado del cliente, es una forma complicada (pero natural en el contexto de las otras directivas) de configurar la certificate_authoritieslista. Si, como servicio, coloca un certificado autofirmado con estos nombres SSLCADNRequestFile, esto hará que el CertificateRequestmensaje TLS se use CN=Dummy CAen la certificate_authoritieslista (estos son solo nombres, no certificados en esta etapa). El cliente podrá recoger su propio certificado con el DN del emisorCN=Dummy CA, si su certificado podría verificarse o no mediante ese certificado (las mismas claves) o no, ya que de todos modos no hay verificación de firma en estos pasos.

Dicho esto, recuerde que con SSLVerifyCLient optional_no_ca, no se realiza una verificación real del certificado (supongo que podría verificar la SSL_CLIENT_VERIFYvariable si su verificación manual es solo una solución alternativa a una PKI que haya configurado de todos modos). Todo lo que sabrá en esa etapa es que el cliente tiene la clave privada para el certificado de clave pública que ha presentado (garantizado por el CertificateVerifymensaje TLS ): deberá realizar algún tipo de verificación si desea que haya autenticación de algunos ordenar. (No puede confiar en el contenido del certificado, es decir, en cualquiera de los enlaces entre su clave pública y los nombres / atributos que contiene).

Esto no funcionará bien para los archivos, pero puede hacerlo para una aplicación (por ejemplo, PHP / CGI / ... incluso Java si pasa el certificado al servidor Java proxy). Una forma básica sería tener una lista conocida de claves públicas, o podría mirar las ideas en FOAF + SSL / WebID .

Bruno
fuente
2

El uso SSLVerifyCLient optional_no_ca(en lugar de require) hace que apache no verifique la CA emisora ​​(y por lo tanto no necesita un archivo o ruta de certificado de CA). Sí permite que el cliente / usuario no envíe un certificado, por lo que la verificación de que se haya utilizado un certificado debe hacerse por separado.

(Aparentemente, simplemente no pude leer completamente la mod_ssldocumentación).

Isaac
fuente