2012-09-23 18 views
5

Estoy intentando construir un servidor HTTPS personalizado en Java (6) utilizando la clase incorporada com.sun.net.httpserver.HttpsServer. Funciona bien hasta que requiera autenticación de cliente. En ese momento falla con la siguiente excepción en la depuración SSL en el servidor.Cómo deshabilitar la comprobación de restricciones (tipo de certificado Netscape) en Java6?

sun.security.validator.ValidatorException: Netscape tipo cert no permite el uso de cliente SSL

estoy usando certificados emitidos por nuestro CA interno que se utiliza para todas las aplicaciones internas para nosotros. Revisé los detalles del certificado y encontré que ese tipo era "Servidor SSL" (detalles citados a continuación). Dado que nuestra política es utilizar un tipo de "Servidor SSL" para todas las aplicaciones internas, es difícil cambiar el certificado. Como quiero usar un certificado de Servidor para el Cliente, no creo que sea un problema de seguridad.

Lo que estoy buscando es una manera de desactivar esta verificación de restricciones en Java. ¿Alguien ha encontrado esto y ha resuelto esto? Cualquier ayuda es muy apreciada.

Best Regards, Arun

Owner: CN=myapp, OU=mygroup, O=mycompany 

Issuer: O=MYCA 

Serial number: 4cc8c1da 

Valid from: Mon Jan 10 13:46:34 EST 2011 until: Thu Jan 10 14:16:34 EST 2013 

Certificate fingerprints: 
     MD5: 8C:84:7F:7A:40:23:F1:B5:81:CD:F9:0C:27:16:69:5E 
     SHA1: 9B:39:0B:2F:61:83:52:93:D5:58:E5:43:13:7A:8F:E1:FD:AC:98:A4 
     Signature algorithm name: SHA1withRSA 
     Version: 3 

Extensions: 

[1]: ObjectId: 2.5.29.16 Criticality=false 
PrivateKeyUsage: [ 
From: Mon Jan 10 13:46:34 EST 2011, To: Wed Jul 11 21:16:34 EDT 2012] 

[2]: ObjectId: 2.5.29.15 Criticality=false 
KeyUsage [ 
    DigitalSignature 
    Key_Encipherment 
] 

[3]: ObjectId: 2.5.29.14 Criticality=false 
SubjectKeyIdentifier [ 
KeyIdentifier [ 
0000: D3 47 35 9B B4 B7 03 18 C6 53 2C B0 FE FD 49 D8 .G5......S,...I. 
0010: D0 FB EE 15          .... 
] 
] 

[4]: ObjectId: 1.2.840.113533.7.65.0 Criticality=false 

[5]: ObjectId: 2.5.29.31 Criticality=false 
CRLDistributionPoints [ 
    [DistributionPoint: 
    [CN=CRL413, O=SWIFT] 
]] 

[6]: ObjectId: 2.5.29.19 Criticality=false 
BasicConstraints:[ 
    CA:false 
    PathLen: undefined 
] 

****[7]: ObjectId: 2.16.840.1.113730.1.1 Criticality=false 
NetscapeCertType [ 
    SSL server 
]**** 

[8]: ObjectId: 2.5.29.35 Criticality=false 
AuthorityKeyIdentifier [ 
KeyIdentifier [ 
0000: 8F AF 56 BC 80 77 A3 FD 9E D2 89 83 98 FE 98 C7 ..V..w.......... 
0010: 20 65 23 CC           e#. 
] 

] 

Respuesta

1

usted podría envolver los administradores de confianza predeterminado y atrapar esta excepción particular. Esto sería algo como lo siguiente:

class IgnoreClientUsageTrustManager extends X509TrustManager { 
    private final X509TrustManager origTrustManager; 
    public class IgnoreClientUsageTrustManager(X509TrustManager origTrustManager) { 
     this.origTrustManager = origTrustManager; 
    } 

    public checkClientTrusted(X509Certificate[] chain, String authType 
     throws IllegalArgumentException, CertificateException { 
     try { 
      this.origTrustManager.checkClientTrusted(chain, authType); 
     } catch (ValidatorException e) { 
      // Check it's that very exception, otherwise, re-throw. 
     } 
    } 

    // delegate the other methods to the origTrustManager 
}   

A continuación, utilice ese gestor de confianza para crear un SSLContext y utilizarlo con su servidor.

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm()); 
tmf.init((KeyStore)null); 
TrustManager[] trustManagers = tmf.getTrustManagers(); 

for (int i = 0; i < trustManagers.length; i++) { 
    if (trustManagers[i] instanceof X509TrustManager) { 
     trustManagers[i] = IgnoreClientUsageTrustManager(trustManagers[i]); 
    } 
} 

SSLContext sslContext = SSLContext.getInstance("TLS"); 
sslContext.init(... you keymanagers ..., trustManagers, null); 

Debe inicializar sus keymanagers desde los almacenes de claves de su servidor (como es normal). Debería poder utilizar el HttpsServer's HttpsConfigurator para configurar el SSLContext (vea el ejemplo en la documentación).

Sin embargo, esta técnica no es ideal.

  • En primer lugar, es ValidatorException en un paquete sun.* que no forma parte de la API pública: este código será específica para el Oracle/OpenJDK JRE.
  • En segundo lugar, se basa en el hecho de que la entidad final verificada (que verifica la extensión de uso de la clave) happens after the rest of the trust validation (lo que hace aceptable ignorar esa excepción, ya que no ignora otras comprobaciones más fundamentales).

Por supuesto, podría volver a implementar su propia validación en su lugar, utilizando la API de Java Certificate Path, e ignorando solo el uso de la clave para este fin. Esto requiere un poco más de código.

De manera más general, está intentando eludir las especificaciones de todos modos, si desea utilizar un certificado para SSL/TLS como certificado de cliente cuando no tiene la extensión correcta. La mejor solución para esto es modificar su política de CA, que debería ser factible si es una CA interna de todos modos. Es bastante común que los certificados del servidor tengan configurado también el uso de la clave extendida del cliente TLS, incluso con CA grandes.

+0

Muchas gracias. Funcionó muy bien. Estoy de acuerdo en que la solución ideal es actualizar la política de CA, pero si no construyo la solución de derivación, la actualización de mi software en doscientos sistemas requerirá la renovación inmediata del certificado. – Arun

+2

Esto suena como una solución sucia que durará por toda la eternidad y después. – sjas

+0

@sjas Sí, solo espero que quien lea esto lea el texto y no simplemente copie y pegue. – Bruno

Cuestiones relacionadas