我正在尝试使用集成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字节数据包但我无法发明NegotiateStream期望的第一个5字节响应数据包。我尝试提供之前尝试发送的相同数据包NegotiateStream,但这当然不起作用。
我想知道发生了什么以及如何解决这个问题。在Windows XP SP3和Windows Server 2008上也会出现相同的行为。
我不是Kerberos / GSSAPI专家,但是从我在文档中发现的看来,Kerberos对话应该确实从一个5字节的数据包开始。但是,我在使用其他工具时从未见过它,Exchange也拒绝使用它。也许,当GSSAPI被用于SASL协议(用于POP3 / IMAP / SMTP进行身份验证)时,应该省略第一个数据包?但是我怎么能告诉NegotiateStream这个或者至少应该在它期望来自服务器的5字节响应时发送给它呢?
我尝试了不同的NegotiateStream模式,我还向Exchange发出了AUTH NTLM和AUTH GSSAPI,但这一切都没有区别。其他工作实现(支持GSSAPI和NTLM)都以相同的方式工作(GSSAPI和NTLM数据包之间没有太大区别)。所有传入和传出的数据包都大于5个字节。
我也尝试在Windows XP上使用IIS SMTP服务,结果相同。基于SSPI的非NegotiateStream实现工作,而NegotiateStream不是由于第一个数据包。如果我不发送它,我不知道NegotiateStream期望作为第一个响应。
我曾经认为应该可以使它工作,因为SmtpClient类可以以某种方式管理它并使用默认凭据和NTLM进行身份验证。但是我发现SmtpClient不在内部使用NegotiateStream,它只是进行非托管SSPI调用,就像我在旧版本的软件中一样。
也尝试使用Visual Studio 2010 / .NET 4.0。没有运气(并没有新的方法/属性来微调NegotiateStream中的东西)。
我完全迷失了: - (
答案 0 :(得分:0)
我不确定究竟是什么问题。您是否希望/必须使用NegotiateStream编写自己的实现?或者您只需要使用SMTP / IMAP / POP3的GSSAPI / Kerberos身份验证?在这种情况下,支持GSSAPI并使用Exchange服务器(例如我们的Rebex Secure Mail)进行测试的邮件组件可能是一个不错的选择和节省时间。
以下代码将使用GSSAPI连接并登录到Exchange服务器SMTP:
Smtp smtp = new Smtp();
smtp.Connect("yourserver");
smtp.Login("username","password", SmtpAuthentication.GssApi);
...
smtp.Disconnect();