2012-09-23 17 views
5

Sto provando a creare un server HTTPS personalizzato in Java (6) utilizzando la classe integrata com.sun.net.httpserver.HttpsServer. Funziona bene fino a quando non richiedo l'autenticazione del client. A quel punto fallisce con la seguente eccezione nel debug SSL sul server.Come disattivare il controllo dei vincoli (tipo di certificato Netscape) in Java6?

sun.security.validator.ValidatorException: Netscape tipo cert non consente l'utilizzo di client SSL

Sto usando certificati rilasciati dal nostro CA interno che viene utilizzato per tutte le applicazioni interne a noi. Ho controllato i dettagli del certificato e ho scoperto che il tipo era "Server SSL" (dettagli citati sotto). Poiché la nostra politica è di utilizzare un tipo "Server SSL" per tutte le applicazioni interne, è difficile modificare il certificato. Dal momento che voglio utilizzare un certificato server per il cliente, non credo che questo sia un problema di sicurezza.

Quello che sto cercando è un modo per disabilitare questo controllo dei vincoli in Java. Qualcuno ha incontrato questo e risolto questo? Qualsiasi aiuto è molto apprezzato.

migliori saluti, 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#. 
] 

] 

risposta

1

Si potrebbe avvolgere i manager di fiducia di default e prendere questo particolare eccezione. Questo sarebbe qualcosa in queste righe:

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 
}   

Poi, utilizzare che il manager di fiducia di creare un SSLContext e utilizzarlo con il server.

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); 

Si dovrebbe inizializzare i tuoi keymanagers dai vostri archivi di chiavi del server (come di consueto). Dovresti quindi essere in grado di utilizzare lo HttpsConfigurator per impostare lo SSLContext (vedi l'esempio nella documentazione).

Questa tecnica non è l'ideale, però.

  • Innanzitutto, ValidatorException è in un pacchetto sun.* che non fa parte del pubblico API: questo codice sarà specifico per Oracle/OpenJDK JRE.
  • In secondo luogo, si basa sul fatto che l'entità finale ha verificato (che verifica l'estensione di utilizzo della chiave) happens after the rest of the trust validation (che rende accettabile ignorare tale eccezione, poiché in questo modo non si ignorano altri controlli più fondamentali).

Si potrebbe ovviamente implementare nuovamente la propria convalida, utilizzando l'API Percorso certificato Java e ignorando solo l'utilizzo della chiave per questo scopo. Ciò richiede un po 'più di codice.

Più in generale, si sta tentando di ignorare le specifiche comunque, se si desidera utilizzare un certificato per SSL/TLS come certificato client quando non ha l'estensione corretta. La soluzione migliore per questo è modificare la politica della CA, che dovrebbe essere fattibile se si tratta comunque di una CA interna. È abbastanza comune per i certificati server avere anche l'utilizzo della chiave estesa del client TLS, anche con grandi CA.

+0

Grazie mille. Ha funzionato molto bene. Sono d'accordo che la soluzione ideale sia quella di aggiornare la politica della CA, ma se non costruisco la soluzione di bypass, l'aggiornamento del mio software su centinaia di sistemi richiederà il rinnovo immediato del certificato. – Arun

+2

Sembra una soluzione sporca che durerà per tutta l'eternità e dopo. – sjas

+0

@sjas Sì, spero solo che chiunque legga questo leggi il testo e non semplicemente copia e incolla. – Bruno