NegotiateStream не может работать с Kerberos / NTLM / GSSAPI через SASL (POP3 / IMAP / SMTP)? - PullRequest
3 голосов
/ 21 июля 2010

Я пытаюсь получить встроенную проверку подлинности Windows (используя учетные данные по умолчанию текущего зарегистрированного пользователя Windows) для входа в учетную запись Exchange 2007 (SMTP / POP3 / IMAP).

У меня уже есть рабочая реализация для этого, но она использует функции SSPI и, следовательно, требует разрешения неуправляемого кода (ничего хорошего). Я пытался использовать для этого класс NegotiateStream, но он не работает.

Вы не можете напрямую использовать NegotiateStream с POP3 / IMAP / SMTP, поскольку каждый запрос и ответ во всем диалоге должен быть заключен в base64 и заключен в суффиксы почтового протокола и т. Д. Итак, я реализовал свои собственные потоковые классы, которые делает это и вводит его между NetworkStream и NegotiateStream. Однако я заметил, что запросы, созданные NegotiateStream, и ответы, которые он ожидает, отличаются от тех запросов, которые я успешно использовал (и те, которые были созданы другими почтовыми клиентами, способными к аутентификации NTLM / GSSAPI).

В частности, NegotiateStream сначала отправляет запрос длиной 5 байт, который не отправляется другими реализациями. Этот пакет отклонен Exchange с сообщением «ошибка протокола».

Второй запрос, созданный NegotiateStream, является правильным (начинается с NTLMSSP). Итак, я решил проигнорировать первый пакет в моем промежуточном потоке с кодировкой base64 и не отправлять его. Когда Exchange получает второй пакет, он успешно ест этот пакет и возвращает правильный ответ о продолжении. Однако на этот раз NegotiateStream теперь хочет получить 5-байтовый ответ, тогда как сервер вернул гораздо больший ответ. Вкратце, NegotiateStream отправляет +1 запрос и ожидает +1 ответа, чем должен.

Я могу избежать отправки первого «избыточного» 5-байтового пакета, но я не могу изобрести первый 5-байтовый ответный пакет, ожидаемый NegotiateStream. Я пытался передать тот же пакет, который NegotiateStream пытался отправить раньше, но это, конечно, не сработало.

Я хочу узнать, что происходит и как это исправить. Такое же поведение наблюдается в Windows XP SP3 и Windows Server 2008.

Я не эксперт Kerberos / GSSAPI, но из того, что я нашел в документации, кажется, что разговор Kerberos действительно должен начинаться с 5-байтового пакета. Однако я никогда не видел этого при использовании других рабочих инструментов, и Exchange тоже отвергает его. Возможно, когда GSSAPI используется по протоколу SASL (используется в POP3 / IMAP / SMTP для аутентификации), первый пакет должен быть пропущен? Но как я могу сообщить NegotiateStream об этом или, по крайней мере, что я должен отправить ему, когда он ожидает, что 5-байтовый ответ от сервера?

Я пробовал разные режимы NegotiateStream, я также выдавал AUTH NTLM и AUTH GSSAPI для Exchange, но все это не имеет значения. И другие рабочие реализации (которые поддерживают как GSSAPI, так и NTLM) работают одинаково (нет большой разницы между пакетами GSSAPI и NTLM). Все входящие и исходящие пакеты там намного больше, чем 5 байтов.

Я также пытался использовать службу IIS SMTP в Windows XP с тем же результатом. Основанные на SSPI не-NegotiateStream реализации работают, в то время как NegotiateStream не работает из-за первого пакета. Если я не отправлю его, я понятия не имею, что ожидает NegotiateStream в качестве первого ответа.

Однажды я подумал, что это должно быть возможно, так как класс SmtpClient может каким-то образом управлять этим и аутентифицироваться с учетными данными по умолчанию и NTLM. Но я обнаружил, что SmtpClient внутренне не использует NegotiateStream, он просто делает неуправляемые вызовы SSPI, как я это делал в старой версии моего программного обеспечения.

Пробовал также с Visual Studio 2010 / .NET 4.0. Не повезло (и нет новых методов / свойств для точной настройки в NegotiateStream).

Я полностью потерян: - (

1 Ответ

0 голосов
/ 21 июля 2010

Я не уверен, что именно вопрос. Вы хотите / должны написать свою собственную реализацию, используя NegotiateStream? Или вам нужно использовать только аутентификацию GSSAPI / Kerberos с SMTP / IMAP / POP3? В таком случае почтовый компонент, который поддерживает GSSAPI и который тестируется на сервере Exchange (например, наша Rebex Secure Mail ), может быть хорошим выбором и экономит время.

Следующий код подключится и войдет в систему SMTP-сервера Exchange с помощью GSSAPI:

Smtp smtp = new Smtp();
smtp.Connect("yourserver");
smtp.Login("username","password", SmtpAuthentication.GssApi);

...
smtp.Disconnect();
...