Hi everyone!
I'm trying to get Integrated Windows Authentication (using default credentials of the currently logged Windows user) to log in Exchange 2007 account (SMTP/POP3/IMAP).
I already have working implementation for this but it uses SSPI functions and thus needs unmanagedcode permissions (no good). I tried to make use of NegotiateStream class for this but it does not work.
You can't directly use NegotiateStream with POP3/IMAP/SMTP as every request and response in the entire conversation needs to be wrapped in base64 and embraced with the mail protocol suffixes, etc. So, I implemented my own stream classes which does this, and injected it between NetworkStream and NegotiateStream. However, I noticed that the requests created by NegotiateStream and responses which it expects are different from those ones I have been successfully using (and those created by other mail clients which are capable of NTLM/GSSAPI sort of authentication).
In particular, NegotiateStream first sends a 5-byte length request which is not sent by other implementations. This packet is rejected by Exchange with "protocol error" message.
The second request created by NegotiateStream is the correct one (starts with NTLMSSP). So, I decided to ignore the first packet in my base64-encoding intermediate stream and not send it. When Exchange gets the second packet, it eats this packet successfully and returns the proper continuation response. However, this time NegotiateStream now wants to receive 5-bytes response while the server returned much larger response. Shortly speaking, NegotiateStream sends +1 request and expects +1 response than it should.
I can avoid sending the first "redundant" 5-bytes packet but I cannot invent the first 5-bytes response packet expected by NegotiateStream. I tried to feed the same packet NegotiateStream attempted to send before but this of course didn't work.
I want to find out what's going on and how to fix this. The same behavior occurs on Windows XP SP3 and Windows Server 2008.
I'm not Kerberos/GSSAPI expert but from what I found in the docs it seems Kerberos conversation should indeed start with a 5-bytes packet. However, I never saw it when using other working tools and Exchange rejects it too. Maybe, when GSSAPI is being used over SASL protocol (used in POP3/IMAP/SMTP for authentication), the first packet should be omitted? But how can I tell NegotiateStream about this or at least what should I send to it when it expects that 5-bytes response from the server?
I tried different modes of NegotiateStream, I also issued both AUTH NTLM and AUTH GSSAPI to Exchange but this all makes no difference. And other working implementations (which support both GSSAPI and NTLM) all work the same way (there is no big difference between GSSAPI and NTLM packets). All incoming and outgoing packets there are much larger than 5 bytes.
I also tried with IIS SMTP service on Windows XP with the same result. SSPI-based non-NegotiateStream implementations work while NegotiateStream doesn't due to the first packet. If I do not send it, I have no idea what NegotiateStream expects as the first response.
I once thought it should be possible to make it work as SmtpClient class can manage this somehow and authenticate with the default credentials and NTLM. But I found that SmtpClient does not internally use NegotiateStream, it just makes unmanaged SSPI calls, just like I do in the old version of my software.
Tried with Visual Studio 2010 / .NET 4.0 as well. No luck (and no new methods/properties to fine-tune things in NegotiateStream).
I'm completely lost :-(