2011-01-06 18 views
10

SSL経由でLDAPディレクトリに接続する必要があります。非本番環境でJNDI/LDAP接続の自己署名証明書を受け入れる方法は?

、我々はもちろん、との検証に失敗し、自己署名証明書を使用します。

javax.naming.CommunicationException: simple bind failed: ldapserver:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target] 
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:197) 
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694) 
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293) 
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175) 
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193) 
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136) 
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66) 
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667) 
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288) 
at javax.naming.InitialContext.init(InitialContext.java:223) 
at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134) 

を私はcustom trust manager for SSL-enabled connectionsを使用する方法を知っていますが、どのように知りません実際の接続を管理していないJNDI APIに関連したものを使用してください。つまり、次の標準設定はどこにありますか?私はトラストマネージャをプラグインできますか?

ありがとうございます。

Hashtable env = new Hashtable(); 
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
env.put(Context.PROVIDER_URL, "ldaps://ldapserver:636"); 
env.put(Context.SECURITY_PROTOCOL, "ssl"); 
env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
env.put(Context.SECURITY_PRINCIPAL, "myUser"); 
env.put(Context.SECURITY_CREDENTIALS, "myPassword"); 
LdapContext ctx = new InitialLdapContext(env, null); 
ctx.search (...) 

答えて

18

JNDIのドキュメントによれば、SSLSocketFactory

http://download.oracle.com/javase/1.5.0/docs/guide/jndi/jndi-ldap-gl.html#socket

カスタムを設定することが可能と思われます
public class MySSLSocketFactory extends SocketFactory { 
    private SSLSocketFactory sf; 

    public MySSLSocketFactory() { 
     KeyStore keyStore = ... /* Get a keystore containing the self-signed certificate) */ 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(); 
     tmf.init(keyStore); 
     SSLContext ctx = SSLContext.getInstance("TLS"); 
     ctx.init(null, tmf.getTrustManagers(), null); 
     sf = ctx.getSocketFactory(); 
    } 

    /* delegate SSLSocketFactory public methods to sf */ 
    ... 
} 

設定環境は、このソケットファクトリを使用するには

env.put("java.naming.ldap.factory.socket", "com.example.MySSLSocketFactory"); 
+0

ありがとうございました。私はそれが正しいことだと思う。私はJBoss内で実行するのが難しいですが、クラスローダーによって、java.lang.IllegalArgumentException:オブジェクトがクラス宣言のインスタンスではないと思われる場合があります。ソケットがcom.sun.jndi.ldap.Connection.createSocket (Connection.java:317) しかしそれは別の問題です – wishihadabettername

+9

誰かがIllegalArugumentExceptionを実行するのを助けるために。カスタム(SSL)SocketFactoryに静的getDefault()メソッドを実装する必要があります。 –

1

私は最後にこれをしてから約5年が経過していますので、私の答えは多少曖昧になります。私はあなたが/ usr/java/jre/lib/security /の下で見つけることができるはずのjava.securityの中で信頼されているプロバイダを意味すると思います。証明書を信頼できるものとして受け入れます。

私は、現時点では私のノートへのアクセス権を持っていけないが、私はそれらを介して掘るがあるでしょうが、後に

6

あなたがのTrustManagerをオーバーライドするときは、すべての証明書を受け入れることができる:

DummyTrustmanager.java

public class DummyTrustmanager implements X509TrustManager { 
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
     // do nothing 
    } 

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { 
     // do nothing 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
     return new java.security.cert.X509Certificate[0]; 
    } 
} 

MySSLSocketFactory.java

public class MySSLSocketFactory extends SSLSocketFactory { 
    private SSLSocketFactory socketFactory; 

    public MySSLSocketFactory() { 
     try { 
      SSLContext ctx = SSLContext.getInstance("TLS"); 
      ctx.init(null, new TrustManager[] { new DummyTrustmanager() }, new SecureRandom()); 
      socketFactory = ctx.getSocketFactory(); 
     } catch (Exception ex) { 
      ex.printStackTrace(System.err); 
      /* handle exception */ 
     } 
    } 

    public static SocketFactory getDefault() { 
     return new MySSLSocketFactory(); 
    } 

    @Override 
    public String[] getDefaultCipherSuites() { 
     return socketFactory.getDefaultCipherSuites(); 
    } 

    @Override 
    public String[] getSupportedCipherSuites() { 
     return socketFactory.getSupportedCipherSuites(); 
    } 

    @Override 
    public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException { 
     return socketFactory.createSocket(socket, string, i, bln); 
    } 

    @Override 
    public Socket createSocket(String string, int i) throws IOException, UnknownHostException { 
     return socketFactory.createSocket(string, i); 
    } 

    @Override 
    public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException, UnknownHostException { 
     return socketFactory.createSocket(string, i, ia, i1); 
    } 

    @Override 
    public Socket createSocket(InetAddress ia, int i) throws IOException { 
     return socketFactory.createSocket(ia, i); 
    } 

    @Override 
    public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException { 
     return socketFactory.createSocket(ia, i, ia1, i1); 
    } 
} 

をMain.java

public class Main { 
    public static void main(String[] args) throws NamingException { 
     Hashtable env = new Hashtable(11); 
     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
     env.put(Context.PROVIDER_URL, "ldaps://ldapserver:636/"); 
     env.put(Context.SECURITY_PROTOCOL, "ssl"); 
     env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
     env.put(Context.SECURITY_PRINCIPAL, "myUser"); 
     env.put(Context.SECURITY_CREDENTIALS, "myPassword"); 
     env.put("java.naming.ldap.factory.socket", "ldapsecure.MySSLSocketFactory"); 
     LdapContext ctx = new InitialLdapContext(env, null); 
    } 
} 
+6

これにより、この自己署名証明書を受け入れるだけでなく、信頼確認を完全に無効にすることになります。したがって、接続を攻撃するMITMの証明書を含む可能性のある証明書も受け入れます。 – Bruno

+0

働いたバターが好き、ありがとう! – Sohan

2

@Jcs回答は正しいですが、カスタムTrustManagerを使用したくない場合や、その特定の自己署名証明書がVM内の他の用途のための信頼できるCAになることを望む場合は、

  • あなたのデフォルトのトラストストア(JREセキュリティディレクトリの下に通常cacerts)または
  • にこの証明書を追加します(おそらくデフォルトcacertsのコピーに基づいて)別の場所に新しいトラストストアを作成しているだろう:どちらかができますその特定の証明書を含み、これをデフォルトのトラストストアとして使用しますが、システムプロパティーをjavax.net.ssl.trustStore*に設定します。 JNDIをさておき
1

完全に、一部フレームワークは、(これは一般的にある/etc/ldap.confまたはそのようなものである)LOCAL SYSTEMのLDAPの構成を参照します。私がLOCALと言うときは、JNDI操作が実行されているシステムを意味します。

少なくともほとんどのLDAP対応のLinuxのOSの場合には、そのようなLDAP設定ファイル内(通常)で読み込む行:

TLS_REQCERT demand 

これがデフォルト設定TLS/SSLの重大性(あります最も厳しい)、何らかの理由で証明書に誤りがある場合(これには自己署名が含まれます)、接続に失敗する可能性があります。

「要求」(「許可」または「しない」で再生)ではなく、異なる設定を試してみることができます。これが完了したら、操作をもう一度試し、問題が解消したかどうかを確認します。繰り返しますが、このようなものではなく、ローカルシステムの設定を読み込んだり検出したりするものではありません。いくつかは、いくつかはありません。見る価値がある。私はこれが役に立てば幸い

...

マックス

4

んが、コードは必要ありません。テストクライアントのトラストストアに証明書を追加するだけです。

これに余分なコードを書き込まないでください。安全ではなく、コードが生産に漏れてしまう大きなリスクを冒しています。あなたは本当にそれを望んでいません。

関連する問題