30 Commits

Author SHA1 Message Date
1bfa2f8ce4 Convert project to .NET 4.8 and add Wrap and Unwrap functionality to Encrypt and Decrypt messages 2023-10-06 09:28:43 -04:00
Kevin Thompson
3a7629fada Removed the binaries link. 2019-08-09 12:22:25 -04:00
Kevin Thompson
0b81172157 Update readme.md 2019-08-09 12:20:19 -04:00
Kevin Thompson
d49e27109e Bumped the version to 0.3.1. 2019-08-05 21:02:31 -04:00
Kevin Thompson
b655f5650e Fixed the project file to write out documentation properly. 2019-08-05 20:54:39 -04:00
Kevin Thompson
2bc74ddb4f Added the strong-name key for nsspi to the repo. 2019-08-05 20:41:56 -04:00
Kevin Thompson
1a7f60d3e1 Finished implementing GetRemoteIdentity. 2019-08-02 13:52:52 -04:00
Kevin Thompson
16bd8b2d68 Fixed the project to open with the right version of Visual Studio. 2019-07-19 16:43:11 -04:00
Kevin Thompson
06f1b08050 Added support to retrieve the remote identity. 2019-07-19 16:42:41 -04:00
Kevin Thompson
8c3126316f Published release 0.3.0 2019-06-16 22:05:10 -04:00
Kevin Thompson
9cd6edbeb7 Added the project license to the package information. 2019-06-16 21:53:52 -04:00
Kevin Thompson
ad88537c14 Updated copyright year. 2019-06-16 21:53:01 -04:00
Kevin Thompson
2611d94033 Added strong-name signing to the library. 2019-06-16 17:48:27 -04:00
Kevin Thompson
f892e1c93f Bumped the version number to 0.3.0.0; enabled output of docs. 2019-06-16 17:25:59 -04:00
Kevin Thompson
91f6a680cf Improved code style. 2019-06-16 17:24:43 -04:00
Kevin Thompson
52322afeaa Updated comments. 2019-06-16 17:22:50 -04:00
Kevin Thompson
002da1559b Fixed code style. 2019-06-16 17:22:21 -04:00
Kevin Thompson
01ad97b272 Removed unused code. 2019-06-16 17:21:14 -04:00
Kevin Thompson
ac4217d9d4 Updated comments. 2019-06-16 16:57:43 -04:00
Kevin Thompson
bbb7c7a060 Improved the impersonation revert process.
The Dispose(bool) method will still act even if finalizing, but it armors its access to the server to ensure that it doesn't accidentally cause a nullref trying to revert itself.
2019-06-16 16:57:23 -04:00
Kevin Thompson
4bd2ad0024 Merge pull request #19 from StefanOssendorf/feature/net-standard
Nsspi switched to SDK project style; targets .Net Framework 4.0 and .Net Standard 2.0. Demo projects unchanged.
2019-06-16 11:00:33 -04:00
Stefan Ossendorf
3ccdcc701e Nsspi targets now Net4.0 and .NetStandard2.0
Nsspi now multi targets .Net 4.0 and .NetStandard 2.0.
Dependencies are included based on framework.
2019-05-31 09:12:53 +02:00
Stefan Ossendorf
923d70195d Nsspi target framework changed to .NetStandard2.0
Nsspi targets now .NetStandard2.0
Other projects now targets .net4 .6.1
Nuspec file removed and nuget file will now be created on each build (new capaibility of VS17 used for that)
Assemblyinfo resieds now within csproj of nsspi project
ReSharpher folder added to gitignore
2019-05-30 14:46:03 +02:00
Kevin Thompson
56ca05b230 Fixed typo 2019-02-12 01:17:03 -05:00
Kevin Thompson
82eaae0570 Announced the release of v0.2.1. 2018-09-23 10:53:18 -04:00
Kevin Thompson
6bf95f46ee Updated version information to v0.2.1 2018-09-23 10:44:43 -04:00
Kevin Thompson
5c63105acf Merge pull request #12 from antiduh/pr/11
Pr/11 Integrate @SteveSyfuhs Thread.CurrentPrinciple changes
2018-04-01 18:10:28 -04:00
Kevin Thompson
19716405b8 Moved SetThreadIdentity into the ServerContext
The ImpersonationHandle class should probably stay as bare as possible since it's provided to the caller and we don't want to expose anything more than we need. Since the ServerContext is capable of performing this as a private method, move it there.
Updated the comments and variable names on the constructor to better indicate what exactly the option does, especially since modification of this property seems to be such a touchy subject.
2018-04-01 18:05:00 -04:00
Steve Syfuhs
f0820875c3 Fixed enum value. Any actual unicode strings passed in will only use the first character because the 0 byte after the first character is treated as a terminator.
Added ability to set the current thread principal so it's inline with the actual security context.
2018-03-30 11:40:37 -07:00
Kevin Thompson
8355a6b821 Fixed binaries url 2017-10-20 01:52:33 -04:00
42 changed files with 542 additions and 238 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
.vs
/_ReSharper.Caches

View File

@@ -1,4 +1,4 @@
Copyright (c) 2014, Kevin Thompson
Copyright (c) 2019, Kevin Thompson
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 16.0.28527.54
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{E93FBF1A-5198-44D6-BDF0-880D17F2B81A}"
EndProject

View File

@@ -1,6 +1,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Principal;
using NSspi.Buffers;
using NSspi.Credentials;
@@ -82,6 +83,11 @@ namespace NSspi.Contexts
/// </summary>
public bool Disposed { get; private set; }
/// <summary>
/// Constant for wrapping only...no encryption
/// </summary>
protected uint KERB_WRAP_NO_ENCRYPT = 0x80000001;
/// <summary>
/// Marks the context as having completed the initialization process, ie, exchanging of authentication tokens.
/// </summary>
@@ -117,6 +123,105 @@ namespace NSspi.Contexts
this.Disposed = true;
}
/// <summary>
/// Returns the identity of the remote entity.
/// </summary>
/// <returns></returns>
public IIdentity GetRemoteIdentity()
{
IIdentity result = null;
using( var tokenHandle = GetContextToken() )
{
bool gotRef = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
tokenHandle.DangerousAddRef( ref gotRef );
}
catch( Exception )
{
if( gotRef )
{
tokenHandle.DangerousRelease();
gotRef = false;
}
throw;
}
finally
{
try
{
result = new WindowsIdentity(
tokenHandle.DangerousGetHandle(),
this.Credential.SecurityPackage
);
}
finally
{
// Make sure we release the handle, even if the allocation for
// WindowsIdentity fails.
tokenHandle.DangerousRelease();
}
}
}
return result;
}
private SafeTokenHandle GetContextToken()
{
bool gotRef = false;
SecurityStatus status = SecurityStatus.InternalError;
SafeTokenHandle token;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
this.ContextHandle.DangerousAddRef( ref gotRef );
}
catch( Exception )
{
if( gotRef )
{
this.ContextHandle.DangerousRelease();
gotRef = false;
}
throw;
}
finally
{
if( gotRef )
{
try
{
status = ContextNativeMethods.QuerySecurityContextToken(
ref this.ContextHandle.rawHandle,
out token
);
}
finally
{
this.ContextHandle.DangerousRelease();
}
}
else
{
token = null;
}
}
if( status != SecurityStatus.OK )
{
throw new SSPIException( "Failed to query context token.", status );
}
return token;
}
/// <summary>
/// Encrypts the byte array using the context's session key.
/// </summary>
@@ -130,8 +235,9 @@ namespace NSspi.Contexts
/// - The padding buffer.
/// </remarks>
/// <param name="input">The raw message to encrypt.</param>
/// <param name="wrapOnly">Only wrap the message, no encryption</param>
/// <returns>The packed and encrypted message.</returns>
public byte[] Encrypt( byte[] input )
public byte[] Encrypt( byte[] input, bool wrapOnly = false )
{
// The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
SecPkgContext_Sizes sizes;
@@ -156,9 +262,14 @@ namespace NSspi.Contexts
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
{
uint qualityOfProtection = 0u;
if (wrapOnly)
{
qualityOfProtection = KERB_WRAP_NO_ENCRYPT;
}
status = ContextNativeMethods.SafeEncryptMessage(
this.ContextHandle,
0,
qualityOfProtection,
adapter,
0
);
@@ -212,8 +323,9 @@ namespace NSspi.Contexts
/// - The padding buffer.
/// </remarks>
/// <param name="input">The packed and encrypted data.</param>
/// <param name="unwrapOnly">Only wrap the message, no encryption</param>
/// <returns>The original plaintext message.</returns>
public byte[] Decrypt( byte[] input )
public byte[] Decrypt( byte[] input, bool unwrapOnly = false)
{
SecPkgContext_Sizes sizes;
@@ -293,9 +405,14 @@ namespace NSspi.Contexts
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
{
uint qualityOfProtection = 0u;
if (unwrapOnly)
{
qualityOfProtection = KERB_WRAP_NO_ENCRYPT;
}
status = ContextNativeMethods.SafeDecryptMessage(
this.ContextHandle,
0,
qualityOfProtection,
adapter,
0
);

View File

@@ -116,7 +116,16 @@ namespace NSspi.Contexts
/// </summary>
AcceptIntegrity = 0x00020000,
/// <summary>
/// Set by a client; indicates the context can only impersonate with limited privileges,
/// allowing the server only to identify the client when impersonating.
/// </summary>
InitIdentify = 0x00020000,
/// <summary>
/// Set by a server; indicates the context can only impersonate with limited privileges,
/// allowing the server only to identify the client when impersonating.
/// </summary>
AcceptIdentify = 0x00080000,
/// <summary>

View File

@@ -106,9 +106,9 @@ namespace NSspi.Contexts
[DllImport( "Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus EncryptMessage(
ref RawSspiHandle contextHandle,
int qualityOfProtection,
uint qualityOfProtection,
IntPtr bufferDescriptor,
int sequenceNumber
uint sequenceNumber
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
@@ -116,17 +116,17 @@ namespace NSspi.Contexts
internal static extern SecurityStatus DecryptMessage(
ref RawSspiHandle contextHandle,
IntPtr bufferDescriptor,
int sequenceNumber,
int qualityOfProtection
uint sequenceNumber,
uint qualityOfProtection
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
[DllImport( "Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus MakeSignature(
ref RawSspiHandle contextHandle,
int qualityOfProtection,
uint qualityOfProtection,
IntPtr bufferDescriptor,
int sequenceNumber
uint sequenceNumber
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
@@ -134,8 +134,8 @@ namespace NSspi.Contexts
internal static extern SecurityStatus VerifySignature(
ref RawSspiHandle contextHandle,
IntPtr bufferDescriptor,
int sequenceNumber,
int qualityOfProtection
uint sequenceNumber,
uint qualityOfProtection
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
@@ -174,6 +174,10 @@ namespace NSspi.Contexts
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle );
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
[DllImport( "Secur32.dll", EntryPoint = "QuerySecurityContextToken", SetLastError = true )]
internal static extern SecurityStatus QuerySecurityContextToken( ref RawSspiHandle contextHandle, [Out] out SafeTokenHandle handle );
[StructLayout( LayoutKind.Sequential )]
private class KeyStruct
{
@@ -251,9 +255,9 @@ namespace NSspi.Contexts
/// <returns></returns>
internal static SecurityStatus SafeEncryptMessage(
SafeContextHandle handle,
int qualityOfProtection,
uint qualityOfProtection,
SecureBufferAdapter bufferAdapter,
int sequenceNumber )
uint sequenceNumber )
{
SecurityStatus status = SecurityStatus.InternalError;
bool gotRef = false;
@@ -302,9 +306,9 @@ namespace NSspi.Contexts
/// <returns></returns>
internal static SecurityStatus SafeDecryptMessage(
SafeContextHandle handle,
int qualityOfProtection,
uint qualityOfProtection,
SecureBufferAdapter bufferAdapter,
int sequenceNumber )
uint sequenceNumber )
{
SecurityStatus status = SecurityStatus.InvalidHandle;
bool gotRef = false;
@@ -353,9 +357,9 @@ namespace NSspi.Contexts
/// <returns></returns>
internal static SecurityStatus SafeMakeSignature(
SafeContextHandle handle,
int qualityOfProtection,
uint qualityOfProtection,
SecureBufferAdapter adapter,
int sequenceNumber )
uint sequenceNumber )
{
bool gotRef = false;
SecurityStatus status = SecurityStatus.InternalError;
@@ -404,9 +408,9 @@ namespace NSspi.Contexts
/// <returns></returns>
internal static SecurityStatus SafeVerifySignature(
SafeContextHandle handle,
int qualityOfProtection,
uint qualityOfProtection,
SecureBufferAdapter adapter,
int sequenceNumber )
uint sequenceNumber )
{
bool gotRef = false;
SecurityStatus status = SecurityStatus.InternalError;

View File

@@ -1,4 +1,6 @@
using System;
using System.Security.Principal;
using System.Threading;
namespace NSspi.Contexts
{
@@ -16,8 +18,9 @@ namespace NSspi.Contexts
/// </remarks>
public class ImpersonationHandle : IDisposable
{
private readonly ServerContext server;
private bool disposed;
private ServerContext server;
/// <summary>
/// Initializes a new instance of the ImpersonationHandle. Does not perform impersonation.
@@ -29,13 +32,16 @@ namespace NSspi.Contexts
this.disposed = false;
}
/// <summary>
/// Finalizes the ImpersonationHandle by reverting the impersonation.
/// </summary>
~ImpersonationHandle()
{
Dispose( false );
}
/// <summary>
/// Reverts the impersonation.
/// Reverts impersonation.
/// </summary>
public void Dispose()
{
@@ -43,11 +49,27 @@ namespace NSspi.Contexts
GC.SuppressFinalize( this );
}
protected virtual void Dispose( bool disposing )
/// <summary>
/// Reverts impersonation.
/// </summary>
/// <param name="disposing">True if being disposed, false if being finalized.</param>
private void Dispose( bool disposing )
{
if( disposing && this.disposed == false && this.server != null && this.server.Disposed == false )
// This implements a variant of the typical dispose pattern. Always try to revert
// impersonation, even if finalizing. Don't do anything if we're already reverted.
if( this.disposed == false )
{
this.server.RevertImpersonate();
this.disposed = true;
// Just in case the reference is being pulled out from under us, pull a stable copy
// of the reference while we're null-checking.
var serverCopy = this.server;
if( serverCopy != null && serverCopy.Disposed == false )
{
serverCopy.RevertImpersonate();
}
}
}
}

View File

@@ -8,10 +8,17 @@ namespace NSspi.Contexts
/// </summary>
public class SafeContextHandle : SafeSspiHandle
{
/// <summary>
/// Initializes a new instance of the <see cref="SafeContextHandle"/> class.
/// </summary>
public SafeContextHandle()
: base()
{ }
/// <summary>
/// Releases the safe context handle.
/// </summary>
/// <returns></returns>
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
protected override bool ReleaseHandle()
{

View File

@@ -0,0 +1,27 @@
using System;
using System.Runtime.InteropServices;
namespace NSspi.Contexts
{
public class SafeTokenHandle : SafeHandle
{
public SafeTokenHandle() : base( IntPtr.Zero, true )
{
}
public override bool IsInvalid
{
get
{
return handle == IntPtr.Zero || handle == new IntPtr( -1 );
}
}
protected override bool ReleaseHandle()
{
NativeMethods.CloseHandle( this.handle );
return true;
}
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Security.Principal;
using System.Threading;
using NSspi.Buffers;
using NSspi.Credentials;
@@ -10,24 +12,31 @@ namespace NSspi.Contexts
/// </summary>
public class ServerContext : Context
{
private ContextAttrib requestedAttribs;
private ContextAttrib finalAttribs;
private readonly ContextAttrib requestedAttribs;
private readonly bool impersonationSetsThreadPrinciple;
private ContextAttrib finalAttribs;
private bool impersonating;
/// <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( Credential 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.impersonationSetsThreadPrinciple = impersonationSetsThreadPrinciple;
this.finalAttribs = ContextAttrib.Zero;
this.impersonating = false;
this.SupportsImpersonate = this.Credential.PackageInfo.Capabilities.HasFlag( SecPkgCapability.Impersonation );
}
@@ -127,8 +136,6 @@ namespace NSspi.Contexts
if( status == SecurityStatus.OK )
{
nextToken = null;
base.Initialize( rawExpiry.ToDateTime() );
if( outBuffer.Length != 0 )
@@ -220,7 +227,7 @@ namespace NSspi.Contexts
this.ContextHandle.DangerousRelease();
this.impersonating = true;
this.impersonating = status == SecurityStatus.OK;
}
}
@@ -237,6 +244,11 @@ namespace NSspi.Contexts
throw new SSPIException( "Failed to impersonate the client", status );
}
if( this.impersonating && this.impersonationSetsThreadPrinciple )
{
Thread.CurrentPrincipal = new WindowsPrincipal( (WindowsIdentity)GetRemoteIdentity() );
}
return handle;
}
@@ -282,6 +294,10 @@ namespace NSspi.Contexts
}
}
/// <summary>
/// Releases all resources associted with the ServerContext.
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose( bool disposing )
{
// We were disposed while impersonating. This means that the consumer that is currently holding

View File

@@ -50,6 +50,6 @@ namespace NSspi.Credentials
{
Ansi = 1,
Unicode = 1
Unicode = 2
}
}

View File

@@ -9,16 +9,16 @@ namespace NSspi.Credentials
/// </summary>
public class Credential : IDisposable
{
/// <summary>
/// The name of the security package that controls the credential.
/// </summary>
private readonly string securityPackage;
/// <summary>
/// Whether the Credential has been disposed.
/// </summary>
private bool disposed;
/// <summary>
/// The name of the security package that controls the credential.
/// </summary>
private string securityPackage;
/// <summary>
/// A safe handle to the credential's handle.
/// </summary>
@@ -35,11 +35,10 @@ namespace NSspi.Credentials
/// <param name="package">The security package to acquire the credential from.</param>
public Credential( string package )
{
this.disposed = false;
this.securityPackage = package;
this.disposed = false;
this.expiry = DateTime.MinValue;
this.PackageInfo = PackageSupport.GetPackageCapabilities( this.SecurityPackage );
}
@@ -178,6 +177,10 @@ namespace NSspi.Credentials
GC.SuppressFinalize( this );
}
/// <summary>
/// Releases all resources associted with the credential.
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose( bool disposing )
{
if( this.disposed == false )

View File

@@ -8,10 +8,17 @@ namespace NSspi.Credentials
/// </summary>
public class SafeCredentialHandle : SafeSspiHandle
{
/// <summary>
/// Initializes a new instance of the <see cref="SafeCredentialHandle"/> class.
/// </summary>
public SafeCredentialHandle()
: base()
{ }
/// <summary>
/// Releases the resources held by the credential handle.
/// </summary>
/// <returns></returns>
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
protected override bool ReleaseHandle()
{

View File

@@ -3,19 +3,38 @@ using System.Reflection;
namespace NSspi
{
/// <summary>
/// Tags an enumeration member with a string that can be programmatically accessed.
/// </summary>
[AttributeUsage( AttributeTargets.Field )]
public class EnumStringAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="EnumStringAttribute"/> class.
/// </summary>
/// <param name="text">The string to associate with the enumeration member.</param>
public EnumStringAttribute( string text )
{
this.Text = text;
}
/// <summary>
/// Gets the string associated with the enumeration member.
/// </summary>
public string Text { get; private set; }
}
/// <summary>
/// Converts betwen enumeration members and the strings associated to the members through the
/// <see cref="EnumStringAttribute"/> type.
/// </summary>
public class EnumMgr
{
/// <summary>
/// Gets the text associated with the given enumeration member through a <see cref="EnumStringAttribute"/>.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToText( Enum value )
{
FieldInfo field = value.GetType().GetField( value.ToString() );
@@ -32,6 +51,12 @@ namespace NSspi
}
}
/// <summary>
/// Returns the enumeration member that is tagged with the given text using the <see cref="EnumStringAttribute"/> type.
/// </summary>
/// <typeparam name="T">The enumeration type to inspect.</typeparam>
/// <param name="text"></param>
/// <returns></returns>
public static T FromText<T>( string text )
{
FieldInfo[] fields = typeof( T ).GetFields();

View File

@@ -1,97 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4B4CD933-BF62-4F92-B8FA-6771758C5197}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
<RootNamespace>NSspi</RootNamespace>
<AssemblyName>NSspi</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<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>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\NSspi.XML</DocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Kevin Thompson</Authors>
<PackageReleaseNotes>Adds support for accessing the remote identity.</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/antiduh/nsspi</PackageProjectUrl>
<Version>0.3.1.0</Version>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>nsspi key.snk</AssemblyOriginatorKeyFile>
<PackageLicenseFile>License.txt</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup>
<StartupObject>
</StartupObject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Data" />
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Security.Principal.Windows" Version="4.5.1" />
</ItemGroup>
<ItemGroup>
<Compile Include="ByteWriter.cs" />
<Compile Include="Contexts\ClientContext.cs" />
<Compile Include="Contexts\Context.cs" />
<Compile Include="Contexts\ContextAttrib.cs" />
<Compile Include="Contexts\ContextNativeMethods.cs" />
<Compile Include="Contexts\ContextQueries.cs" />
<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\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="NativeMethods.cs" />
<Compile Include="PackageSupport.cs" />
<Compile Include="PackageNames.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SecureBuffer\SecureBuffer.cs" />
<Compile Include="SecureBuffer\SecureBufferAdapter.cs" />
<Compile Include="SecureBuffer\SecureBufferDataRep.cs" />
<Compile Include="SecureBuffer\SecureBufferDesc.cs" />
<Compile Include="SecureBuffer\SecureBufferType.cs" />
<Compile Include="SecurityStatus.cs" />
<Compile Include="SSPIException.cs" />
<Compile Include="SspiHandle.cs" />
<Compile Include="TimeStamp.cs" />
<None Include="..\License.txt">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,18 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>NSspi</id>
<version>0.2.0.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 2017</copyright>
</metadata>
</package>

View File

@@ -17,5 +17,9 @@ 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 );
[DllImport( "Kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true )]
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
internal static extern bool CloseHandle( IntPtr handle );
}
}

View File

@@ -1,17 +1,4 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle( "NSspi" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "Kevin Thompson" )]
[assembly: AssemblyProduct( "NSspi" )]
[assembly: AssemblyCopyright( "Copyright © Kevin Thompson 2017" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
using System.Runtime.InteropServices;
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
@@ -19,17 +6,4 @@ using System.Runtime.InteropServices;
[assembly: ComVisible( false )]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid( "9abf710c-c646-42aa-8183-76bfa141a07b" )]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// 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.2.0.0" )]
[assembly: AssemblyFileVersion( "0.2.0.0" )]
[assembly: Guid( "9abf710c-c646-42aa-8183-76bfa141a07b" )]

View File

@@ -56,26 +56,48 @@ namespace NSspi
[EnumString( "The security context was used after its expiration time passed." )]
ContextExpired = 0x00090317,
/// <summary>
/// The credentials supplied to the security context were not fully initialized.
/// </summary>
[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" )]
/// <summary>
/// The context data must be re-negotiated with the peer.
/// </summary>
[EnumString( "The context data must be re-negotiated with the peer." )]
Renegotiate = 0x00090321,
// Errors
// -------------- Errors --------------
/// <summary>
/// The SSPI operation failed due to insufficient memory resources.
/// </summary>
[EnumString( "Not enough memory." )]
OutOfMemory = 0x80090300,
/// <summary>
/// The handle provided to the API was invalid.
/// </summary>
[EnumString( "The handle provided to the API was invalid." )]
InvalidHandle = 0x80090301,
[EnumString( "The attempted operation is not supported" )]
/// <summary>
/// The attempted operation is not supported.
/// </summary>
[EnumString( "The attempted operation is not supported." )]
Unsupported = 0x80090302,
/// <summary>
/// The specified principle is not known in the authentication system.
/// </summary>
[EnumString( "The specified principle is not known in the authentication system." )]
TargetUnknown = 0x80090303,
[EnumString( "An internal error occurred" )]
/// <summary>
/// An internal error occurred
/// </summary>
[EnumString( "An internal error occurred." )]
InternalError = 0x80090304,
/// <summary>
@@ -84,7 +106,16 @@ namespace NSspi
[EnumString( "The requested security package was not found." )]
PackageNotFound = 0x80090305,
/// <summary>
/// Cannot use the provided credentials, the caller is not the owner of the credentials.
/// </summary>
[EnumString( "The caller is not the owner of the desired credentials." )]
NotOwner = 0x80090306,
/// <summary>
/// The requested security package failed to initalize, and thus cannot be used.
/// </summary>
[EnumString( "The requested security package failed to initalize, and thus cannot be used." )]
CannotInstall = 0x80090307,
/// <summary>
@@ -93,7 +124,16 @@ namespace NSspi
[EnumString( "The provided authentication token is invalid or corrupted." )]
InvalidToken = 0x80090308,
/// <summary>
/// The security package is not able to marshall the logon buffer, so the logon attempt has failed
/// </summary>
[EnumString( "The security package is not able to marshall the logon buffer, so the logon attempt has failed." )]
CannotPack = 0x80090309,
/// <summary>
/// The per-message Quality of Protection is not supported by the security package.
/// </summary>
[EnumString( "The per-message Quality of Protection is not supported by the security package." )]
QopNotSupported = 0x8009030A,
/// <summary>
@@ -102,22 +142,41 @@ namespace NSspi
[EnumString( "Impersonation is not supported with the current security package." )]
NoImpersonation = 0x8009030B,
/// <summary>
/// The logon was denied, perhaps because the provided credentials were incorrect.
/// </summary>
[EnumString( "The logon was denied, perhaps because the provided credentials were incorrect." )]
LogonDenied = 0x8009030C,
/// <summary>
/// The credentials provided are not recognized by the selected security package.
/// </summary>
[EnumString( "The credentials provided are not recognized by the selected security package." )]
UnknownCredentials = 0x8009030D,
/// <summary>
/// No credentials are available in the selected security package.
/// </summary>
[EnumString( "No credentials are available in the selected security package." )]
NoCredentials = 0x8009030E,
/// <summary>
/// A message that was provided to the Decrypt or VerifySignature functions was altered after
/// it was created.
/// </summary>
[EnumString( "A message that was provided to the Decrypt or VerifySignature functions was altered " +
"after it was created." )]
"after it was created." )]
MessageAltered = 0x8009030F,
/// <summary>
/// A message was received out of the expected order.
/// </summary>
[EnumString( "A message was received out of the expected order." )]
OutOfSequence = 0x80090310,
/// <summary>
/// The current security package cannot contact an authenticating authority.
/// </summary>
[EnumString( "The current security package cannot contact an authenticating authority." )]
NoAuthenticatingAuthority = 0x80090311,
@@ -132,20 +191,87 @@ namespace NSspi
/// will indicate success, but will save off the extra, unrelated data in a buffer of
/// type 'extra'.
/// </remarks>
[EnumString( "The buffer provided to an SSPI API call contained a message that was not complete." )]
IncompleteMessage = 0x80090318,
/// <summary>
/// The credentials supplied were not complete, and could not be verified. The context could not be initialized.
/// </summary>
[EnumString( "The credentials supplied were not complete, and could not be verified. The context could not be initialized." )]
IncompleteCredentials = 0x80090320,
/// <summary>
/// The buffers supplied to a security function were too small.
/// </summary>
[EnumString( "The buffers supplied to a security function were too small." )]
BufferNotEnough = 0x80090321,
/// <summary>
/// The target principal name is incorrect.
/// </summary>
[EnumString( "The target principal name is incorrect." )]
WrongPrincipal = 0x80090322,
/// <summary>
/// The clocks on the client and server machines are skewed.
/// </summary>
[EnumString( "The clocks on the client and server machines are skewed." )]
TimeSkew = 0x80090324,
/// <summary>
/// The certificate chain was issued by an authority that is not trusted.
/// </summary>
[EnumString( "The certificate chain was issued by an authority that is not trusted." )]
UntrustedRoot = 0x80090325,
/// <summary>
/// The message received was unexpected or badly formatted.
/// </summary>
[EnumString( "The message received was unexpected or badly formatted." )]
IllegalMessage = 0x80090326,
/// <summary>
/// An unknown error occurred while processing the certificate.
/// </summary>
[EnumString( "An unknown error occurred while processing the certificate." )]
CertUnknown = 0x80090327,
/// <summary>
/// The received certificate has expired.
/// </summary>
[EnumString( "The received certificate has expired." )]
CertExpired = 0x80090328,
/// <summary>
/// The client and server cannot communicate, because they do not possess a common algorithm.
/// </summary>
[EnumString( "The client and server cannot communicate, because they do not possess a common algorithm." )]
AlgorithmMismatch = 0x80090331,
/// <summary>
/// The security context could not be established due to a failure in the requested quality
/// of service (e.g. mutual authentication or delegation).
/// </summary>
[EnumString( "The security context could not be established due to a failure in the requested " +
"quality of service (e.g. mutual authentication or delegation)." )]
SecurityQosFailed = 0x80090332,
/// <summary>
/// Smartcard logon is required and was not used.
/// </summary>
[EnumString( "Smartcard logon is required and was not used." )]
SmartcardLogonRequired = 0x8009033E,
/// <summary>
/// An unsupported preauthentication mechanism was presented to the Kerberos package.
/// </summary>
[EnumString( "An unsupported preauthentication mechanism was presented to the Kerberos package." )]
UnsupportedPreauth = 0x80090343,
/// <summary>
/// Client's supplied SSPI channel bindings were incorrect.
/// </summary>
[EnumString( "Client's supplied SSPI channel bindings were incorrect." )]
BadBinding = 0x80090346
}

View File

@@ -55,17 +55,27 @@ namespace NSspi
{
internal RawSspiHandle rawHandle;
/// <summary>
/// Initializes a new instance of the <see cref="SafeSspiHandle"/> class.
/// </summary>
protected SafeSspiHandle()
: base( IntPtr.Zero, true )
{
this.rawHandle = new RawSspiHandle();
}
/// <summary>
/// Gets whether the handle is invalid.
/// </summary>
public override bool IsInvalid
{
get { return IsClosed || this.rawHandle.IsZero(); }
}
/// <summary>
/// Marks the handle as no longer being in use.
/// </summary>
/// <returns></returns>
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
protected override bool ReleaseHandle()
{

View File

@@ -10,6 +10,9 @@ namespace NSspi
[StructLayout( LayoutKind.Sequential )]
public struct TimeStamp
{
/// <summary>
/// Returns the calendar date and time corresponding a zero timestamp.
/// </summary>
public static readonly DateTime Epoch = new DateTime( 1601, 1, 1, 0, 0, 0, DateTimeKind.Utc );
/// <summary>

BIN
NSspi/nsspi key.snk Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NsspiDemo</RootNamespace>
<AssemblyName>NsspiDemo</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,6 +32,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace NsspiDemo.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace NsspiDemo.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace TestClient.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace TestClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestClient</RootNamespace>
<AssemblyName>TestClient</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,6 +32,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />

View File

@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>

View File

@@ -93,10 +93,7 @@ namespace TestProtocol
try
{
if( this.Disconnected != null )
{
this.Disconnected();
}
this.Disconnected?.Invoke();
}
catch
{ }
@@ -178,7 +175,7 @@ namespace TestProtocol
{
this.Received( message );
}
catch( Exception e )
catch( Exception )
{ }
}
}

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace TestProtocol.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace TestProtocol.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestProtocol</RootNamespace>
<AssemblyName>TestProtocol</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,6 +32,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />

View File

@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace TestServer.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace TestServer.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -170,7 +170,8 @@
//
// impersonateButton
//
this.impersonateButton.Location = new System.Drawing.Point(262, 350);
this.impersonateButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.impersonateButton.Location = new System.Drawing.Point(262, 356);
this.impersonateButton.Name = "impersonateButton";
this.impersonateButton.Size = new System.Drawing.Size(116, 23);
this.impersonateButton.TabIndex = 4;

View File

@@ -1,14 +1,16 @@
using System;
using System.IO;
using System.Security.Principal;
using System.Text;
using System.Windows.Forms;
using NSspi;
using NSspi.Contexts;
using NSspi.Credentials;
using TestProtocol;
namespace TestServer
{
using System.IO;
using NSspi;
using NSspi.Contexts;
using NSspi.Credentials;
using Message = TestProtocol.Message;
public partial class ServerForm : Form
@@ -38,7 +40,8 @@ namespace TestServer
ContextAttrib.SequenceDetect |
ContextAttrib.MutualAuth |
ContextAttrib.Delegate |
ContextAttrib.Confidentiality
ContextAttrib.Confidentiality,
true
);
this.server = new CustomServer();
@@ -123,7 +126,11 @@ namespace TestServer
{
MessageBox.Show( "Starting impersonation: " + Environment.UserName );
FileStream stream = File.Create( Environment.GetFolderPath( Environment.SpecialFolder.DesktopDirectory ) + @"\test.txt" );
var directory = Environment.GetFolderPath( Environment.SpecialFolder.DesktopDirectory );
Directory.CreateDirectory( directory );
FileStream stream = File.Create( directory + @"\test.txt" );
StreamWriter writer = new StreamWriter( stream, Encoding.UTF8 );
writer.WriteLine( "Hello world." );
@@ -164,6 +171,32 @@ namespace TestServer
}
}
private void InitComplete()
{
UpdateButtons();
this.clientUsernameTextBox.Text = serverContext.ContextUserName;
var builder = new StringBuilder();
var remoteId = this.serverContext.GetRemoteIdentity();
builder.AppendLine( "Client identity information:" );
builder.AppendLine( " - Name: " + remoteId.Name );
var windowsId = remoteId as WindowsIdentity;
if( windowsId != null )
{
builder.AppendLine( " - User SID: " + windowsId.User.Value );
foreach( var claim in windowsId.Claims )
{
builder.AppendLine( " - " + claim.ToString() );
}
}
this.receivedTextbox.AppendText( builder.ToString() );
}
private void server_Disconnected()
{
this.running = true;
@@ -209,11 +242,7 @@ namespace TestServer
this.initializing = false;
this.connected = true;
this.Invoke( (Action)delegate ()
{
UpdateButtons();
this.clientUsernameTextBox.Text = serverContext.ContextUserName;
} );
this.Invoke( (Action)InitComplete );
}
}
else

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestServer</RootNamespace>
<AssemblyName>TestServer</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,6 +32,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />

View File

@@ -1,12 +1,10 @@
## Downloads ##
The latest release of NSspi is v0.2.0.
The latest release of NSspi is v0.3.1, released 5-Aug-2019.
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.
Version 0.3.1 adds support to obtain an IIdentity/WindowsPrinciple representing the remote connection. This is useful for servers that wish to query the properties on the principle, such as claims.
* [Source](https://github.com/antiduh/nsspi/archive/0.2.0.zip)
* [Binaries](https://github.com/antiduh/nsspi/releases/download/0.1.3/nsspi-0.2.0-bin.zip)
* [Source](https://github.com/antiduh/nsspi/archive/0.3.1.zip)
* [Nuget package](https://www.nuget.org/packages/NSspi)
You can also browse the list of [releases](https://github.com/antiduh/nsspi/releases).
@@ -14,7 +12,7 @@ You can also browse the list of [releases](https://github.com/antiduh/nsspi/rele
## 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.
This project 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.