2011-02-10 9 views
4

に完成されたことを確認する方法:SSL handshake failures when no data was sent over Twisted TLSConnectionTLSハンドシェイクが。これは、この質問のフォローアップされたツイスト

私はすぐに、クライアントが接続されているように、接続を閉じ、単純なSSLサーバーを実装しています。

私は、OpenSSLでそれをテストしていると私は、このハンドシェイクに失敗しました:

$ openssl s_client -connect localhost:12345        
CONNECTED(00000003) 2329:error:140790E5:SSL routines:SSL23_WRITE 
:ssl handshake failure:s23_lib.c:188: 

問題はTLS.Connection.loseConnectionが行われるための継続的なハンドシェイクを待たずに、ただ、クライアントが切断されていることです。

コールバックはOpenSSL.SSL.Connection.do_handshakeに添付されていましたが、残念ながら私はこれができるかどうか、またはそれをどうやって行うのか分かりません。

TLSハンドシェイクが行われたことをどのようにテストできるかについてのヒントは非常に高く評価されています。どうもありがとう!ここで

は、私は、有効なこれは本当に汚いとない100%を解決するために、今のコード

class ApplicationProtocol(Protocol): 
     '''Protocol that closes the connection when connection is made.''' 
     def connectionMade(self): 
      self.transport.loseConnection() 

# Here is a barebone TLS Server 
serverFactory = ServerFactory() 
serverFactory.protocol = ApplicationProtocol 
server_cert_path = 'server.pem' 
serverContextFactory = DefaultOpenSSLContextFactory(
      privateKeyFileName = server_cert_path, 
      certificateFileName = server_cert_path, 
      sslmethod=SSL.SSLv23_METHOD) 

tlsFactory = TLSMemoryBIOFactory(serverContextFactory, False, serverFactory) 
reactor.listenTCP(12345, tlsFactory) 
#reactor.listenSSL(12345, serverFactory, serverContextFactory) 

です。

def tls_lose_connection(self): 
    """ 
    Monkey patching for TLSMemoryBIOProtocol to wait for handshake to end, 
    before closing the connection. 

    Send a TLS close alert and close the underlying connection. 
    """ 

    def close_connection(): 
     self.disconnecting = True 
     if not self._writeBlockedOnRead: 
      self._tlsConnection.shutdown() 
      self._flushSendBIO() 
      self.transport.loseConnection() 

    # If we don't know if the handshake was done, we wait for a bit 
    # and the close the connection. 
    # This is done to avoid closing the connection in the middle of a 
    # handshake. 
    if not self._handshakeDone: 
     reactor.callLater(0.5, close_connection) 
    else: 
     close_connection() 


TLSMemoryBIOProtocol.loseConnection = tls_lose_connection 

答えて

4

SSLコンテキストオブジェクトは、 "info callback" - Context.set_info_callbackで設定できます。これはSSL_CTX_set_info_callbackのラッパーです。残念ながら、pyOpenSSLでは、単一の接続のコールバックを指定するための(この場合は)少し便利なSSL_set_info_callbackは公開されていません。

情報コールバックは、ハンドシェイクが完了すると呼び出されます。いくつかのアクロバットを使って、この通知をDeferredや他のプロトコルへのコールバックにすることができます。

詳細については、pyOpenSSL set_info_callback documentationおよびOpenSSL SSL_CTX_set_info_callback documentationを参照してください。

+1

ありがとう、非常に:)。 pyOpenSSLのドキュメントから、Context.set_info_callbackはConnectionオブジェクトをコールバックに渡しているようです...このコールバックをフックして、接続上でhandshake_in_progressとhandshake_doneフラグを設定できると思います。 –

+0

@Adi - これを行う方法を見つけましたか? info_callbackがOpenSSL.SSLを取得したことを確認しました。Connectionインスタンスを作成し、ハンドシェイクが完了したことを確認するフラグをテストすることができますが、ConnectionインスタンスからTwisted Protocolインスタンスを取得する準備ができていません。 – Von

+0

@ Von私の現在の汚れたソリューションを追加しました。私はset_info_callbackの値を調べようとしましたが、正しい値が見つからず、ハンドシェークが行われたかどうかを確認できませんでした。 –

5

私はJean-Paulの答えを実装するコードを提供しています。

class ProxyClientTLSContextFactory(ssl.ClientContextFactory): 
    isClient = 1 

def getContext(self): 
    ctx = SSL.Context(SSL.TLSv1_METHOD) 
    logger = logging.GetLogger() 
    def infoCallback(conn, where, ret): 
     # conn is a OpenSSL.SSL.Connection 
     # where is a set of flags telling where in the handshake we are 
     # See http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html 
     logger.debug("infoCallback %s %d %d" % (conn, where, ret)) 
     if where & SSL.SSL_CB_HANDSHAKE_START: 
      logger.debug("Handshake started") 
     if where & SSL.SSL_CB_HANDSHAKE_DONE: 
      logger.debug("Handshake done") 
    ctx.set_info_callback(infoCallback) 
    return ctx 

私はinfoCallback(の内部に走った問題は)私は戻って、関連するツイストプロトコルインスタンスにSSL.Connectionから取得する方法が分からないということです。

私がしたいのは、接続が確立され、TLSハンドシェイクが完了した後、自分のプロトコルインスタンスでコールバックを呼び出して、証明書の検証が自分の好きなものであることを確認することです。

+0

'ctx.set_info_callback(lambda conn、where、ret:self.infoCallback(conn、where、ret))' 'あなたの' infoCallback'は 'self'オブジェクトの真のメソッドであり、それを使うことができますそれが望むように。 –

0

ハンドシェイクの問題のため、loseConnection()を使用すると信頼性が低いとわかりました。それを呼び出すことは可能で、接続は完全に切断されません。だから、私はいつもabortConnection()を代わりに使っています。ハンドシェイクの状態に関係なく接続が閉じられていることを確認します。

関連する問題