Fixed Credential using a fixed-size 64-bit handle; it's always 2 pointers.
Reworked the Credential handle into a SafeCredentialHandle. We still use references to the raw handle, which is unsafe, but I will hopefully rework that soon.
This commit is contained in:
@@ -25,8 +25,6 @@ namespace NSspi.Contexts
|
||||
|
||||
public SecurityStatus Init( byte[] serverToken, out byte[] outToken )
|
||||
{
|
||||
long credHandle = base.Credential.CredentialHandle;
|
||||
|
||||
long prevContextHandle = base.ContextHandle;
|
||||
long newContextHandle = 0;
|
||||
|
||||
@@ -62,7 +60,7 @@ namespace NSspi.Contexts
|
||||
if ( prevContextHandle == 0 )
|
||||
{
|
||||
status = ContextNativeMethods.InitializeSecurityContext_1(
|
||||
ref credHandle,
|
||||
ref this.Credential.Handle.rawHandle,
|
||||
IntPtr.Zero,
|
||||
this.serverPrinc,
|
||||
this.requestedAttribs,
|
||||
@@ -81,7 +79,7 @@ namespace NSspi.Contexts
|
||||
using ( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
|
||||
{
|
||||
status = ContextNativeMethods.InitializeSecurityContext_2(
|
||||
ref credHandle,
|
||||
ref this.Credential.Handle.rawHandle,
|
||||
ref prevContextHandle,
|
||||
this.serverPrinc,
|
||||
this.requestedAttribs,
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace NSspi.Contexts
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus AcceptSecurityContext_1(
|
||||
ref long credHandle,
|
||||
ref RawSspiHandle credHandle,
|
||||
IntPtr oldContextHandle,
|
||||
IntPtr inputBuffer,
|
||||
ContextAttrib requestedAttribs,
|
||||
@@ -51,7 +51,7 @@ namespace NSspi.Contexts
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus AcceptSecurityContext_2(
|
||||
ref long credHandle,
|
||||
ref RawSspiHandle credHandle,
|
||||
ref long oldContextHandle,
|
||||
IntPtr inputBuffer,
|
||||
ContextAttrib requestedAttribs,
|
||||
@@ -104,7 +104,7 @@ namespace NSspi.Contexts
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus InitializeSecurityContext_1(
|
||||
ref long credentialHandle,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
IntPtr zero,
|
||||
string serverPrincipleName,
|
||||
ContextAttrib requiredAttribs,
|
||||
@@ -126,7 +126,7 @@ namespace NSspi.Contexts
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus InitializeSecurityContext_2(
|
||||
ref long credentialHandle,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
ref long previousHandle,
|
||||
string serverPrincipleName,
|
||||
ContextAttrib requiredAttribs,
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace NSspi.Contexts
|
||||
SecureBuffer clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
||||
SecureBuffer outBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
|
||||
|
||||
long credHandle = this.Credential.CredentialHandle;
|
||||
long oldContextHandle = base.ContextHandle;
|
||||
long newContextHandle = 0;
|
||||
|
||||
@@ -42,7 +41,7 @@ namespace NSspi.Contexts
|
||||
if ( oldContextHandle == 0 )
|
||||
{
|
||||
status = ContextNativeMethods.AcceptSecurityContext_1(
|
||||
ref credHandle,
|
||||
ref this.Credential.Handle.rawHandle,
|
||||
IntPtr.Zero,
|
||||
clientAdapter.Handle,
|
||||
requestedAttribs,
|
||||
@@ -56,7 +55,7 @@ namespace NSspi.Contexts
|
||||
else
|
||||
{
|
||||
status = ContextNativeMethods.AcceptSecurityContext_2(
|
||||
ref credHandle,
|
||||
ref this.Credential.Handle.rawHandle,
|
||||
ref oldContextHandle,
|
||||
clientAdapter.Handle,
|
||||
requestedAttribs,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -14,7 +15,7 @@ namespace NSspi
|
||||
|
||||
private SecurityPackage securityPackage;
|
||||
|
||||
private long credHandle;
|
||||
private SafeCredentialHandle safeCredHandle;
|
||||
private long expiry;
|
||||
|
||||
public Credential(SecurityPackage package, CredentialType credentialType)
|
||||
@@ -22,7 +23,6 @@ namespace NSspi
|
||||
this.disposed = false;
|
||||
this.securityPackage = package;
|
||||
|
||||
this.credHandle = 0;
|
||||
this.expiry = 0;
|
||||
|
||||
Init( package, credentialType );
|
||||
@@ -66,17 +66,30 @@ namespace NSspi
|
||||
}
|
||||
|
||||
// -- Invoke --
|
||||
SecurityStatus status = NativeMethods.AcquireCredentialsHandle(
|
||||
null,
|
||||
packageName,
|
||||
use,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
ref this.credHandle,
|
||||
ref this.expiry
|
||||
);
|
||||
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
this.safeCredHandle = 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 = NativeMethods.AcquireCredentialsHandle(
|
||||
null,
|
||||
packageName,
|
||||
use,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
ref this.safeCredHandle.rawHandle,
|
||||
ref this.expiry
|
||||
);
|
||||
}
|
||||
|
||||
if ( status != SecurityStatus.OK )
|
||||
{
|
||||
@@ -112,7 +125,7 @@ namespace NSspi
|
||||
string name = null;
|
||||
|
||||
status = NativeMethods.QueryCredentialsAttribute_Name(
|
||||
ref this.credHandle,
|
||||
ref this.safeCredHandle.rawHandle,
|
||||
CredentialQueryAttrib.Names,
|
||||
ref carrier
|
||||
);
|
||||
@@ -131,11 +144,11 @@ namespace NSspi
|
||||
}
|
||||
}
|
||||
|
||||
public long CredentialHandle
|
||||
public SafeCredentialHandle Handle
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.credHandle;
|
||||
return this.safeCredHandle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,16 +162,12 @@ namespace NSspi
|
||||
{
|
||||
if ( this.disposed == false )
|
||||
{
|
||||
SecurityStatus result;
|
||||
|
||||
result = NativeMethods.FreeCredentialsHandle( ref this.credHandle );
|
||||
if ( disposing )
|
||||
{
|
||||
this.safeCredHandle.Dispose();
|
||||
}
|
||||
|
||||
this.disposed = true;
|
||||
|
||||
if ( disposing && result != SecurityStatus.OK )
|
||||
{
|
||||
throw new SSPIException( "Failed to release credentials handle", result );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<Compile Include="SecureBuffer\SecureBufferType.cs" />
|
||||
<Compile Include="SecurityStatus.cs" />
|
||||
<Compile Include="SSPIException.cs" />
|
||||
<Compile Include="SspiHandle.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace NSspi
|
||||
IntPtr packageData,
|
||||
IntPtr getKeyFunc,
|
||||
IntPtr getKeyData,
|
||||
ref long credentialHandle,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
ref long expiry
|
||||
);
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace NSspi
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus FreeCredentialsHandle(
|
||||
ref long credentialHandle
|
||||
ref RawSspiHandle credentialHandle
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -118,7 +118,7 @@ namespace NSspi
|
||||
SetLastError = true
|
||||
)]
|
||||
public static extern SecurityStatus QueryCredentialsAttribute_Name(
|
||||
ref long credentialHandle,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
CredentialQueryAttrib attributeName,
|
||||
ref QueryNameAttribCarrier name
|
||||
);
|
||||
|
||||
79
SspiHandle.cs
Normal file
79
SspiHandle.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
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;
|
||||
|
||||
namespace NSspi
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents any SSPI handle created for credential handles, context handles, and security package
|
||||
/// handles. Any SSPI handle is always the size of two native pointers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The documentation for SSPI handles can be found here:
|
||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa380495(v=vs.85).aspx
|
||||
///
|
||||
/// This class is not reference safe - if used directly, or referenced directly, it may be leaked,
|
||||
/// or subject to finalizer races, or any of the hundred of things SafeHandles were designed to fix.
|
||||
/// Do not directly use this class - use only though SafeHandle wrapper objects. Any reference needed
|
||||
/// to this handle for performing work (InitializeSecurityContext, eg), should be done through
|
||||
/// a second class SafeSspiHandleReference so that reference counting is properly executed.
|
||||
/// </remarks>
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 ) ]
|
||||
public struct RawSspiHandle
|
||||
{
|
||||
private IntPtr lowPart;
|
||||
private IntPtr highPart;
|
||||
|
||||
public bool IsZero()
|
||||
{
|
||||
return this.lowPart == IntPtr.Zero && this.highPart == IntPtr.Zero;
|
||||
}
|
||||
|
||||
// This guy has to be executed in a CER.
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success)]
|
||||
public void SetInvalid()
|
||||
{
|
||||
this.lowPart = IntPtr.Zero;
|
||||
this.highPart = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract class SafeSspiHandle : SafeHandle
|
||||
{
|
||||
internal RawSspiHandle rawHandle;
|
||||
|
||||
protected SafeSspiHandle()
|
||||
: base( IntPtr.Zero, true )
|
||||
{
|
||||
this.rawHandle = new RawSspiHandle();
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return IsClosed || this.rawHandle.IsZero(); }
|
||||
}
|
||||
}
|
||||
|
||||
public class SafeCredentialHandle : SafeSspiHandle
|
||||
{
|
||||
public SafeCredentialHandle()
|
||||
: base()
|
||||
{ }
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
SecurityStatus status = NativeMethods.FreeCredentialsHandle(
|
||||
ref base.rawHandle
|
||||
);
|
||||
|
||||
return status == SecurityStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user