Rough implementation of impersonation.
This commit is contained in:
@@ -13,15 +13,13 @@ namespace NSspi.Contexts
|
||||
{
|
||||
public class Context : IDisposable
|
||||
{
|
||||
private bool disposed;
|
||||
|
||||
public Context( Credential cred )
|
||||
{
|
||||
this.Credential = cred;
|
||||
|
||||
this.ContextHandle = new SafeContextHandle();
|
||||
|
||||
this.disposed = false;
|
||||
this.Disposed = false;
|
||||
this.Initialized = false;
|
||||
}
|
||||
|
||||
@@ -55,6 +53,8 @@ namespace NSspi.Contexts
|
||||
}
|
||||
}
|
||||
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose( true );
|
||||
@@ -63,7 +63,7 @@ namespace NSspi.Contexts
|
||||
|
||||
protected virtual void Dispose( bool disposing )
|
||||
{
|
||||
if( this.disposed ) { return; }
|
||||
if( this.Disposed ) { return; }
|
||||
|
||||
if( disposing )
|
||||
{
|
||||
@@ -72,7 +72,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
|
||||
|
||||
this.disposed = true;
|
||||
this.Disposed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -359,6 +359,10 @@ namespace NSspi.Contexts
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private void InitSecPkgInfo()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,11 +148,11 @@ namespace NSspi.Contexts
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "ImpersonateSecurityContext ", CharSet = CharSet.Unicode )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "ImpersonateSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus ImpersonateSecurityContext( ref RawSspiHandle contextHandle );
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext ", CharSet = CharSet.Unicode )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle );
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@ namespace NSspi.Contexts
|
||||
|
||||
protected virtual void Dispose( bool disposing )
|
||||
{
|
||||
|
||||
if( disposing && this.server != null && this.server.Disposed == false )
|
||||
{
|
||||
this.server.RevertImpersonate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Buffers;
|
||||
@@ -12,11 +13,15 @@ namespace NSspi.Contexts
|
||||
{
|
||||
private ContextAttrib requestedAttribs;
|
||||
private ContextAttrib finalAttribs;
|
||||
|
||||
|
||||
private bool impersonating;
|
||||
|
||||
public ServerContext(ServerCredential cred, ContextAttrib requestedAttribs) : base ( cred )
|
||||
{
|
||||
this.requestedAttribs = requestedAttribs;
|
||||
this.finalAttribs = ContextAttrib.Zero;
|
||||
|
||||
this.impersonating = false;
|
||||
}
|
||||
|
||||
public SecurityStatus AcceptToken( byte[] clientToken, out byte[] nextToken )
|
||||
@@ -81,6 +86,8 @@ namespace NSspi.Contexts
|
||||
{
|
||||
nextToken = null;
|
||||
}
|
||||
|
||||
InitProviderCapabilities();
|
||||
}
|
||||
else if ( status == SecurityStatus.ContinueNeeded )
|
||||
{
|
||||
@@ -96,5 +103,105 @@ namespace NSspi.Contexts
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public ImpersonationHandle ImpersonateClient()
|
||||
{
|
||||
ImpersonationHandle handle = new ImpersonationHandle( this );
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
bool gotRef = false;
|
||||
|
||||
if( impersonating )
|
||||
{
|
||||
throw new InvalidOperationException( "Cannot impersonate again while already impersonating." );
|
||||
}
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||
}
|
||||
catch( Exception )
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
this.ContextHandle.DangerousRelease();
|
||||
gotRef = false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
status = ContextNativeMethods.ImpersonateSecurityContext(
|
||||
ref this.ContextHandle.rawHandle
|
||||
);
|
||||
|
||||
this.ContextHandle.DangerousRelease();
|
||||
|
||||
this.impersonating = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( status == SecurityStatus.NoImpersonation )
|
||||
{
|
||||
throw new SSPIException( "Impersonation could not be performed.", status );
|
||||
}
|
||||
else if( status == SecurityStatus.Unsupported )
|
||||
{
|
||||
throw new SSPIException( "Impersonation is not supported by the security context's Security Support Provider.", status );
|
||||
}
|
||||
else if( status != SecurityStatus.OK )
|
||||
{
|
||||
throw new SSPIException( "Failed to impersonate the client", status );
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal void RevertImpersonate()
|
||||
{
|
||||
bool gotRef = false;
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
if( impersonating == false || this.Disposed )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||
}
|
||||
catch( Exception )
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
this.ContextHandle.DangerousRelease();
|
||||
gotRef = false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
status = ContextNativeMethods.RevertSecurityContext(
|
||||
ref this.ContextHandle.rawHandle
|
||||
);
|
||||
|
||||
this.ContextHandle.DangerousRelease();
|
||||
|
||||
this.impersonating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitProviderCapabilities()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user