From 5f3fd6416905025229661252b790ff5337cb4213 Mon Sep 17 00:00:00 2001 From: antiduh Date: Wed, 25 Jun 2014 20:12:46 +0000 Subject: [PATCH] Rough implementation of impersonation. --- Contexts/Context.cs | 16 +++-- Contexts/ContextNativeMethods.cs | 4 +- Contexts/ImpersonationHandle.cs | 5 +- Contexts/ServerContext.cs | 109 ++++++++++++++++++++++++++++++- 4 files changed, 124 insertions(+), 10 deletions(-) diff --git a/Contexts/Context.cs b/Contexts/Context.cs index 4dcca18..a694da6 100644 --- a/Contexts/Context.cs +++ b/Contexts/Context.cs @@ -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; } /// @@ -359,6 +359,10 @@ namespace NSspi.Contexts return result; } - + + private void InitSecPkgInfo() + { + + } } } diff --git a/Contexts/ContextNativeMethods.cs b/Contexts/ContextNativeMethods.cs index bff36a9..56971f6 100644 --- a/Contexts/ContextNativeMethods.cs +++ b/Contexts/ContextNativeMethods.cs @@ -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 ); diff --git a/Contexts/ImpersonationHandle.cs b/Contexts/ImpersonationHandle.cs index a104379..752e665 100644 --- a/Contexts/ImpersonationHandle.cs +++ b/Contexts/ImpersonationHandle.cs @@ -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(); + } } } diff --git a/Contexts/ServerContext.cs b/Contexts/ServerContext.cs index 24d5a50..39f66e5 100644 --- a/Contexts/ServerContext.cs +++ b/Contexts/ServerContext.cs @@ -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() + { + } } }