208 lines
6.6 KiB
C#
208 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using NSspi.Buffers;
|
|
using NSspi.Credentials;
|
|
|
|
namespace NSspi.Contexts
|
|
{
|
|
public class ServerContext : Context
|
|
{
|
|
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 )
|
|
{
|
|
SecureBuffer clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
|
SecureBuffer outBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
|
|
|
|
SecurityStatus status;
|
|
long expiry = 0;
|
|
|
|
SecureBufferAdapter clientAdapter;
|
|
SecureBufferAdapter outAdapter;
|
|
|
|
using ( clientAdapter = new SecureBufferAdapter( clientBuffer ) )
|
|
{
|
|
using ( outAdapter = new SecureBufferAdapter( outBuffer ) )
|
|
{
|
|
if( this.ContextHandle.IsInvalid )
|
|
{
|
|
status = ContextNativeMethods.AcceptSecurityContext_1(
|
|
ref this.Credential.Handle.rawHandle,
|
|
IntPtr.Zero,
|
|
clientAdapter.Handle,
|
|
requestedAttribs,
|
|
SecureBufferDataRep.Network,
|
|
ref this.ContextHandle.rawHandle,
|
|
outAdapter.Handle,
|
|
ref this.finalAttribs,
|
|
ref expiry
|
|
);
|
|
}
|
|
else
|
|
{
|
|
status = ContextNativeMethods.AcceptSecurityContext_2(
|
|
ref this.Credential.Handle.rawHandle,
|
|
ref this.ContextHandle.rawHandle,
|
|
clientAdapter.Handle,
|
|
requestedAttribs,
|
|
SecureBufferDataRep.Network,
|
|
ref this.ContextHandle.rawHandle,
|
|
outAdapter.Handle,
|
|
ref this.finalAttribs,
|
|
ref expiry
|
|
);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( status == SecurityStatus.OK )
|
|
{
|
|
nextToken = null;
|
|
this.Initialized = true;
|
|
|
|
if ( outBuffer.Length != 0 )
|
|
{
|
|
nextToken = new byte[outBuffer.Length];
|
|
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
|
}
|
|
else
|
|
{
|
|
nextToken = null;
|
|
}
|
|
|
|
InitProviderCapabilities();
|
|
}
|
|
else if ( status == SecurityStatus.ContinueNeeded )
|
|
{
|
|
this.Initialized = false;
|
|
|
|
nextToken = new byte[outBuffer.Length];
|
|
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
|
}
|
|
else
|
|
{
|
|
throw new SSPIException( "Failed to call AcceptSecurityContext", status );
|
|
}
|
|
|
|
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()
|
|
{
|
|
}
|
|
}
|
|
}
|