1

さて、この投稿に入る前に、これは簡単な修正ではない可能性があることを警告しておく必要があります。この投稿を読んで返信できる人は誰でも、多くの C/C++ を知っている必要があり、上記の質問に答えるには少なくとも Python の知識が必要です。

基本的に、サーバーに接続し、認証のために SSL 証明書を送信する Mumble (VOIP クライアント) からの接続方法があります。同じ Mumble VOIP サーバーに接続する Python スクリプトもありますが、証明書は送信しません。

現在の Mumble クライアントが行っているように、証明書を送信するために既存のコードを変更する必要があります。

--

証明書を送信しているように見える C++ コードは次のとおりです。

    ServerHandler::ServerHandler() {
         MumbleSSL::addSystemCA();

          {
           QList<QSslCipher> pref;
           foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
           if (c.usedBits() < 128)
             continue;
            pref << c;
           }
           if (pref.isEmpty())
            qFatal("No ciphers of at least 128 bit found");
           QSslSocket::setDefaultCiphers(pref);
          }

    void ServerHandler::run() {
          qbaDigest = QByteArray();
          QSslSocket *qtsSock = new QSslSocket(this);

           qtsSock->setPrivateKey(g.s.kpCertificate.second);
           qtsSock->setLocalCertificate(g.s.kpCertificate.first.at(0));
           QList<QSslCertificate> certs = qtsSock->caCertificates();
           certs << g.s.kpCertificate.first;
           qtsSock->setCaCertificates(certs);

          cConnection = ConnectionPtr(new Connection(this, qtsSock));

          qtsSock->setProtocol(QSsl::TlsV1);
          qtsSock->connectToHostEncrypted(qsHostName, usPort);

     void ServerHandler::serverConnectionConnected() {
          tConnectionTimeoutTimer->stop();

          qscCert = cConnection->peerCertificateChain();
          qscCipher = cConnection->sessionCipher();

          if (! qscCert.isEmpty()) {
           const QSslCertificate &qsc = qscCert.last();
           qbaDigest = sha1(qsc.publicKey().toDer());
           bUdp = Database::getUdp(qbaDigest);
                  } else {
           bUdp = true;
          }

          QStringList tokens = Database::getTokens(qbaDigest);
          foreach(const QString &qs, tokens)
           mpa.add_tokens(u8(qs));

          QMap<int, CELTCodec *>::const_iterator i;
          for (i=g.qmCodecs.constBegin(); i != g.qmCodecs.constEnd(); ++i)
                mpa.add_celt_versions(i.key());

          sendMessage(mpa);

--

そして悲しいかな、これは私が今すぐそれに接続するために行うことです(Pythonで):

    try:
        self.socket.connect(self.host)
    except:
        print self.threadName,"Couldn't connect to server"
        return
    self.socket.setblocking(0)
    print self.threadName,"connected to server"

--

そうです...証明書を必要とするサーバーに接続するには、Python ソースにさらに何をする必要がありますか? 私のソースは現在、requirecert が false に設定されている任意のサーバーに問題なく接続しているためです。これは自分のサーバーで使用されるため、すべてのサーバーで動作する必要があります (皮肉なことに、requirecerts がオンになっています)。

証明書を .p12 または w/e タイプのファイルとして事前に生成できるため、証明書を生成するためのプログラムは必要ありません。サーバーが望むように証明書を送信するために必要なだけです(投稿したc ++で行われているように)。

本当に早く助けてください!さらに情報が必要な場合は、もう一度メッセージを送ってください。 無関係なコードをすべて取り除き、ssl を扱うコードだけになりました。

4

1 に答える 1

0

C++ コードから見ると、ssl をサポートし、正しい認証ファイルとネゴシエートし、ペイロードを正しい秘密鍵で暗号化するだけでよいように見えます。これらの証明書と秘密鍵は、元のプログラムのどこかに保存されている可能性があります。C++ がロードしている可能性のある非標準の権限がある場合は、それらのルート権限を Python インストールのどこに配置するかを調べるか、Python がそれらの問題を単純に無視するようにする必要がありますが、これは安全性が低くなります。

Python では、上記のようにソケットを作成できますが、urllib は除きます。このライブラリは、HTTPs をサポートし、証明書と秘密鍵を提供します。URLオープナー

使用例:

opener = urllib.URLopener(key_file = 'mykey.key', cert_file = 'mycert.cer')
self.socket = opener.open(url)

おそらく、適切なエラー チェックなどを使用してより堅牢にする必要がありますが、この情報が役立つことを願っています。

于 2010-11-21T19:59:35.513 に答える