Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bf95f46ee | ||
|
|
5c63105acf | ||
|
|
19716405b8 | ||
|
|
f0820875c3 | ||
|
|
8355a6b821 | ||
|
|
4d79f1b5db | ||
|
|
aef74fe8aa | ||
|
|
37a7881d25 | ||
|
|
9350412fb6 | ||
|
|
6a5e6056a7 | ||
|
|
c6c0ac623e | ||
|
|
c07abdaa62 | ||
|
|
f2d4541bab | ||
|
|
0eb8ff49f2 | ||
|
|
3b189d2865 | ||
|
|
6ff68d8812 | ||
|
|
e631d77f01 | ||
|
|
4e629a71b2 | ||
|
|
8db4b6d8a5 | ||
|
|
6b008f0e72 | ||
|
|
8e68283df6 | ||
|
|
9862ee4aa4 | ||
|
|
5cb0735213 | ||
|
|
5018ba17c2 | ||
|
|
5eeb3f874b | ||
|
|
91f18604fe | ||
|
|
c3b560cd17 | ||
|
|
e7d93e0732 | ||
|
|
1684280216 | ||
|
|
e93e20fa7f | ||
|
|
7a42da7f2c | ||
|
|
f8400caea6 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.vs
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{E93FBF1A-5198-44D6-BDF0-880D17F2B81A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProtocol", "TestProtocol\TestProtocol.csproj", "{9BFD94E1-D9FB-44D7-A6E7-8BAC2620E535}"
|
||||
|
||||
2
NSspi/.gitignore
vendored
Normal file
2
NSspi/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
@@ -38,7 +33,6 @@ namespace NSspi
|
||||
buffer[position + 1] = (byte)( value >> 16 );
|
||||
buffer[position + 2] = (byte)( value >> 8 );
|
||||
buffer[position + 3] = (byte)( value );
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Buffers;
|
||||
using NSspi.Credentials;
|
||||
|
||||
@@ -33,7 +28,7 @@ namespace NSspi.Contexts
|
||||
/// <param name="requestedAttribs">Requested attributes that describe the desired properties of the
|
||||
/// context once it is established. If a context cannot be established that satisfies the indicated
|
||||
/// properties, the context initialization is aborted.</param>
|
||||
public ClientContext( ClientCredential cred, string serverPrinc, ContextAttrib requestedAttribs )
|
||||
public ClientContext( Credential cred, string serverPrinc, ContextAttrib requestedAttribs )
|
||||
: base( cred )
|
||||
{
|
||||
this.serverPrinc = serverPrinc;
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Buffers;
|
||||
using NSspi.Contexts;
|
||||
using NSspi.Credentials;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
@@ -296,7 +291,6 @@ namespace NSspi.Contexts
|
||||
}
|
||||
// else there was no padding.
|
||||
|
||||
|
||||
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
|
||||
{
|
||||
status = ContextNativeMethods.SafeDecryptMessage(
|
||||
@@ -389,6 +383,35 @@ namespace NSspi.Contexts
|
||||
return outMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Session Key from a context or null on failure.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Session keys are sometimes needed for other purposes or HMAC functions. This function
|
||||
/// will run QueryAttribute to get the session key struct, and read and return the key from
|
||||
/// that struct.
|
||||
/// </remarks>
|
||||
/// <returns>byte[] with the session key data or null on failure</returns>
|
||||
public byte[] QuerySessionKey()
|
||||
{
|
||||
SecurityStatus status;
|
||||
|
||||
byte[] SessionKey = null;
|
||||
|
||||
status = ContextNativeMethods.SafeQueryContextAttribute(
|
||||
this.ContextHandle,
|
||||
ContextQueryAttrib.SessionKey,
|
||||
ref SessionKey
|
||||
);
|
||||
|
||||
if( status != SecurityStatus.OK )
|
||||
{
|
||||
throw new SSPIException( "Failed to query session key.", status );
|
||||
}
|
||||
|
||||
return SessionKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the signature of a signed message
|
||||
/// </summary>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
@@ -36,7 +32,6 @@ namespace NSspi.Contexts
|
||||
/// </summary>
|
||||
MutualAuth = 0x00000002,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature
|
||||
/// message support functionality.
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Buffers;
|
||||
using NSspi.Contexts;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
@@ -58,7 +53,6 @@ namespace NSspi.Contexts
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus AcceptSecurityContext_2(
|
||||
ref RawSspiHandle credHandle,
|
||||
@@ -72,7 +66,6 @@ namespace NSspi.Contexts
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus InitializeSecurityContext_1(
|
||||
ref RawSspiHandle credentialHandle,
|
||||
@@ -89,7 +82,6 @@ namespace NSspi.Contexts
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus InitializeSecurityContext_2(
|
||||
ref RawSspiHandle credentialHandle,
|
||||
@@ -110,7 +102,6 @@ namespace NSspi.Contexts
|
||||
[DllImport( "Secur32.dll", EntryPoint = "DeleteSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus DeleteSecurityContext( ref RawSspiHandle contextHandle );
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus EncryptMessage(
|
||||
@@ -163,11 +154,18 @@ namespace NSspi.Contexts
|
||||
ref SecPkgContext_String names
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus QueryContextAttributes(
|
||||
ref RawSspiHandle contextHandle,
|
||||
ContextQueryAttrib attrib,
|
||||
IntPtr attribute
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus FreeContextBuffer( IntPtr handle );
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "ImpersonateSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus ImpersonateSecurityContext( ref RawSspiHandle contextHandle );
|
||||
@@ -176,6 +174,72 @@ namespace NSspi.Contexts
|
||||
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle );
|
||||
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
private class KeyStruct
|
||||
{
|
||||
public int size;
|
||||
public IntPtr data;
|
||||
}
|
||||
|
||||
internal static SecurityStatus SafeQueryContextAttribute(
|
||||
SafeContextHandle handle,
|
||||
ContextQueryAttrib attribute,
|
||||
ref byte[] buffer
|
||||
)
|
||||
{
|
||||
bool gotRef = false;
|
||||
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
|
||||
int pointerSize = System.Environment.Is64BitOperatingSystem ? 8 : 4; //NOTE: update this when 128 bit processors exist
|
||||
IntPtr alloc_buffer = Marshal.AllocHGlobal( sizeof( uint ) + pointerSize ); //NOTE: this is at most 4 + sizeof(void*) bytes
|
||||
//see struct SecPkgContext_SessionKey
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380096(v=vs.85).aspx
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef( ref gotRef );
|
||||
}
|
||||
catch( Exception )
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
status = ContextNativeMethods.QueryContextAttributes(
|
||||
ref handle.rawHandle,
|
||||
attribute,
|
||||
alloc_buffer
|
||||
);
|
||||
if( status == SecurityStatus.OK )
|
||||
{
|
||||
KeyStruct key = new KeyStruct();
|
||||
|
||||
Marshal.PtrToStructure( alloc_buffer, key ); // fit to the proper size, read a byte[]
|
||||
|
||||
byte[] sizedBuffer = new byte[key.size];
|
||||
|
||||
for( int i = 0; i < key.size; i++ )
|
||||
sizedBuffer[i] = Marshal.ReadByte( key.data, i );
|
||||
|
||||
buffer = sizedBuffer;
|
||||
}
|
||||
handle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
Marshal.FreeHGlobal( alloc_buffer );
|
||||
return status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely invokes the native EncryptMessage function, making sure that handle ref counting is
|
||||
/// performed in a proper CER.
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
@@ -36,5 +32,15 @@ namespace NSspi.Contexts
|
||||
/// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
|
||||
/// </remarks>
|
||||
Authority = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Queries the context for it's neogtiated SessionKey
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Results for a query of this type are stored in a Win32 SecPkgContext_SessionKey structure
|
||||
/// </remarks>
|
||||
SessionKey = 9,
|
||||
|
||||
AccessToken = 13, //not implemented yet but this would be cool
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
@@ -54,6 +52,5 @@ namespace NSspi.Contexts
|
||||
this.server.RevertImpersonate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Contexts
|
||||
{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using NSspi.Buffers;
|
||||
using NSspi.Credentials;
|
||||
|
||||
@@ -18,19 +16,25 @@ namespace NSspi.Contexts
|
||||
private ContextAttrib finalAttribs;
|
||||
|
||||
private bool impersonating;
|
||||
private bool impersonationSetsThreadPrinciple;
|
||||
|
||||
/// <summary>
|
||||
/// Performs basic initialization of a new instance of the ServerContext class. The ServerContext
|
||||
/// is not ready for message manipulation until a security context has been established with a client.
|
||||
/// Performs basic initialization of a new instance of the ServerContext class. The
|
||||
/// ServerContext is not ready for message manipulation until a security context has been
|
||||
/// established with a client.
|
||||
/// </summary>
|
||||
/// <param name="cred"></param>
|
||||
/// <param name="requestedAttribs"></param>
|
||||
public ServerContext(ServerCredential cred, ContextAttrib requestedAttribs) : base ( cred )
|
||||
/// <param name="impersonationSetsThreadPrinciple">
|
||||
/// If true, the `Thread.CurrentPrinciple` property will be modified by successful impersonation.
|
||||
/// </param>
|
||||
public ServerContext( Credential cred, ContextAttrib requestedAttribs, bool impersonationSetsThreadPrinciple = false ) : base( cred )
|
||||
{
|
||||
this.requestedAttribs = requestedAttribs;
|
||||
this.finalAttribs = ContextAttrib.Zero;
|
||||
|
||||
this.impersonating = false;
|
||||
this.impersonationSetsThreadPrinciple = impersonationSetsThreadPrinciple;
|
||||
|
||||
this.SupportsImpersonate = this.Credential.PackageInfo.Capabilities.HasFlag( SecPkgCapability.Impersonation );
|
||||
}
|
||||
@@ -125,8 +129,6 @@ namespace NSspi.Contexts
|
||||
ref this.finalAttribs,
|
||||
ref rawExpiry
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,7 +228,7 @@ namespace NSspi.Contexts
|
||||
|
||||
this.ContextHandle.DangerousRelease();
|
||||
|
||||
this.impersonating = true;
|
||||
this.impersonating = status == SecurityStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +245,11 @@ namespace NSspi.Contexts
|
||||
throw new SSPIException( "Failed to impersonate the client", status );
|
||||
}
|
||||
|
||||
if( this.impersonating && this.impersonationSetsThreadPrinciple )
|
||||
{
|
||||
SetThreadPrinciple();
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -305,5 +312,15 @@ namespace NSspi.Contexts
|
||||
|
||||
base.Dispose( disposing );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current thread security context to the impersonated identity.
|
||||
/// </summary>
|
||||
private void SetThreadPrinciple()
|
||||
{
|
||||
Thread.CurrentPrincipal = new WindowsPrincipal(
|
||||
WindowsIdentity.GetCurrent( TokenAccessLevels.AllAccess )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
NSspi/Credentials/AuthData.cs
Normal file
55
NSspi/Credentials/AuthData.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides authentication data in native method calls.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implements the 'SEC_WINNT_AUTH_IDENTITY' structure. See:
|
||||
///
|
||||
/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380131(v=vs.85).aspx
|
||||
/// </remarks>
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
internal struct NativeAuthData
|
||||
{
|
||||
public NativeAuthData( string domain, string username, string password, NativeAuthDataFlag flag )
|
||||
{
|
||||
this.Domain = domain;
|
||||
this.DomainLength = domain.Length;
|
||||
|
||||
this.User = username;
|
||||
this.UserLength = username.Length;
|
||||
|
||||
this.Password = password;
|
||||
this.PasswordLength = password.Length;
|
||||
|
||||
this.Flags = flag;
|
||||
}
|
||||
|
||||
[MarshalAs( UnmanagedType.LPWStr )]
|
||||
public string User;
|
||||
|
||||
public int UserLength;
|
||||
|
||||
[MarshalAs( UnmanagedType.LPWStr )]
|
||||
public string Domain;
|
||||
|
||||
public int DomainLength;
|
||||
|
||||
[MarshalAs( UnmanagedType.LPWStr )]
|
||||
public string Password;
|
||||
|
||||
public int PasswordLength;
|
||||
|
||||
public NativeAuthDataFlag Flags;
|
||||
}
|
||||
|
||||
internal enum NativeAuthDataFlag : int
|
||||
{
|
||||
Ansi = 1,
|
||||
|
||||
Unicode = 2
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the credentials of the user running the current process, for use as an SSPI client.
|
||||
/// </summary>
|
||||
public class ClientCredential : CurrentCredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ClientCredential class.
|
||||
/// </summary>
|
||||
/// <param name="package">The security package to acquire the credential handle from.</param>
|
||||
public ClientCredential( string package )
|
||||
: base( package, CredentialUse.Outbound )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
20
NSspi/Credentials/ClientCurrentCredential.cs
Normal file
20
NSspi/Credentials/ClientCurrentCredential.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a handle to the credentials of the user running the current process, to be used to
|
||||
/// authenticate as a client.
|
||||
/// </summary>
|
||||
public class ClientCurrentCredential : CurrentCredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ClientCurrentCredential class.
|
||||
/// </summary>
|
||||
/// <param name="package">The security package to acquire the credential handle from.</param>
|
||||
public ClientCurrentCredential( string package )
|
||||
: base( package, CredentialUse.Outbound )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Credentials;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Credentials;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
@@ -25,13 +20,27 @@ namespace NSspi.Credentials
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "AcquireCredentialsHandle", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus AcquireCredentialsHandle_AuthData(
|
||||
string principleName,
|
||||
string packageName,
|
||||
CredentialUse credentialUse,
|
||||
IntPtr loginId,
|
||||
ref NativeAuthData authData,
|
||||
IntPtr getKeyFunc,
|
||||
IntPtr getKeyData,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "FreeCredentialsHandle", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus FreeCredentialsHandle(
|
||||
ref RawSspiHandle credentialHandle
|
||||
);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The overload of the QueryCredentialsAttribute method that is used for querying the name attribute.
|
||||
/// In this call, it takes a void* to a structure that contains a wide char pointer. The wide character
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
@@ -64,6 +60,5 @@ namespace NSspi.Credentials
|
||||
|
||||
this.Expiry = rawExpiry.ToDateTime();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
78
NSspi/Credentials/PasswordCredential.cs
Normal file
78
NSspi/Credentials/PasswordCredential.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents credentials acquired by providing a username, password, and domain.
|
||||
/// </summary>
|
||||
public class PasswordCredential : Credential
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the PasswordCredential class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is possible to acquire a valid handle to credentials that do not provide a valid
|
||||
/// username-password combination. The username and password are not validation until the
|
||||
/// authentication cycle begins.
|
||||
/// </remarks>
|
||||
/// <param name="domain">The domain to authenticate to.</param>
|
||||
/// <param name="username">The username of the user to authenticate as.</param>
|
||||
/// <param name="password">The user's password.</param>
|
||||
/// <param name="secPackage">The SSPI security package to create credentials for.</param>
|
||||
/// <param name="use">
|
||||
/// Specify inbound when acquiring credentials for a server; outbound for a client.
|
||||
/// </param>
|
||||
public PasswordCredential( string domain, string username, string password, string secPackage, CredentialUse use )
|
||||
: base( secPackage )
|
||||
{
|
||||
NativeAuthData authData = new NativeAuthData( domain, username, password, NativeAuthDataFlag.Unicode );
|
||||
|
||||
Init( authData, secPackage, use );
|
||||
}
|
||||
|
||||
private void Init( NativeAuthData authData, string secPackage, CredentialUse use )
|
||||
{
|
||||
string packageName;
|
||||
TimeStamp rawExpiry = new TimeStamp();
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
// -- Package --
|
||||
// Copy off for the call, since this.SecurityPackage is a property.
|
||||
packageName = this.SecurityPackage;
|
||||
|
||||
this.Handle = new SafeCredentialHandle();
|
||||
|
||||
|
||||
// The finally clause is the actual constrained region. The VM pre-allocates any stack space,
|
||||
// performs any allocations it needs to prepare methods for execution, and postpones any
|
||||
// instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
status = CredentialNativeMethods.AcquireCredentialsHandle_AuthData(
|
||||
null,
|
||||
packageName,
|
||||
use,
|
||||
IntPtr.Zero,
|
||||
ref authData,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
ref this.Handle.rawHandle,
|
||||
ref rawExpiry
|
||||
);
|
||||
}
|
||||
|
||||
if( status != SecurityStatus.OK )
|
||||
{
|
||||
throw new SSPIException( "Failed to call AcquireCredentialHandle", status );
|
||||
}
|
||||
|
||||
this.Expiry = rawExpiry.ToDateTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
@@ -28,5 +24,4 @@ namespace NSspi.Credentials
|
||||
return status == SecurityStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the credentials of the user running the current process, for use as an SSPI server.
|
||||
/// Represents a handle to the credentials of the user running the current process, to be used to
|
||||
/// authenticate as a server.
|
||||
/// </summary>
|
||||
public class ServerCredential : CurrentCredential
|
||||
public class ServerCurrentCredential : CurrentCredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ServerCredential class, acquiring credentials from
|
||||
/// the current thread's security context.
|
||||
/// </summary>
|
||||
/// <param name="package">The name of the security package to obtain credentials from.</param>
|
||||
public ServerCredential( string package )
|
||||
public ServerCurrentCredential( string package )
|
||||
: base( package, CredentialUse.Inbound )
|
||||
{
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DocumentationFile>bin\Debug\NSspi.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -42,11 +43,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" />
|
||||
@@ -58,18 +55,20 @@
|
||||
<Compile Include="Contexts\ContextQueryAttrib.cs" />
|
||||
<Compile Include="Contexts\ImpersonationHandle.cs" />
|
||||
<Compile Include="Contexts\SafeContextHandle.cs" />
|
||||
<Compile Include="Credentials\AuthData.cs" />
|
||||
<Compile Include="Credentials\ClientCurrentCredential.cs" />
|
||||
<Compile Include="Credentials\CurrentCredential.cs" />
|
||||
<Compile Include="Credentials\PasswordCredential.cs" />
|
||||
<Compile Include="Credentials\ServerCurrentCredential.cs" />
|
||||
<Compile Include="EnumMgr.cs" />
|
||||
<Compile Include="SecPkgInfo.cs" />
|
||||
<Compile Include="Contexts\ServerContext.cs" />
|
||||
<Compile Include="Credentials\ClientCredential.cs" />
|
||||
<Compile Include="Credentials\Credential.cs" />
|
||||
<Compile Include="Credentials\CredentialNativeMethods.cs" />
|
||||
<Compile Include="Credentials\CredentialQueryAttrib.cs" />
|
||||
<Compile Include="Credentials\CredentialUse.cs" />
|
||||
<Compile Include="Credentials\QueryNameSupport.cs" />
|
||||
<Compile Include="Credentials\SafeCredentialHandle.cs" />
|
||||
<Compile Include="Credentials\ServerCredential.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="PackageSupport.cs" />
|
||||
<Compile Include="PackageNames.cs" />
|
||||
@@ -84,7 +83,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
18
NSspi/NSspi.nuspec
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>NSspi</id>
|
||||
<version>0.2.1.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>Adds support for username/password credentials, but introduces a minor change in the interface that breaks existing code.</releaseNotes>
|
||||
<copyright>Copyright 2018</copyright>
|
||||
</metadata>
|
||||
</package>
|
||||
@@ -1,11 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Contexts;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
@@ -15,7 +10,6 @@ namespace NSspi
|
||||
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus FreeContextBuffer( IntPtr buffer );
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "QuerySecurityPackageInfo", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus QuerySecurityPackageInfo( string packageName, ref IntPtr pkgInfo );
|
||||
@@ -23,6 +17,5 @@ namespace NSspi
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "EnumerateSecurityPackages", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus EnumerateSecurityPackages( ref int numPackages, ref IntPtr pkgInfoArry );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
@@ -10,7 +9,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration( "" )]
|
||||
[assembly: AssemblyCompany( "Kevin Thompson" )]
|
||||
[assembly: AssemblyProduct( "NSspi" )]
|
||||
[assembly: AssemblyCopyright("Copyright © Kevin Thompson 2014")]
|
||||
[assembly: AssemblyCopyright( "Copyright © Kevin Thompson 2018" )]
|
||||
[assembly: AssemblyTrademark( "" )]
|
||||
[assembly: AssemblyCulture( "" )]
|
||||
|
||||
@@ -32,5 +31,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("0.1.1.0")]
|
||||
[assembly: AssemblyFileVersion("0.1.1.0")]
|
||||
[assembly: AssemblyVersion( "0.2.1.0" )]
|
||||
[assembly: AssemblyFileVersion( "0.2.1.0" )]
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
@@ -35,7 +31,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" );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Buffers
|
||||
{
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Buffers
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Buffers
|
||||
{
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Buffers
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Buffers
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
@@ -109,7 +105,6 @@ namespace NSspi
|
||||
[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,
|
||||
|
||||
@@ -138,6 +133,7 @@ namespace NSspi
|
||||
/// type 'extra'.
|
||||
/// </remarks>
|
||||
IncompleteMessage = 0x80090318,
|
||||
|
||||
IncompleteCredentials = 0x80090320,
|
||||
BufferNotEnough = 0x80090321,
|
||||
WrongPrincipal = 0x80090322,
|
||||
@@ -168,5 +164,4 @@ namespace NSspi
|
||||
return (uint)status > 0x80000000u;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Contexts;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
|
||||
2
NsspiDemo/.gitignore
vendored
Normal file
2
NsspiDemo/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
@@ -16,10 +16,10 @@ namespace NSspi
|
||||
|
||||
private static void CredTest( string packageName )
|
||||
{
|
||||
ClientCredential clientCred = null;
|
||||
ClientCurrentCredential clientCred = null;
|
||||
ClientContext client = null;
|
||||
|
||||
ServerCredential serverCred = null;
|
||||
ServerCurrentCredential serverCred = null;
|
||||
ServerContext server = null;
|
||||
|
||||
byte[] clientToken;
|
||||
@@ -30,8 +30,8 @@ namespace NSspi
|
||||
|
||||
try
|
||||
{
|
||||
clientCred = new ClientCredential( packageName );
|
||||
serverCred = new ServerCredential( packageName );
|
||||
clientCred = new ClientCurrentCredential( packageName );
|
||||
serverCred = new ServerCurrentCredential( packageName );
|
||||
|
||||
Console.Out.WriteLine( clientCred.PrincipleName );
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace NSspi
|
||||
ContextAttrib.Delegate
|
||||
);
|
||||
|
||||
|
||||
server = new ServerContext(
|
||||
serverCred,
|
||||
ContextAttrib.MutualAuth |
|
||||
@@ -75,7 +74,6 @@ namespace NSspi
|
||||
if( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
|
||||
}
|
||||
|
||||
|
||||
Console.Out.WriteLine( "Server authority: " + server.AuthorityName );
|
||||
Console.Out.WriteLine( "Server context user: " + server.ContextUserName );
|
||||
|
||||
@@ -117,10 +115,8 @@ namespace NSspi
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
|
||||
using( server.ImpersonateClient() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
cipherText = client.MakeSignature( plainText );
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
2
TestClient/.gitignore
vendored
Normal file
2
TestClient/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
@@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using NSspi;
|
||||
using NSspi.Contexts;
|
||||
@@ -20,7 +14,7 @@ namespace TestClient
|
||||
public partial class ClientForm : Form
|
||||
{
|
||||
private ClientContext context;
|
||||
private ClientCredential cred;
|
||||
private ClientCurrentCredential cred;
|
||||
|
||||
private CustomConnection connection;
|
||||
|
||||
@@ -48,7 +42,7 @@ namespace TestClient
|
||||
this.FormClosing += Form1_FormClosing;
|
||||
|
||||
// --- SSPI ---
|
||||
this.cred = new ClientCredential( PackageNames.Negotiate );
|
||||
this.cred = new ClientCurrentCredential( PackageNames.Negotiate );
|
||||
|
||||
this.context = new ClientContext(
|
||||
cred,
|
||||
@@ -107,7 +101,6 @@ namespace TestClient
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +109,6 @@ namespace TestClient
|
||||
this.connection.Stop();
|
||||
}
|
||||
|
||||
|
||||
private void encryptButton_Click( object sender, EventArgs e )
|
||||
{
|
||||
byte[] plaintext;
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TestClient
|
||||
{
|
||||
static class Program
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
private static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault( false );
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
2
TestProtocol/.gitignore
vendored
Normal file
2
TestProtocol/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using NSspi;
|
||||
|
||||
@@ -124,7 +120,6 @@ namespace TestProtocol
|
||||
// |--4 bytes--|--4 bytes--|---N--|
|
||||
// Every command is a TLV - | Operation | Length | Data |
|
||||
|
||||
|
||||
// Read the operation.
|
||||
this.socket.Receive( readBuffer, 4, SocketFlags.None );
|
||||
|
||||
@@ -153,7 +148,6 @@ namespace TestProtocol
|
||||
remaining -= chunkLength;
|
||||
position += chunkLength;
|
||||
}
|
||||
|
||||
}
|
||||
catch( SocketException e )
|
||||
{
|
||||
@@ -187,7 +181,6 @@ namespace TestProtocol
|
||||
catch( Exception e )
|
||||
{ }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,6 @@ namespace TestProtocol
|
||||
catch( Exception )
|
||||
{ }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
@@ -225,5 +224,4 @@ namespace TestProtocol
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TestProtocol
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TestProtocol
|
||||
{
|
||||
|
||||
2
TestServer/.gitignore
vendored
Normal file
2
TestServer/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
@@ -1,18 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TestServer
|
||||
{
|
||||
static class Program
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
private static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault( false );
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using TestProtocol;
|
||||
|
||||
@@ -19,7 +13,7 @@ namespace TestServer
|
||||
|
||||
public partial class ServerForm : Form
|
||||
{
|
||||
private ServerCredential serverCred;
|
||||
private ServerCurrentCredential serverCred;
|
||||
|
||||
private ServerContext serverContext;
|
||||
|
||||
@@ -35,7 +29,7 @@ namespace TestServer
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.serverCred = new ServerCredential( PackageNames.Negotiate );
|
||||
this.serverCred = new ServerCurrentCredential( PackageNames.Negotiate );
|
||||
|
||||
this.serverContext = new ServerContext(
|
||||
serverCred,
|
||||
@@ -150,7 +144,6 @@ namespace TestServer
|
||||
this.signButton.Enabled = this.connected;
|
||||
}
|
||||
|
||||
|
||||
private void server_Received( Message message )
|
||||
{
|
||||
if( message.Operation == ProtocolOp.ClientToken )
|
||||
@@ -177,7 +170,6 @@ namespace TestServer
|
||||
this.initializing = true;
|
||||
this.connected = false;
|
||||
|
||||
|
||||
this.serverContext.Dispose();
|
||||
this.serverContext = new ServerContext(
|
||||
serverCred,
|
||||
@@ -196,7 +188,6 @@ namespace TestServer
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
private void HandleInit( Message message )
|
||||
{
|
||||
byte[] nextToken;
|
||||
@@ -232,7 +223,6 @@ namespace TestServer
|
||||
MessageBox.Show( "Failed to accept token from client. Sspi error code: " + status );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +263,5 @@ namespace TestServer
|
||||
MessageBox.Show( "Received unexpected message from server. Message type: " + message.Operation );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,22 @@
|
||||
## Downloads ##
|
||||
|
||||
The latest release of NSspi is v0.2.0.
|
||||
|
||||
Version 0.2.0 adds the ability to authenticate using provided username/password credentials.
|
||||
**Please note** that v0.2.0 introduces a small change in the design that breaks backwards compatibility with previous verisons.
|
||||
|
||||
* [Source](https://github.com/antiduh/nsspi/archive/0.2.0.zip)
|
||||
* [Binaries](https://github.com/antiduh/nsspi/releases/download/0.2.0/nsspi-0.2.0-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.
|
||||
@@ -8,7 +25,7 @@ The SSPI API provides an interface for real authentication protocols, such as Ke
|
||||
|
||||
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 ====
|
||||
## 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.
|
||||
|
||||
@@ -26,25 +43,19 @@ The project is broken up into 3 chunks:
|
||||
may be run on separate machines, that show how one might integrate SSPI into a custom
|
||||
application.
|
||||
|
||||
==== More information ====
|
||||
## 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 documentation on the SSPI API:<br/>
|
||||
[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.
|
||||
http://msdn.microsoft.com/en-us/library/ms973911.aspx
|
||||
MSDN article on SSPI along with a sample Managed C++ SSPI library and UI client/servers.<br/>
|
||||
[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/
|
||||
* [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/)
|
||||
Reference in New Issue
Block a user