ユーザ用ツール

サイト用ツール


Sidebar

ミドルウェア系:openfire:openfireで使用するcipherをサーバ側で変更

Openfireで使用するcipherをサーバ側で変更

Openfire側でのCipherSuites限定の実装を調査した。大量のOpenfireのJavaコード(数十万)を頑張って読んだ。

NIOConnectionクラス

幾つか実装を変更しながら、TLSハンドシェイクを試しているうちに、幾つかあるうちの以下のstartTLSメソッドが 使用されていることを突き止めた。

  • /usr/local/src/openfire_src/src/java/org/jivesoftware/openfire/nio/NIOConnection.java
323     public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
324         boolean c2s = (remoteServer == null);
325         KeyStore ksKeys = SSLConfig.getKeyStore();
326         String keypass = SSLConfig.getKeyPassword();
327
328         KeyStore ksTrust = (c2s ? SSLConfig.getc2sTrustStore() : SSLConfig.gets2sTrustStore() );
329         String trustpass = (c2s ? SSLConfig.getc2sTrustPassword() : SSLConfig.gets2sTrustPassword() );
330         if (c2s)  Log.debug("NIOConnection: startTLS: using c2s");
331         else Log.debug("NIOConnection: startTLS: using s2s");
332         // KeyManager's decide which key material to use.
333         KeyManager[] km = SSLJiveKeyManagerFactory.getKeyManagers(ksKeys, keypass);
334
335         // TrustManager's decide whether to allow connections.
336         TrustManager[] tm = SSLJiveTrustManagerFactory.getTrustManagers(ksTrust, trustpass);
337
338         if (clientMode || authentication == ClientAuth.needed || authentication == ClientAuth.wanted) {
339             // We might need to verify a certificate from our peer, so get different TrustManager[]'s
340             if(c2s) {
341                 // Check if we can trust certificates presented by the client
342                 tm = new TrustManager[]{new ClientTrustManager(ksTrust)};
343             } else {
344                 // Check if we can trust certificates presented by the server
345                 tm = new TrustManager[]{new ServerTrustManager(remoteServer, ksTrust, this)};
346             }
347         }
348
349         String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS");
350         SSLContext tlsContext = SSLContext.getInstance(algorithm);
351
352         tlsContext.init(km, tm, null);
353
354         SSLFilter filter = new SSLFilter(tlsContext);
355         filter.setUseClientMode(clientMode);
356         if (authentication == ClientAuth.needed) {
357             filter.setNeedClientAuth(true);
358         }
359         else if (authentication == ClientAuth.wanted) {
360             // Just indicate that we would like to authenticate the client but if client
361             // certificates are self-signed or have no certificate chain then we are still
362             // good
363             filter.setWantClientAuth(true);
364         }
365         // TODO Temporary workaround (placing SSLFilter before ExecutorFilter) to avoid deadlock. Waiting for
366         // MINA devs feedback
367         ioSession.getFilterChain().addBefore("org.apache.mina.common.ExecutorThreadModel", "tls", filter);
368         //ioSession.getFilterChain().addAfter("org.apache.mina.common.ExecutorThreadModel", "tls", filter);
369         ioSession.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
370         if (!clientMode) {
371             // Indicate the client that the server is ready to negotiate TLS
372             deliverRawText("<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
373         }
374     }

さらに、ここでCipherSuitesを実装可能なクラスメソッド、例えばSSLEngineSSLSocket、あるいは、SSLServerSocketなどと 同等の処理を探したが見当たらない。

Apache MINAのSSLFilterクラス

Web検索を行ったり、その他のコードを比較しながら読むうちに、Apache MINAと呼ばれる 非同期IOライブラリを使っている事が判明。

Apache MINAで実装されているクラス、SSLFilterに注目し、該当クラスに関するApache MINAの仕様を 調査していると、CipherSuitesの設定メソッドがあることを突き止めた。

http://mina.apache.org/mina-project/apidocs/org/apache/mina/filter/ssl/SslFilter.html

そこで、355行目に以下の実装を追記。

353         SSLFilter filter = new SSLFilter(tlsContext);
354         filter.setUseClientMode(clientMode);
355         filter.setEnabledCipherSuites(new String[]{"SSL_RSA_WITH_RC4_128_SHA"});
356         if (authentication == ClientAuth.needed) {
357             filter.setNeedClientAuth(true);
358         }

これにより、CipherSuitesを「SSL_RSA_WITH_RC4_128_SHA」に限定できると考えられる。 再度ビルドし、ログインを試すと、無事CipherSuitesを限定できた。

Cipher: RC4-SHA                 SSLv3 Kx=RSA      Au=RSA  Enc=RC4(128)  Mac=SHA1

RECV <<<<<<<<<<<<<<<<<<<<<<<<< : Sun May 19 18:05:33 2013

これにより、上記のNIOConnectionクラスのstartTLSメソッドにSSLFilterクラスのsetEnabledCipherSuitesを 使うことで、CipherSuitesのサーバ側からの変更が可能となる。

ミドルウェア系/openfire/openfireで使用するcipherをサーバ側で変更.txt · 最終更新: 2013/05/19 18:35 by matsumoto_r