Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Client-server authentication - using SSPI?

I'm working on a client-server application and I want the client to authenticate itself to the server using the user's logon credentials, but I don't want the user to have to type in their user name and password. I certainly don't want to be responsible for securely handling passwords. I only need the user to prove to me that they are who they say they are, and then my server can go ahead and grant/deny commands as it pleases.

My users are part of a domain, and so I want to be able to use the logon credentials they created when they logged in.

I'm not using any sort of web services, nor do I want to. I control both the client and server software, and both are written in pure C# and use good ol' sockets for getting work done.

I'd prefer to do this with pure C#/.Net, but I'm open to using unsafe C# and pinvokes to win32 API if it means that I'll get the job done.

I've read a little bit about SSPI in windows, but I'm kind of feeling around in the dark since this sort of application development is new to me.

Does anybody know how to do this? Is SSPI the way? How does one use SSPI from within C#? Is there a .Net-native way so that my code can remain portable?

like image 207
antiduh Avatar asked Jun 21 '13 17:06

antiduh


People also ask

How does SSPI work?

The SSPI returns transparent binary large objects. These are passed between the applications, at which point they can be passed to the SSPI layer. Thus, the SSPI enables an application to use various security models available on a computer or network without changing the interface to the security system.

What is Kerberos SSPI?

SSPI Authentication. SSPI is a Windows technology for secure authentication with single sign-on. PostgreSQL will use SSPI in negotiate mode, which will use Kerberos when possible and automatically fall back to NTLM in other cases.

What is SSPI in SQL Server?

SSPI stands for Security Support Provider Interface. The SSPI allows an application to use any of the available security packages on a system without changing the interface to use security services.

What is data SSPI?

Security Support Provider Interface (SSPI) is a component of Windows API that performs security-related operations such as authentication.


2 Answers

Update:

SSPI is the right approach for this. The API isn't too hard to use, but does require a decent-sized project to wrap into C#.

In the process of researching the necessary bits to solve this question, I wrote a project to provide SSPI in .Net. Below I describe the basics of interfacing with the Windows SSPI API so that anybody may replicate my results. If you find yourself wanting to use SSPI in .Net, I may suggest you use the project I created to solve this:

NSspi - A .Net interface to the SSPI API

SSPI provides you raw byte arrays containing authentication tokens that you then decide how to transmit - be it over a socket with binary-formatted messages, a custom XML channel, .Net Remoting, some form of WCF, heck, even a serial port. You get to decide how to deal with them. With SSPI a server can authenticate clients, securely identify the client, and even perform basic message handling procedures like encryption/signing using the security context established with the client.

The SSPI API is documented here: SSPI API overview

Specifically take a look at the following functions:

  • AcquireCredentialsHandle
    • Acquires a handle to some form of credentials (eg, the current user's logon). Used by servers and clients.
  • InitializeSecurityContext
    • Used by clients to establish a security context with a server.
  • AcceptSecurityContext
    • Used by servers to establish a security context with a client.

The typical workflow is that each side will initialize their credentials using AcquireCredentialsHandle. The authentication cycle then starts and progresses as follows:

  • The client invokes InitializeSecurityContext, providing no input tokens, which returns output tokens in the form of a byte array. ISC returns 'ContinueNeeded' to indicate that the authentication cycle is not complete.
  • The client sends the tokens to the server by whichever means it desires.
  • The server feeds the received tokens as input to AcceptSecurityContext and produces its own output tokens. ASC also returns 'ContinueNeeded' to indicate that the authentication cycle is not complete.
  • The server then sends its output tokens to the client.
  • The client provides the servers tokens as input to InitializeSecurityContext, which returns new output tokens.
  • The client sends his new output tokens to the server.
  • ...

This cycle continues until the client sees InitializeSecurityContext return 'OK' and the server sees AcceptSecurityContext return 'OK'. Each function may return 'OK' and still provide an output token (as indicated by a non-null return), to indicate that it still has to send data to the other side. This is how the client knows that its half is done but the server's is still incomplete; and vice versa if the server completes before the client. Which side completes first (returns 'OK') depends on the specific security package being used under the hood by SSPI, and any SSPI consumer should be aware of this.

The information above should be enough for anybody to being interfacing with the SSPI system in order to provide 'Windows Integrated Authentication' in their application and replicate my results.

Below is my earlier answer as I learned how to invoke the SSPI API.


I had forgotten about this question, and coincidentally returned to this problem a few days ago on a whim. I do need to solve this problem in a year or two though :)

It is possible in .Net, and I am currently developing a .Net SSPI wrapper that I intend to publish.

I'm basing my work off of some SSPI samples from Microsoft I found.

The sample contains a C++/CLI managed assembly that implements the necessary parts of the SSPI API (in the folder Microsoft\Samples\Security\SSPI\SSPI extracted from the REMSSPI.exe file). They then have two UIs, a client application and a server application, both written in C# that make use of this API to perform SSPI authentication.

The UIs make use of the .Net remoting facility to tie it all together, but if I understand the SSPI API correctly, the only information that the client and server need to exchange consists of byte[]s containing security context token data, which can easily be integrated into whatever communications infrastructure you want; in my case, a binary protocol of my own design.

Some notes on getting the sample to work - they have the 'SSPI' library source, which best compiles under VS 2005, though I've gotten it to work under 2008; 2010 or above would require some rework since they use language constructs that were deprecated. You may also need to modify header files that are part of your platform SDK, because they make use of const pointer assignments to unconst variables, and I don't know a better way to make the compiler happy (I've never used C++/CLI before).

They do include a compiled SSPI dll in the Microsoft\Samples\Security\SSPI\bin folder. To get the client/server binaries to work, you have to copy that dll to their bin directory, else the fail assembly resolution.

So to summarize:

  • Go here to download the REMSSPI.exe sample self-extracting zip.
  • Extract the REMSSPI.exe file (twice..)
  • Microsoft\Samples\Security\SSPI\
    • bin\ - contains compiled dll Microsoft.Samples.Security.SSPI.dll
    • SSPI\ - contains source to dll
    • Sample\ - contains UI source code
      • bin\ - Contains build UI samples. Copy the SSPI.dll file here and run ControlPanel.Client.exe and ControlPanel.Server.exe
like image 193
antiduh Avatar answered Sep 22 '22 08:09

antiduh


You may ask: "How does the server confirm a client are who they say they are?"

Answer: If all the roundtrips of handshake could be finished successfully, i.e. both

  • InitializeSecurityContext returns "OK"
  • AcceptSecurityContext returns "OK"

it means the client's Windows login credentials have been confirmed to be real.

AcceptSecurityContext outputs a CtxtHandle security context (through the 6th parameter).

This context handle includes the client's Windows login username. The server can get the client's windows username by calling QueryContextAttributesEx:

SecPkgContext_NativeNames pinfo; QueryContextAttributesEx(&m_securitycontext, SECPKG_ATTR_NATIVE_NAMES, &pinfo); 

This populates a Native Names structure:

SecPkgContext_NativeNames  {    SEC_CHAR *sClientName;    SEC_CHAR *sServerName; } 

the value pinfo.sClientName is the client's real login user name.

Note: The previous handshakes already guarantee the truth of security context, so the server would believe pinfo.sClientName is just the client's real windows username.

like image 27
winnie_quest Avatar answered Sep 21 '22 08:09

winnie_quest