Implemented SafeHandle usage for Context et al. The usage isn't actually safe yet, since I still reference the rawHandle without doing safe (CER) reference counting on the handle.

This commit is contained in:
antiduh
2014-06-24 19:41:19 +00:00
parent a681cc27c5
commit 6b3e395f7c
5 changed files with 72 additions and 49 deletions

View File

@@ -25,9 +25,6 @@ namespace NSspi.Contexts
public SecurityStatus Init( byte[] serverToken, out byte[] outToken )
{
long prevContextHandle = base.ContextHandle;
long newContextHandle = 0;
long expiry = 0;
SecurityStatus status;
@@ -38,11 +35,11 @@ namespace NSspi.Contexts
SecureBuffer serverBuffer;
SecureBufferAdapter serverAdapter;
if ( (serverToken != null) && (prevContextHandle == 0) )
if ( (serverToken != null) && ( this.ContextHandle.IsInvalid ) )
{
throw new InvalidOperationException( "Out-of-order usage detected - have a server token, but no previous client token had been created." );
}
else if ( (serverToken == null) && (prevContextHandle != 0) )
else if ( (serverToken == null) && ( this.ContextHandle.IsInvalid == false ) )
{
throw new InvalidOperationException( "Must provide the server's response when continuing the init process." );
}
@@ -55,9 +52,24 @@ namespace NSspi.Contexts
serverBuffer = new SecureBuffer( serverToken, BufferType.Token );
}
// Some notes on handles and invoking InitializeSecurityContext
// - The first time around, the phContext parameter (the 'old' handle) is a null pointer to what
// would be an RawSspiHandle, to indicate this is the first time it's being called.
// The phNewContext is a pointer (reference) to an RawSspiHandle struct of where to write the
// new handle's values.
// - The next time you invoke ISC, it takes a pointer to the handle it gave you last time in phContext,
// and takes a pointer to where it should write the new handle's values in phNewContext.
// - After the first time, you can provide the same handle to both parameters. From MSDN:
// "On the second call, phNewContext can be the same as the handle specified in the phContext
// parameter."
// It will overwrite the handle you gave it with the new handle value.
// - All handle structures themselves are actually *two* pointer variables, eg, 64 bits on 32-bit
// Windows, 128 bits on 64-bit Windows.
// - So in the end, on a 64-bit machine, we're passing a 64-bit value (the pointer to the struct) that
// points to 128 bits of memory (the struct itself) for where to write the handle numbers.
using ( outAdapter = new SecureBufferAdapter( outTokenBuffer ) )
{
if ( prevContextHandle == 0 )
if ( this.ContextHandle.IsInvalid )
{
status = ContextNativeMethods.InitializeSecurityContext_1(
ref this.Credential.Handle.rawHandle,
@@ -68,7 +80,7 @@ namespace NSspi.Contexts
SecureBufferDataRep.Network,
IntPtr.Zero,
0,
ref newContextHandle,
ref this.ContextHandle.rawHandle,
outAdapter.Handle,
ref this.finalAttribs,
ref expiry
@@ -80,14 +92,14 @@ namespace NSspi.Contexts
{
status = ContextNativeMethods.InitializeSecurityContext_2(
ref this.Credential.Handle.rawHandle,
ref prevContextHandle,
ref this.ContextHandle.rawHandle,
this.serverPrinc,
this.requestedAttribs,
0,
SecureBufferDataRep.Network,
serverAdapter.Handle,
0,
ref newContextHandle,
ref this.ContextHandle.rawHandle,
outAdapter.Handle,
ref this.finalAttribs,
ref expiry
@@ -114,8 +126,6 @@ namespace NSspi.Contexts
throw new SSPIException( "Failed to invoke InitializeSecurityContext for a client", status );
}
base.ContextHandle = newContextHandle;
return status;
}
}

View File

@@ -16,6 +16,8 @@ namespace NSspi
{
this.Credential = cred;
this.ContextHandle = new SafeContextHandle();
this.disposed = false;
}
@@ -26,7 +28,7 @@ namespace NSspi
protected Credential Credential { get; private set; }
public long ContextHandle { get; protected set; }
public SafeContextHandle ContextHandle { get; protected set; }
public string AuthorityName
{
@@ -59,10 +61,10 @@ namespace NSspi
this.Credential.Dispose();
}
long contextHandleCopy = this.ContextHandle;
ContextNativeMethods.DeleteSecurityContext( ref contextHandleCopy );
// TODO SAFE_CER
ContextNativeMethods.DeleteSecurityContext( ref this.ContextHandle.rawHandle );
this.ContextHandle = 0;
this.ContextHandle.Dispose();
this.disposed = true;
}
@@ -90,8 +92,6 @@ namespace NSspi
SecureBuffer paddingBuffer;
SecureBufferAdapter adapter;
long contextHandle = this.ContextHandle;
SecurityStatus status;
byte[] result;
@@ -103,8 +103,9 @@ namespace NSspi
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
{
// TODO SAFE_CER
status = ContextNativeMethods.EncryptMessage(
ref contextHandle,
ref this.ContextHandle.rawHandle,
0,
adapter.Handle,
0
@@ -154,9 +155,7 @@ namespace NSspi
SecureBuffer dataBuffer;
SecureBuffer paddingBuffer;
SecureBufferAdapter adapter;
long contextHandle = this.ContextHandle;
SecurityStatus status;
byte[] result = null;
int remaining;
@@ -221,8 +220,9 @@ namespace NSspi
using( adapter = new SecureBufferAdapter( new [] { trailerBuffer, dataBuffer, paddingBuffer } ) )
{
// TODO SAFE_CER
status = ContextNativeMethods.DecryptMessage(
ref contextHandle,
ref this.ContextHandle.rawHandle,
adapter.Handle,
0,
0
@@ -243,11 +243,11 @@ namespace NSspi
internal SecPkgContext_Sizes QueryBufferSizes()
{
SecPkgContext_Sizes sizes = new SecPkgContext_Sizes();
long contextHandle = this.ContextHandle;
SecurityStatus status;
// TODO SAFE_CER
status = ContextNativeMethods.QueryContextAttributes_Sizes(
ref contextHandle,
ref this.ContextHandle.rawHandle,
ContextQueryAttrib.Sizes,
ref sizes
);
@@ -263,7 +263,6 @@ namespace NSspi
internal string QueryContextString(ContextQueryAttrib attrib)
{
SecPkgContext_String stringAttrib;
long contextHandle;
SecurityStatus status;
string result;
@@ -274,10 +273,9 @@ namespace NSspi
stringAttrib = new SecPkgContext_String();
contextHandle = this.ContextHandle;
// TODO SAFE_CER
status = ContextNativeMethods.QueryContextAttributes_String(
ref contextHandle,
ref this.ContextHandle.rawHandle,
attrib,
ref stringAttrib
);

View File

@@ -36,7 +36,7 @@ namespace NSspi.Contexts
IntPtr inputBuffer,
ContextAttrib requestedAttribs,
SecureBufferDataRep dataRep,
ref long newContextHandle,
ref RawSspiHandle newContextHandle,
IntPtr outputBuffer,
ref ContextAttrib outputAttribs,
ref long expiry
@@ -52,11 +52,11 @@ namespace NSspi.Contexts
)]
public static extern SecurityStatus AcceptSecurityContext_2(
ref RawSspiHandle credHandle,
ref long oldContextHandle,
ref RawSspiHandle oldContextHandle,
IntPtr inputBuffer,
ContextAttrib requestedAttribs,
SecureBufferDataRep dataRep,
ref long newContextHandle,
ref RawSspiHandle newContextHandle,
IntPtr outputBuffer,
ref ContextAttrib outputAttribs,
ref long expiry
@@ -112,7 +112,7 @@ namespace NSspi.Contexts
SecureBufferDataRep dataRep,
IntPtr inputBuffer,
int reserved2,
ref long newContextHandle,
ref RawSspiHandle newContextHandle,
IntPtr outputBuffer,
ref ContextAttrib contextAttribs,
ref long expiry
@@ -127,14 +127,14 @@ namespace NSspi.Contexts
)]
public static extern SecurityStatus InitializeSecurityContext_2(
ref RawSspiHandle credentialHandle,
ref long previousHandle,
ref RawSspiHandle previousHandle,
string serverPrincipleName,
ContextAttrib requiredAttribs,
int reserved1,
SecureBufferDataRep dataRep,
IntPtr inputBuffer,
int reserved2,
ref long newContextHandle,
ref RawSspiHandle newContextHandle,
IntPtr outputBuffer,
ref ContextAttrib contextAttribs,
ref long expiry
@@ -147,7 +147,7 @@ namespace NSspi.Contexts
CharSet = CharSet.Unicode,
SetLastError = true
)]
public static extern SecurityStatus DeleteSecurityContext( ref long contextHandle );
public static extern SecurityStatus DeleteSecurityContext( ref RawSspiHandle contextHandle );
[DllImport(
"Secur32.dll",
@@ -157,7 +157,7 @@ namespace NSspi.Contexts
SetLastError = true
)]
public static extern SecurityStatus EncryptMessage(
ref long contextHandle,
ref RawSspiHandle contextHandle,
int qualityOfProtection,
IntPtr bufferDescriptor,
int sequenceNumber
@@ -172,7 +172,7 @@ namespace NSspi.Contexts
SetLastError = true
)]
public static extern SecurityStatus DecryptMessage(
ref long contextHandle,
ref RawSspiHandle contextHandle,
IntPtr bufferDescriptor,
int sequenceNumber,
int qualityOfProtection
@@ -184,7 +184,7 @@ namespace NSspi.Contexts
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode )]
public static extern SecurityStatus QueryContextAttributes_Sizes(
ref long contextHandle,
ref RawSspiHandle contextHandle,
ContextQueryAttrib attrib,
ref SecPkgContext_Sizes sizes
);
@@ -195,7 +195,7 @@ namespace NSspi.Contexts
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode )]
public static extern SecurityStatus QueryContextAttributes_String(
ref long contextHandle,
ref RawSspiHandle contextHandle,
ContextQueryAttrib attrib,
ref SecPkgContext_String names
);

View File

@@ -24,21 +24,17 @@ namespace NSspi.Contexts
SecureBuffer clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
SecureBuffer outBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
long oldContextHandle = base.ContextHandle;
long newContextHandle = 0;
SecurityStatus status;
long expiry = 0;
SecureBufferAdapter clientAdapter;
SecureBufferAdapter outAdapter;
using ( clientAdapter = new SecureBufferAdapter( clientBuffer ) )
{
using ( outAdapter = new SecureBufferAdapter( outBuffer ) )
{
if ( oldContextHandle == 0 )
if( this.ContextHandle.IsInvalid )
{
status = ContextNativeMethods.AcceptSecurityContext_1(
ref this.Credential.Handle.rawHandle,
@@ -46,7 +42,7 @@ namespace NSspi.Contexts
clientAdapter.Handle,
requestedAttribs,
SecureBufferDataRep.Network,
ref newContextHandle,
ref this.ContextHandle.rawHandle,
outAdapter.Handle,
ref this.finalAttribs,
ref expiry
@@ -56,15 +52,17 @@ namespace NSspi.Contexts
{
status = ContextNativeMethods.AcceptSecurityContext_2(
ref this.Credential.Handle.rawHandle,
ref oldContextHandle,
ref this.ContextHandle.rawHandle,
clientAdapter.Handle,
requestedAttribs,
SecureBufferDataRep.Network,
ref newContextHandle,
ref this.ContextHandle.rawHandle,
outAdapter.Handle,
ref this.finalAttribs,
ref expiry
);
}
}
}
@@ -96,8 +94,6 @@ namespace NSspi.Contexts
throw new SSPIException( "Failed to call AcceptSecurityContext", status );
}
base.ContextHandle = newContextHandle;
return status;
}
}

View File

@@ -6,6 +6,7 @@ using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using NSspi.Contexts;
namespace NSspi
{
@@ -83,4 +84,22 @@ namespace NSspi
return status == SecurityStatus.OK;
}
}
public class SafeContextHandle : SafeSspiHandle
{
public SafeContextHandle()
: base()
{ }
protected override bool ReleaseHandle()
{
SecurityStatus status = ContextNativeMethods.DeleteSecurityContext(
ref base.rawHandle
);
base.ReleaseHandle();
return status == SecurityStatus.OK;
}
}
}