我正在尝试获取集成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也拒绝了它。也许,当通过SASL协议(用于POP3 / IMAP / SMTP用于身份验证)使用GSSAPI时,应该省略第一个数据包吗?但是,当它期望服务器发出5字节的响应时,我该如何告知NegotiateStream或至少应将其发送给NegotiateStream?
我尝试了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中的内容)。
我完全迷路了:-(
最佳答案
我不确定这个问题到底是什么。您是否想要/必须使用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();
关于c# - NegotiateStream无法通过SASL(POP3/IMAP/SMTP)使用Kerberos/NTLM/GSSAPI吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3294091/