21 Commits
0.1 ... 0.1.3

Author SHA1 Message Date
Kevin Thompson
6b008f0e72 Bumped version number to 0.1.3
Needed to rebuild the nuget package due to a compilation mistake.
2017-05-01 09:59:15 -04:00
Kevin Thompson
8e68283df6 Added the nuspec file to the project. 2017-05-01 09:56:14 -04:00
Kevin Thompson
9862ee4aa4 Bumped version number to 0.1.2
Includes fix from #6.
2017-05-01 09:55:57 -04:00
Kevin Thompson
5cb0735213 Merge pull request #6 from matt-sullivan/master
Fix SSPIException serialization bug due to typo.
2017-04-30 16:39:25 -04:00
Matt Sullivan
5018ba17c2 Fix SSPIException serialization
It was failing due to a typo in a field name.
2017-05-01 00:10:56 +10:00
Kevin Thompson
5eeb3f874b Merge branch 'master' of https://github.com/antiduh/nsspi 2017-03-01 10:24:27 -05:00
Kevin Thompson
91f18604fe Added language declaration to nuspec 2017-01-20 16:36:24 -05:00
Kevin Thompson
c3b560cd17 Added link to nuget package. 2017-01-20 16:29:56 -05:00
Kevin Thompson
e7d93e0732 Added nuget spec for the core library 2017-01-20 16:20:02 -05:00
Kevin Thompson
1684280216 Removed unneceessary references
Got rid of dependencies that NSspi.csproj doesn't need.
2017-01-20 16:05:08 -05:00
Kevin Thompson
e93e20fa7f Added gitignore files
Marked all derived content directories as ignored.
2017-01-20 16:03:59 -05:00
Kevin Thompson
7a42da7f2c Removed old text-only readme file
Superseded by the markdown version.
2015-06-03 11:16:52 -04:00
Kevin Thompson
f8400caea6 Created a better readme file
Added links to the current release of source and binaries, a very-obvious link to to the 'releases' tab, added sectioning.
2015-06-03 11:16:07 -04:00
antiduh
447ca89baa Add information important to users
Clarified how the library can be used and how the data that comes out of the library (auth tokens) can be handled. It was very important to me when I was first developing this project that I get to choose my token transport mechanism so I can choose how to integrate it into my own app; I imagine lots of other developers are in the same boat.
2015-05-29 13:39:05 -04:00
antiduh
8cc4279e1d Fixed line endings so that the file formats well. 2015-05-28 17:32:41 -04:00
antiduh
4ede16318a Set the project's version number to what I currently expect. 2014-07-14 17:19:49 +00:00
antiduh
1374758ffb Fixed the number formatting in the SSPIException so that the error code comes out '0x....'. 2014-07-11 22:18:12 +00:00
antiduh
4bfe7d8bc9 Added a lifetime check in the ServerContext.ImpersonateClient method. 2014-07-11 22:16:12 +00:00
antiduh
8c19366314 Fixed the attribute usage and renamed the EnumMgr methods - FromText and ToText. 2014-07-11 21:32:06 +00:00
antiduh
3a134be9df Removed test code. 2014-07-11 21:29:53 +00:00
antiduh
50efc7702b Added rough support for attaching messages to errors. 2014-07-11 21:29:17 +00:00
15 changed files with 216 additions and 85 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.vs

2
NSspi/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

View File

@@ -183,14 +183,20 @@ namespace NSspi.Contexts
{
throw new ObjectDisposedException( "ServerContext" );
}
else if( this.Initialized == false )
{
throw new InvalidOperationException(
"The server context has not been completely initialized."
);
}
else if( impersonating )
{
throw new InvalidOperationException( "Cannot impersonate again while already impersonating." );
}
else if( this.SupportsImpersonate == false )
{
throw new InvalidOperationException(
"The ServerContext is using a security package that does not support impersonation."
throw new InvalidOperationException(
"The ServerContext is using a security package that does not support impersonation."
);
}

60
NSspi/EnumMgr.cs Normal file
View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace NSspi
{
[AttributeUsage( AttributeTargets.Field )]
public class EnumStringAttribute : Attribute
{
public EnumStringAttribute( string text )
{
this.Text = text;
}
public string Text { get; private set; }
}
public class EnumMgr
{
public static string ToText( Enum value )
{
FieldInfo field = value.GetType().GetField( value.ToString() );
EnumStringAttribute[] attribs = (EnumStringAttribute[])field.GetCustomAttributes( typeof( EnumStringAttribute ), false );
if( attribs == null || attribs.Length == 0 )
{
return null;
}
else
{
return attribs[0].Text;
}
}
public static T FromText<T>( string text )
{
FieldInfo[] fields = typeof( T ).GetFields();
EnumStringAttribute[] attribs;
foreach( FieldInfo field in fields )
{
attribs = (EnumStringAttribute[])field.GetCustomAttributes( typeof( EnumStringAttribute ), false );
foreach( EnumStringAttribute attrib in attribs )
{
if( attrib.Text == text )
{
return (T)field.GetValue( null );
}
}
}
throw new ArgumentException( "Could not find a matching enumeration value for the text '" + text + "'." );
}
}
}

View File

@@ -42,11 +42,7 @@
<Reference Include="System.Core" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ByteWriter.cs" />
@@ -59,6 +55,7 @@
<Compile Include="Contexts\ImpersonationHandle.cs" />
<Compile Include="Contexts\SafeContextHandle.cs" />
<Compile Include="Credentials\CurrentCredential.cs" />
<Compile Include="EnumMgr.cs" />
<Compile Include="SecPkgInfo.cs" />
<Compile Include="Contexts\ServerContext.cs" />
<Compile Include="Credentials\ClientCredential.cs" />
@@ -83,7 +80,9 @@
<Compile Include="SspiHandle.cs" />
<Compile Include="TimeStamp.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="NSspi.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

18
NSspi/NSspi.nuspec Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>NSspi</id>
<version>0.1.3.0</version>
<authors>Kevin Thompson</authors>
<owners>Kevin Thompson</owners>
<projectUrl>https://github.com/antiduh/nsspi</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
A C#/.Net interface to the Win32 SSPI authentication API,
better known as Windows Integrated Authentication.
</description>
<language>C#</language>
<releaseNotes>First release of NSspi.</releaseNotes>
<copyright>Copyright 2017</copyright>
</metadata>
</package>

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("0.1.3.0")]
[assembly: AssemblyFileVersion("0.1.2.0")]

View File

@@ -35,7 +35,7 @@ namespace NSspi
protected SSPIException( SerializationInfo info, StreamingContext context )
: base( info, context )
{
this.message = info.GetString( "messsage" );
this.message = info.GetString("message");
this.errorCode = (SecurityStatus)info.GetUInt32( "errorCode" );
}
@@ -70,7 +70,12 @@ namespace NSspi
{
get
{
return string.Format( "{0}. Error Code = '{1:X}'.", this.message, this.errorCode );
return string.Format(
"{0}. Error Code = '0x{1:X}' - \"{2}\".",
this.message,
this.errorCode,
EnumMgr.ToText(this.errorCode)
);
}
}
}

View File

@@ -30,56 +30,100 @@ namespace NSspi
/// <summary>
/// The request completed successfully
/// </summary>
[EnumString( "No error" )]
OK = 0x00000000,
/// <summary>
/// The token returned by the context needs to be provided to the cooperating party
/// to continue construction of the context.
/// </summary>
ContinueNeeded = 0x00090312,
[EnumString( "Authentication cycle needs to continue" )]
ContinueNeeded = 0x00090312,
/// <summary>
/// Occurs after a client calls InitializeSecurityContext to indicate that the client
/// must call CompleteAuthToken.
/// </summary>
[EnumString( "Authentication cycle needs to perform a 'complete'." )]
CompleteNeeded = 0x00090313,
/// <summary>
/// Occurs after a client calls InitializeSecurityContext to indicate that the client
/// must call CompleteAuthToken and pass the result to the server.
/// </summary>
CompAndContinue = 0x00090314,
[EnumString( "Authentication cycle needs to perform a 'complete' and then continue." )]
CompAndContinue = 0x00090314,
/// <summary>
/// An attempt to use the context was performed after the context's expiration time elapsed.
/// </summary>
ContextExpired = 0x00090317,
CredentialsNeeded = 0x00090320,
[EnumString( "The security context was used after its expiration time passed." )]
ContextExpired = 0x00090317,
[EnumString( "The credentials supplied to the security context were not fully initialized." )]
CredentialsNeeded = 0x00090320,
[EnumString( "The context data must be re-negotiated with the peer" )]
Renegotiate = 0x00090321,
// Errors
[EnumString( "Not enough memory.")]
OutOfMemory = 0x80090300,
[EnumString( "The handle provided to the API was invalid.")]
InvalidHandle = 0x80090301,
[EnumString( "The attempted operation is not supported")]
Unsupported = 0x80090302,
[EnumString( "The specified principle is not known in the authentication system.")]
TargetUnknown = 0x80090303,
[EnumString( "An internal error occurred" )]
InternalError = 0x80090304,
/// <summary>
/// No security provider package was found with the given name.
/// </summary>
[EnumString( "The requested security package was not found.")]
PackageNotFound = 0x80090305,
NotOwner = 0x80090306,
CannotInstall = 0x80090307,
/// <summary>
/// A token was provided that contained incorrect or corrupted data.
/// </summary>
[EnumString("The provided authentication token is invalid or corrupted.")]
InvalidToken = 0x80090308,
CannotPack = 0x80090309,
QopNotSupported = 0x8009030A,
/// <summary>
/// Impersonation is not supported.
/// </summary>
[EnumString("Impersonation is not supported with the current security package.")]
NoImpersonation = 0x8009030B,
[EnumString("The logon was denied, perhaps because the provided credentials were incorrect.")]
LogonDenied = 0x8009030C,
[EnumString( "The credentials provided are not recognized by the selected security package.")]
UnknownCredentials = 0x8009030D,
[EnumString( "No credentials are available in the selected security package.")]
NoCredentials = 0x8009030E,
[EnumString( "A message that was provided to the Decrypt or VerifySignature functions was altered " +
"after it was created.")]
MessageAltered = 0x8009030F,
[EnumString( "A message was received out of the expected order.")]
OutOfSequence = 0x80090310,
[EnumString( "The current security package cannot contact an authenticating authority.")]
NoAuthenticatingAuthority = 0x80090311,
/// <summary>

2
NsspiDemo/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

View File

@@ -1,70 +0,0 @@
This projects provides a C# / .Net interface to the Windows Integrated Authentication API,
better known as SSPI (Security Service Provider Interface).
The project is provided as a .Net 4.0 assembly, but can just as easily be upgraded to .Net 4.5
or later. The solution file can be opened by Visual Studio 2010 SP1, Visual Studio 2012, or
later Visual Studio editions.
The SSPI API provides an interface for real authentication protocols, such as Kerberos or
NTLM, to be invoked transparently by client and server code in order to perform authentication
and message manipulation. These authentication protocols are better known as 'security packages'.
The SSPI API exposes these packages using a common API, and so a program may invoke one or the
other with only minor changes in implementation. SSPI also supports the 'negotiate' 'meta'
package, that allows a client and server to decide dynamically which real security provider to
use, and then itself provides a passthrough interface to the real package.
==== Usage ====
Typically, a client acquires some form of a credential, either from the currently logged on
user's security context, by acquiring a username and password from the user, or by some other
means. The server acquires a credential in a similar manner. Each uses their credentials to
identify themselves to each other.
A client and a server each start with uninitialized security contexts. They exchange negotiation
and authentication tokens to perform authentication, and if all succeeds, they create a shared
security context in the form of a client's context and a server's context. The effectively shared
context agrees on the security package to use (kerberos, NTLM), and what parameters to use
for message passing. Every new client that authenticates with a server creates a new security
context specific to that client-server pairing.
From the software perspective, a client security context initializes itself by exchanging
authentication tokens with a server; the server initializes itself by exchanging authentication
tokens with the client.
This API provides raw access to the authentication tokens created during the negotiation and
authentication process. In this manner, any application can integrate SSPI-based authentication
by deciding for themselves how to integrate the tokens into their application protocol.
The project is broken up into 3 chunks:
* The NSspi library, which provides safe, managed access to the SSPI API.
* NsspiDemo, a quick demo program to show how to exercise the features of NSspi locally.
* UI demo programs TestClient and TestServer (that have a common dependency on TestProtocol) that
may be run on separate machines, that show how one might integrate SSPI into a custom
application.
==== More information ====
If you would like to understand the SSPI API, feel free to browse the following references:
MSDN documentation on the SSPI API
http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx
MSDN article on SSPI along with a sample Managed C++ SSPI library and UI client/servers.
http://msdn.microsoft.com/en-us/library/ms973911.aspx
Relevant StackOverflow questions:
"Client-server authentication - using SSPI?"
- http://stackoverflow.com/questions/17241365/
"Validate Windows Identity Token"
- http://stackoverflow.com/questions/11238141/
"How to deal with allocations in constrained execution regions?"
- http://stackoverflow.com/questions/24442209/
"AcquireCredentialsHandle returns massive expiration time"
- http://stackoverflow.com/questions/24478056/

2
TestClient/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

2
TestProtocol/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

2
TestServer/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

58
readme.md Normal file
View File

@@ -0,0 +1,58 @@
## Downloads ##
The latest release of NSspi is v0.1.1.
* [Source](https://github.com/antiduh/nsspi/archive/0.1.1.zip)
* [Binaries](https://github.com/antiduh/nsspi/releases/download/0.1.1/nsspi-0.1.1-bin.zip)
* [Nuget package](https://www.nuget.org/packages/NSspi)
You can also browse the list of [releases](https://github.com/antiduh/nsspi/releases).
## Introduction ##
This projects provides a C# / .Net interface to the Windows Integrated Authentication API, better known as SSPI (Security Service Provider Interface). This allows a custom client / server system to authenticate users using their existing logon credentials. This allows a developer to provide Single-Sign-On in their application.
## Overview ##
The API provides raw access to authentication tokens so that authentication can be easily integrated into any networking system - you can send the tokens over a socket, a remoting interface, or heck even a serial port if you want; they're just bytes. Clients and servers may exchange encrypted and signed messages, and the server can perform client impersonation.
The project is provided as a .Net 4.0 assembly, but can just as easily be upgraded to .Net 4.5 or later. The solution file can be opened by Visual Studio 2010 SP1, Visual Studio 2012, or later Visual Studio editions.
The SSPI API provides an interface for real authentication protocols, such as Kerberos or NTLM, to be invoked transparently by client and server code in order to perform authentication and message manipulation. These authentication protocols are better known as 'security packages'.
The SSPI API exposes these packages using a common API, and so a program may invoke one or the other with only minor changes in implementation. SSPI also supports the 'negotiate' 'meta' package, that allows a client and server to decide dynamically which real security provider to use, and then itself provides a passthrough interface to the real package.
## Usage ##
Typically, a client acquires some form of a credential, either from the currently logged on user's security context, by acquiring a username and password from the user, or by some other means. The server acquires a credential in a similar manner. Each uses their credentials to identify themselves to each other.
A client and a server each start with uninitialized security contexts. They exchange negotiation and authentication tokens to perform authentication, and if all succeeds, they create a shared security context in the form of a client's context and a server's context. The effectively shared context agrees on the security package to use (kerberos, NTLM), and what parameters to use for message passing. Every new client that authenticates with a server creates a new security context specific to that client-server pairing.
From the software perspective, a client security context initializes itself by exchanging authentication tokens with a server; the server initializes itself by exchanging authentication tokens with the client.
This API provides raw access to the authentication tokens created during the negotiation and authentication process. In this manner, any application can integrate SSPI-based authentication by deciding for themselves how to integrate the tokens into their application protocol.
The project is broken up into 3 chunks:
* The NSspi library, which provides safe, managed access to the SSPI API.
* NsspiDemo, a quick demo program to show how to exercise the features of NSspi locally.
* UI demo programs TestClient and TestServer (that have a common dependency on TestProtocol) that
may be run on separate machines, that show how one might integrate SSPI into a custom
application.
## More information ##
If you would like to understand the SSPI API, feel free to browse the following references:
MSDN documentation on the SSPI API:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx](http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731\(v=vs.85\).aspx)
MSDN article on SSPI along with a sample Managed C++ SSPI library and UI client/servers.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [http://msdn.microsoft.com/en-us/library/ms973911.aspx](http://msdn.microsoft.com/en-us/library/ms973911.aspx)
Relevant StackOverflow questions:
* [Client-server authentication - using SSPI?](http://stackoverflow.com/questions/17241365/)
* [Validate Windows Identity Token](http://stackoverflow.com/questions/11238141/)
* [How to deal with allocations in constrained execution regions?](http://stackoverflow.com/questions/24442209/)
* [AcquireCredentialsHandle returns massive expiration time](http://stackoverflow.com/questions/24478056/)