.NET SslStream не работает - PullRequest
       32

.NET SslStream не работает

4 голосов
/ 13 января 2011

Я пытаюсь инициализировать tls-туннель с помощью .net SslStream, но после открытия потока я всегда получаю следующую ошибку:

"Невозможно прочитать данные из транспортного соединения: установленное соединение было прерваноПО на вашем хост-компьютере. "

После того, как я установлю соединение tls и после отправки второго сообщения.

Я искал ответ последние четыре дня, но в Интернете нет полезной информации!

edit: я пытаюсь подключиться к talk.google.com

и использую пример кода из MSDN.Разница лишь в том, что я отправляю данные раньше и когда пришло время использовать tls, я делаю следующее:

public void SecureStream()
        {
        netStream.Flush();
        sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

    sslStream.AuthenticateAsClient("talk.google.com");}

edit: мне удалось устранить первую ошибку (небольшая ошибка в том, как я обрабатывалотправить) теперь я всегда получаю

"Невозможно прочитать данные из транспортного соединения: установленное соединение было прервано программным обеспечением на вашем хост-компьютере."

edit2: Я не отправляю никаких пробелов. Iпереписал часть передачи сообщений и у меня все та же проблема.

Я начинаю с

   String streamInit = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='google.com' version='1.0'>";
        client.Send(streamInit);

Затем при получении я получаю следующее

  static void client_MessageReceived(SyncronousClient source, string Result)
    {


        if (Regex.IsMatch(Result, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"><required/></starttls>"))
        {
            String startTlS = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
            source.Send(startTlS);

        }
        else if (Regex.IsMatch(Result, "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"))
        {
            //Do TLS Magic 
            source.SecureStream();
            String streamReInit = "<stream:stream xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'to='google.com'version='1.0'>";
            source.Send(streamReInit);
        }
        else if (Regex.IsMatch(Result, "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"))
        {
            //String AuthType = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-GOOGLE-TOKEN'/>";
            String AuthType = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"/>";
            source.Send(AuthType);
        }}

Ответы [ 2 ]

1 голос
/ 26 января 2011

Это вряд ли ваша проблема (если только .Net не начал делать SNI под прикрытием), но когда вы вызываете AuthenticateAsClient, передайте то же доменное имя, которое вы использовали в атрибуте вашего потока (в данном случае, google.com).Кроме того, вам может потребоваться gmail.com вместо google.com:

sslStream.AuthenticateAsClient("gmail.com", null, SslProtocols.Tls, false);

Как намекает csharptest.net, убедитесь, что у вас нет таймера keepalive, который отправляет дополнительные пробелы, или дождитесь запускаработает таймер до окончания TLS.Единственный другой способ представить, что вы получаете эту ошибку, - это если у вас нет комплекта шифров, который реализует сервер, но я знаю, что .Net SslStream работает против GTalk.

Наконец, используйте один из существующих.Сетевые библиотеки для XMPP (есть 5 в списке здесь ), и вы можете начать писать гораздо более интересный код прямо сейчас.Вы столкнетесь с недостатками системы .Net XML, и ваш подход на основе регулярных выражений не сработает, когда вы начнете получать частичные строфы или множественные строфы за одно чтение.

0 голосов
/ 13 января 2011

Это действительно не имеет смысла для меня. Сервер, если используется SSL, требует, чтобы клиент выполнял рукопожатие SSL при подключении. Таким образом, я не уверен, что вы подразумеваете под «Я отправляю данные раньше ...». Похоже, вы не сразу вызываете AuthenticateAsClient. Если это так, я подозреваю, что это ваша проблема. AFAIK, вы не можете использовать одно и то же сокет / соединение для связи как SSL, так и не SSL. Либо сервер требует SSL, либо он не поддерживает его, он никогда не должен делать оба.

Мой предыдущий ответ был в невежестве. Действительно, похоже, что стандарт действительно требует, чтобы соединение отправляло и получало данные до инициализации рукопожатия SSL. Действительно странно, что они это сделают ... но что угодно. После краткого ознакомления с частями RFC выясняется, что вы должны начать аутентификацию клиента SSL сразу после закрывающего «>». Запрещены пробелы в конце, что может быть вашей проблемой?

...