A while back I started playing with the managed support for secure stream protocols available for windows. The managed wrappers of NegotiateStream wrap up access to SSPI. In a previous post on my previous blog (Previous Rant) I mentioned that even though you asked for a secure stream to be mutually authenticated, windows could decide not to bother and use NTLM and only send your credentials. Personally I felt that the API should have thrown an exception since it did not do what was said on the tin…Having discussed it with others it was pointed out that there is a property you can check on the stream called IsMutuallyAuthenticated prior to actually using the stream, so not too bad..Assuming you remember to check..A little internal wrapper method and you could keep yourself safe.
NegotiateStream is used as a foundation building block for higher level communication abstractions such as remoting. When I use .NET remoting I have no access to the underlying stream I simply make a method call in the same way as I make a local call, the communication context is hidden from me. So if in my remoting configuration I actually specify I want to use mutual authentication and it fails to achieve it because the other end refuses to play ball it falls back to NTLM and I’m none the wiser.
One reason for opting for mutual authentication was the fact that the information Im sending to the server is for its eyes only, it may be sensitive and I don’t want it consumed by any other party. Personally I find this totally unacceptable….
So from a pure security point of view that may rule out .NET remoting which would be a real shame, since I really don’t want to go back to the days of creating my own wire format for RPC between my client and server.
So this got me thinking if there was some kind of workaround. The strategy that I think you can adopt is the following
On the server, declare your remoting service in the normal way, and in addition provide a simple tcp listener on a well known port. This tcp listener is the real trusted entity, clients should negotiate a stream to the listener using mutual authentication and after establishing it check that it was successful.. The server sends back along the stream the URL for the remoting service. The client then uses the contained URL to connect back to host..
This way the client can be sure of using mutual authentication to validate the service, after the service has been validated the client continues to use RPC based protocols.