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 )
|
public SecurityStatus Init( byte[] serverToken, out byte[] outToken )
|
||||||
{
|
{
|
||||||
long credHandle = base.Credential.CredentialHandle;
|
|
||||||
|
|
||||||
long prevContextHandle = base.ContextHandle;
|
long prevContextHandle = base.ContextHandle;
|
||||||
long newContextHandle = 0;
|
long newContextHandle = 0;
|
||||||
|
|
||||||
@@ -62,7 +60,7 @@ namespace NSspi.Contexts
|
|||||||
if ( prevContextHandle == 0 )
|
if ( prevContextHandle == 0 )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.InitializeSecurityContext_1(
|
status = ContextNativeMethods.InitializeSecurityContext_1(
|
||||||
ref credHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
this.serverPrinc,
|
this.serverPrinc,
|
||||||
this.requestedAttribs,
|
this.requestedAttribs,
|
||||||
@@ -81,7 +79,7 @@ namespace NSspi.Contexts
|
|||||||
using ( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
|
using ( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.InitializeSecurityContext_2(
|
status = ContextNativeMethods.InitializeSecurityContext_2(
|
||||||
ref credHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
ref prevContextHandle,
|
ref prevContextHandle,
|
||||||
this.serverPrinc,
|
this.serverPrinc,
|
||||||
this.requestedAttribs,
|
this.requestedAttribs,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace NSspi.Contexts
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus AcceptSecurityContext_1(
|
public static extern SecurityStatus AcceptSecurityContext_1(
|
||||||
ref long credHandle,
|
ref RawSspiHandle credHandle,
|
||||||
IntPtr oldContextHandle,
|
IntPtr oldContextHandle,
|
||||||
IntPtr inputBuffer,
|
IntPtr inputBuffer,
|
||||||
ContextAttrib requestedAttribs,
|
ContextAttrib requestedAttribs,
|
||||||
@@ -51,7 +51,7 @@ namespace NSspi.Contexts
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus AcceptSecurityContext_2(
|
public static extern SecurityStatus AcceptSecurityContext_2(
|
||||||
ref long credHandle,
|
ref RawSspiHandle credHandle,
|
||||||
ref long oldContextHandle,
|
ref long oldContextHandle,
|
||||||
IntPtr inputBuffer,
|
IntPtr inputBuffer,
|
||||||
ContextAttrib requestedAttribs,
|
ContextAttrib requestedAttribs,
|
||||||
@@ -104,7 +104,7 @@ namespace NSspi.Contexts
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus InitializeSecurityContext_1(
|
public static extern SecurityStatus InitializeSecurityContext_1(
|
||||||
ref long credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
IntPtr zero,
|
IntPtr zero,
|
||||||
string serverPrincipleName,
|
string serverPrincipleName,
|
||||||
ContextAttrib requiredAttribs,
|
ContextAttrib requiredAttribs,
|
||||||
@@ -126,7 +126,7 @@ namespace NSspi.Contexts
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus InitializeSecurityContext_2(
|
public static extern SecurityStatus InitializeSecurityContext_2(
|
||||||
ref long credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
ref long previousHandle,
|
ref long previousHandle,
|
||||||
string serverPrincipleName,
|
string serverPrincipleName,
|
||||||
ContextAttrib requiredAttribs,
|
ContextAttrib requiredAttribs,
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace NSspi.Contexts
|
|||||||
SecureBuffer clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
SecureBuffer clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
||||||
SecureBuffer outBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
|
SecureBuffer outBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
|
||||||
|
|
||||||
long credHandle = this.Credential.CredentialHandle;
|
|
||||||
long oldContextHandle = base.ContextHandle;
|
long oldContextHandle = base.ContextHandle;
|
||||||
long newContextHandle = 0;
|
long newContextHandle = 0;
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ namespace NSspi.Contexts
|
|||||||
if ( oldContextHandle == 0 )
|
if ( oldContextHandle == 0 )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.AcceptSecurityContext_1(
|
status = ContextNativeMethods.AcceptSecurityContext_1(
|
||||||
ref credHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
clientAdapter.Handle,
|
clientAdapter.Handle,
|
||||||
requestedAttribs,
|
requestedAttribs,
|
||||||
@@ -56,7 +55,7 @@ namespace NSspi.Contexts
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.AcceptSecurityContext_2(
|
status = ContextNativeMethods.AcceptSecurityContext_2(
|
||||||
ref credHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
ref oldContextHandle,
|
ref oldContextHandle,
|
||||||
clientAdapter.Handle,
|
clientAdapter.Handle,
|
||||||
requestedAttribs,
|
requestedAttribs,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.DirectoryServices.AccountManagement;
|
using System.DirectoryServices.AccountManagement;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -14,7 +15,7 @@ namespace NSspi
|
|||||||
|
|
||||||
private SecurityPackage securityPackage;
|
private SecurityPackage securityPackage;
|
||||||
|
|
||||||
private long credHandle;
|
private SafeCredentialHandle safeCredHandle;
|
||||||
private long expiry;
|
private long expiry;
|
||||||
|
|
||||||
public Credential(SecurityPackage package, CredentialType credentialType)
|
public Credential(SecurityPackage package, CredentialType credentialType)
|
||||||
@@ -22,7 +23,6 @@ namespace NSspi
|
|||||||
this.disposed = false;
|
this.disposed = false;
|
||||||
this.securityPackage = package;
|
this.securityPackage = package;
|
||||||
|
|
||||||
this.credHandle = 0;
|
|
||||||
this.expiry = 0;
|
this.expiry = 0;
|
||||||
|
|
||||||
Init( package, credentialType );
|
Init( package, credentialType );
|
||||||
@@ -66,17 +66,30 @@ namespace NSspi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -- Invoke --
|
// -- Invoke --
|
||||||
SecurityStatus status = NativeMethods.AcquireCredentialsHandle(
|
|
||||||
null,
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
packageName,
|
|
||||||
use,
|
this.safeCredHandle = new SafeCredentialHandle();
|
||||||
IntPtr.Zero,
|
|
||||||
IntPtr.Zero,
|
// The finally clause is the actual constrained region. The VM pre-allocates any stack space,
|
||||||
IntPtr.Zero,
|
// performs any allocations it needs to prepare methods for execution, and postpones any
|
||||||
IntPtr.Zero,
|
// instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
|
||||||
ref this.credHandle,
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
ref this.expiry
|
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 )
|
if ( status != SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
@@ -112,7 +125,7 @@ namespace NSspi
|
|||||||
string name = null;
|
string name = null;
|
||||||
|
|
||||||
status = NativeMethods.QueryCredentialsAttribute_Name(
|
status = NativeMethods.QueryCredentialsAttribute_Name(
|
||||||
ref this.credHandle,
|
ref this.safeCredHandle.rawHandle,
|
||||||
CredentialQueryAttrib.Names,
|
CredentialQueryAttrib.Names,
|
||||||
ref carrier
|
ref carrier
|
||||||
);
|
);
|
||||||
@@ -131,11 +144,11 @@ namespace NSspi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long CredentialHandle
|
public SafeCredentialHandle Handle
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.credHandle;
|
return this.safeCredHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,16 +162,12 @@ namespace NSspi
|
|||||||
{
|
{
|
||||||
if ( this.disposed == false )
|
if ( this.disposed == false )
|
||||||
{
|
{
|
||||||
SecurityStatus result;
|
if ( disposing )
|
||||||
|
{
|
||||||
result = NativeMethods.FreeCredentialsHandle( ref this.credHandle );
|
this.safeCredHandle.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
this.disposed = true;
|
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="SecureBuffer\SecureBufferType.cs" />
|
||||||
<Compile Include="SecurityStatus.cs" />
|
<Compile Include="SecurityStatus.cs" />
|
||||||
<Compile Include="SSPIException.cs" />
|
<Compile Include="SSPIException.cs" />
|
||||||
|
<Compile Include="SspiHandle.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace NSspi
|
|||||||
IntPtr packageData,
|
IntPtr packageData,
|
||||||
IntPtr getKeyFunc,
|
IntPtr getKeyFunc,
|
||||||
IntPtr getKeyData,
|
IntPtr getKeyData,
|
||||||
ref long credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
ref long expiry
|
ref long expiry
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ namespace NSspi
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus FreeCredentialsHandle(
|
public static extern SecurityStatus FreeCredentialsHandle(
|
||||||
ref long credentialHandle
|
ref RawSspiHandle credentialHandle
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -118,7 +118,7 @@ namespace NSspi
|
|||||||
SetLastError = true
|
SetLastError = true
|
||||||
)]
|
)]
|
||||||
public static extern SecurityStatus QueryCredentialsAttribute_Name(
|
public static extern SecurityStatus QueryCredentialsAttribute_Name(
|
||||||
ref long credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
CredentialQueryAttrib attributeName,
|
CredentialQueryAttrib attributeName,
|
||||||
ref QueryNameAttribCarrier name
|
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