Merge pull request #8 from mcgov/master
Adding QuerySessionKey, as well as QueryContextAttributes and SafeQue…
This commit is contained in:
@@ -28,7 +28,7 @@ namespace NSspi.Contexts
|
||||
/// and the Initialize method has been called.
|
||||
/// </summary>
|
||||
/// <param name="cred"></param>
|
||||
protected Context( Credential cred )
|
||||
protected Context(Credential cred)
|
||||
{
|
||||
this.Credential = cred;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace NSspi.Contexts
|
||||
get
|
||||
{
|
||||
CheckLifecycle();
|
||||
return QueryContextString( ContextQueryAttrib.Authority );
|
||||
return QueryContextString(ContextQueryAttrib.Authority);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace NSspi.Contexts
|
||||
get
|
||||
{
|
||||
CheckLifecycle();
|
||||
return QueryContextString( ContextQueryAttrib.Names );
|
||||
return QueryContextString(ContextQueryAttrib.Names);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace NSspi.Contexts
|
||||
/// Marks the context as having completed the initialization process, ie, exchanging of authentication tokens.
|
||||
/// </summary>
|
||||
/// <param name="expiry">The date and time that the context will expire.</param>
|
||||
protected void Initialize( DateTime expiry )
|
||||
protected void Initialize(DateTime expiry)
|
||||
{
|
||||
this.Expiry = expiry;
|
||||
this.Initialized = true;
|
||||
@@ -102,19 +102,19 @@ namespace NSspi.Contexts
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose( true );
|
||||
GC.SuppressFinalize( this );
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases resources associated with the context.
|
||||
/// </summary>
|
||||
/// <param name="disposing">If true, release managed resources, else release only unmanaged resources.</param>
|
||||
protected virtual void Dispose( bool disposing )
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if( this.Disposed ) { return; }
|
||||
if (this.Disposed) { return; }
|
||||
|
||||
if( disposing )
|
||||
if (disposing)
|
||||
{
|
||||
this.ContextHandle.Dispose();
|
||||
}
|
||||
@@ -136,7 +136,7 @@ namespace NSspi.Contexts
|
||||
/// </remarks>
|
||||
/// <param name="input">The raw message to encrypt.</param>
|
||||
/// <returns>The packed and encrypted message.</returns>
|
||||
public byte[] Encrypt( byte[] input )
|
||||
public byte[] Encrypt(byte[] input)
|
||||
{
|
||||
// The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
|
||||
SecPkgContext_Sizes sizes;
|
||||
@@ -153,13 +153,13 @@ namespace NSspi.Contexts
|
||||
|
||||
sizes = QueryBufferSizes();
|
||||
|
||||
trailerBuffer = new SecureBuffer( new byte[sizes.SecurityTrailer], BufferType.Token );
|
||||
dataBuffer = new SecureBuffer( new byte[input.Length], BufferType.Data );
|
||||
paddingBuffer = new SecureBuffer( new byte[sizes.BlockSize], BufferType.Padding );
|
||||
trailerBuffer = new SecureBuffer(new byte[sizes.SecurityTrailer], BufferType.Token);
|
||||
dataBuffer = new SecureBuffer(new byte[input.Length], BufferType.Data);
|
||||
paddingBuffer = new SecureBuffer(new byte[sizes.BlockSize], BufferType.Padding);
|
||||
|
||||
Array.Copy( input, dataBuffer.Buffer, input.Length );
|
||||
Array.Copy(input, dataBuffer.Buffer, input.Length);
|
||||
|
||||
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
|
||||
using (adapter = new SecureBufferAdapter(new[] { trailerBuffer, dataBuffer, paddingBuffer }))
|
||||
{
|
||||
status = ContextNativeMethods.SafeEncryptMessage(
|
||||
this.ContextHandle,
|
||||
@@ -169,9 +169,9 @@ namespace NSspi.Contexts
|
||||
);
|
||||
}
|
||||
|
||||
if( status != SecurityStatus.OK )
|
||||
if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException( "Failed to encrypt message", status );
|
||||
throw new SSPIException("Failed to encrypt message", status);
|
||||
}
|
||||
|
||||
int position = 0;
|
||||
@@ -183,24 +183,24 @@ namespace NSspi.Contexts
|
||||
// -- The encrypted message
|
||||
result = new byte[2 + 4 + 2 + trailerBuffer.Length + dataBuffer.Length + paddingBuffer.Length];
|
||||
|
||||
ByteWriter.WriteInt16_BE( (short)trailerBuffer.Length, result, position );
|
||||
ByteWriter.WriteInt16_BE((short)trailerBuffer.Length, result, position);
|
||||
position += 2;
|
||||
|
||||
ByteWriter.WriteInt32_BE( dataBuffer.Length, result, position );
|
||||
ByteWriter.WriteInt32_BE(dataBuffer.Length, result, position);
|
||||
position += 4;
|
||||
|
||||
ByteWriter.WriteInt16_BE( (short)paddingBuffer.Length, result, position );
|
||||
ByteWriter.WriteInt16_BE((short)paddingBuffer.Length, result, position);
|
||||
position += 2;
|
||||
|
||||
Array.Copy( trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length );
|
||||
Array.Copy(trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length);
|
||||
position += trailerBuffer.Length;
|
||||
|
||||
Array.Copy( dataBuffer.Buffer, 0, result, position, dataBuffer.Length );
|
||||
Array.Copy(dataBuffer.Buffer, 0, result, position, dataBuffer.Length);
|
||||
position += dataBuffer.Length;
|
||||
|
||||
Array.Copy( paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length );
|
||||
Array.Copy(paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length);
|
||||
position += paddingBuffer.Length;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace NSspi.Contexts
|
||||
/// </remarks>
|
||||
/// <param name="input">The packed and encrypted data.</param>
|
||||
/// <returns>The original plaintext message.</returns>
|
||||
public byte[] Decrypt( byte[] input )
|
||||
public byte[] Decrypt(byte[] input)
|
||||
{
|
||||
SecPkgContext_Sizes sizes;
|
||||
|
||||
@@ -241,63 +241,63 @@ namespace NSspi.Contexts
|
||||
sizes = QueryBufferSizes();
|
||||
|
||||
// This check is required, but not sufficient. We could be stricter.
|
||||
if( input.Length < 2 + 4 + 2 + sizes.SecurityTrailer )
|
||||
if (input.Length < 2 + 4 + 2 + sizes.SecurityTrailer)
|
||||
{
|
||||
throw new ArgumentException( "Buffer is too small to possibly contain an encrypted message" );
|
||||
throw new ArgumentException("Buffer is too small to possibly contain an encrypted message");
|
||||
}
|
||||
|
||||
position = 0;
|
||||
|
||||
trailerLength = ByteWriter.ReadInt16_BE( input, position );
|
||||
trailerLength = ByteWriter.ReadInt16_BE(input, position);
|
||||
position += 2;
|
||||
|
||||
dataLength = ByteWriter.ReadInt32_BE( input, position );
|
||||
dataLength = ByteWriter.ReadInt32_BE(input, position);
|
||||
position += 4;
|
||||
|
||||
paddingLength = ByteWriter.ReadInt16_BE( input, position );
|
||||
paddingLength = ByteWriter.ReadInt16_BE(input, position);
|
||||
position += 2;
|
||||
|
||||
if ( trailerLength + dataLength + paddingLength + 2 + 4 + 2 > input.Length )
|
||||
if (trailerLength + dataLength + paddingLength + 2 + 4 + 2 > input.Length)
|
||||
{
|
||||
throw new ArgumentException( "The buffer contains invalid data - the embedded length data does not add up." );
|
||||
throw new ArgumentException("The buffer contains invalid data - the embedded length data does not add up.");
|
||||
}
|
||||
|
||||
trailerBuffer = new SecureBuffer( new byte[trailerLength], BufferType.Token );
|
||||
dataBuffer = new SecureBuffer( new byte[dataLength], BufferType.Data );
|
||||
paddingBuffer = new SecureBuffer( new byte[paddingLength], BufferType.Padding );
|
||||
trailerBuffer = new SecureBuffer(new byte[trailerLength], BufferType.Token);
|
||||
dataBuffer = new SecureBuffer(new byte[dataLength], BufferType.Data);
|
||||
paddingBuffer = new SecureBuffer(new byte[paddingLength], BufferType.Padding);
|
||||
|
||||
remaining = input.Length - position;
|
||||
|
||||
if( trailerBuffer.Length <= remaining )
|
||||
if (trailerBuffer.Length <= remaining)
|
||||
{
|
||||
Array.Copy( input, position, trailerBuffer.Buffer, 0, trailerBuffer.Length );
|
||||
Array.Copy(input, position, trailerBuffer.Buffer, 0, trailerBuffer.Length);
|
||||
position += trailerBuffer.Length;
|
||||
remaining -= trailerBuffer.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException( "Input is missing data - it is not long enough to contain a fully encrypted message" );
|
||||
throw new ArgumentException("Input is missing data - it is not long enough to contain a fully encrypted message");
|
||||
}
|
||||
|
||||
if( dataBuffer.Length <= remaining )
|
||||
|
||||
if (dataBuffer.Length <= remaining)
|
||||
{
|
||||
Array.Copy( input, position, dataBuffer.Buffer, 0, dataBuffer.Length );
|
||||
Array.Copy(input, position, dataBuffer.Buffer, 0, dataBuffer.Length);
|
||||
position += dataBuffer.Length;
|
||||
remaining -= dataBuffer.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException( "Input is missing data - it is not long enough to contain a fully encrypted message" );
|
||||
throw new ArgumentException("Input is missing data - it is not long enough to contain a fully encrypted message");
|
||||
}
|
||||
|
||||
if( paddingBuffer.Length <= remaining )
|
||||
if (paddingBuffer.Length <= remaining)
|
||||
{
|
||||
Array.Copy( input, position, paddingBuffer.Buffer, 0, paddingBuffer.Length );
|
||||
Array.Copy(input, position, paddingBuffer.Buffer, 0, paddingBuffer.Length);
|
||||
}
|
||||
// else there was no padding.
|
||||
|
||||
|
||||
using( adapter = new SecureBufferAdapter( new [] { trailerBuffer, dataBuffer, paddingBuffer } ) )
|
||||
|
||||
using (adapter = new SecureBufferAdapter(new[] { trailerBuffer, dataBuffer, paddingBuffer }))
|
||||
{
|
||||
status = ContextNativeMethods.SafeDecryptMessage(
|
||||
this.ContextHandle,
|
||||
@@ -307,13 +307,13 @@ namespace NSspi.Contexts
|
||||
);
|
||||
}
|
||||
|
||||
if( status != SecurityStatus.OK )
|
||||
if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException( "Failed to encrypt message", status );
|
||||
throw new SSPIException("Failed to encrypt message", status);
|
||||
}
|
||||
|
||||
result = new byte[dataBuffer.Length];
|
||||
Array.Copy( dataBuffer.Buffer, 0, result, 0, dataBuffer.Length );
|
||||
Array.Copy(dataBuffer.Buffer, 0, result, 0, dataBuffer.Length);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -330,7 +330,7 @@ namespace NSspi.Contexts
|
||||
/// </remarks>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] MakeSignature( byte[] message )
|
||||
public byte[] MakeSignature(byte[] message)
|
||||
{
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
@@ -343,12 +343,12 @@ namespace NSspi.Contexts
|
||||
|
||||
sizes = QueryBufferSizes();
|
||||
|
||||
dataBuffer = new SecureBuffer( new byte[message.Length], BufferType.Data );
|
||||
signatureBuffer = new SecureBuffer( new byte[sizes.MaxSignature], BufferType.Token );
|
||||
dataBuffer = new SecureBuffer(new byte[message.Length], BufferType.Data);
|
||||
signatureBuffer = new SecureBuffer(new byte[sizes.MaxSignature], BufferType.Token);
|
||||
|
||||
Array.Copy( message, dataBuffer.Buffer, message.Length );
|
||||
Array.Copy(message, dataBuffer.Buffer, message.Length);
|
||||
|
||||
using ( adapter = new SecureBufferAdapter( new[] { dataBuffer, signatureBuffer } ) )
|
||||
using (adapter = new SecureBufferAdapter(new[] { dataBuffer, signatureBuffer }))
|
||||
{
|
||||
status = ContextNativeMethods.SafeMakeSignature(
|
||||
this.ContextHandle,
|
||||
@@ -358,9 +358,9 @@ namespace NSspi.Contexts
|
||||
);
|
||||
}
|
||||
|
||||
if ( status != SecurityStatus.OK )
|
||||
if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException( "Failed to create message signature.", status );
|
||||
throw new SSPIException("Failed to create message signature.", status);
|
||||
}
|
||||
|
||||
byte[] outMessage;
|
||||
@@ -374,21 +374,51 @@ namespace NSspi.Contexts
|
||||
|
||||
outMessage = new byte[4 + 2 + dataBuffer.Length + signatureBuffer.Length];
|
||||
|
||||
ByteWriter.WriteInt32_BE( dataBuffer.Length, outMessage, position );
|
||||
ByteWriter.WriteInt32_BE(dataBuffer.Length, outMessage, position);
|
||||
position += 4;
|
||||
|
||||
ByteWriter.WriteInt16_BE( (Int16)signatureBuffer.Length, outMessage, position );
|
||||
ByteWriter.WriteInt16_BE((Int16)signatureBuffer.Length, outMessage, position);
|
||||
position += 2;
|
||||
|
||||
Array.Copy( dataBuffer.Buffer, 0, outMessage, position, dataBuffer.Length );
|
||||
Array.Copy(dataBuffer.Buffer, 0, outMessage, position, dataBuffer.Length);
|
||||
position += dataBuffer.Length;
|
||||
|
||||
Array.Copy( signatureBuffer.Buffer, 0, outMessage, position, signatureBuffer.Length );
|
||||
Array.Copy(signatureBuffer.Buffer, 0, outMessage, position, signatureBuffer.Length);
|
||||
position += signatureBuffer.Length;
|
||||
|
||||
return outMessage;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Session Key from a context or null on failure.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Session keys are sometimes needed for other purposes or HMAC functions. This function will run QueryAttribute to get the session key struct, and read and return the key from that struct.
|
||||
/// </remarks>
|
||||
///
|
||||
/// <returns>byte[] with the session key data or null on failure</returns>
|
||||
public byte[] QuerySessionKey()
|
||||
{
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
byte[] SessionKey = null;
|
||||
|
||||
status = ContextNativeMethods.SafeQueryContextAttribute(
|
||||
this.ContextHandle,
|
||||
ContextQueryAttrib.SessionKey,
|
||||
ref SessionKey
|
||||
);
|
||||
|
||||
if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException("Failed to query session key.", status);
|
||||
}
|
||||
|
||||
return SessionKey;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the signature of a signed message
|
||||
/// </summary>
|
||||
@@ -402,7 +432,7 @@ namespace NSspi.Contexts
|
||||
/// <param name="signedMessage">The packed signed message.</param>
|
||||
/// <param name="origMessage">The extracted original message.</param>
|
||||
/// <returns>True if the message has a valid signature, false otherwise.</returns>
|
||||
public bool VerifySignature( byte[] signedMessage, out byte[] origMessage )
|
||||
public bool VerifySignature(byte[] signedMessage, out byte[] origMessage)
|
||||
{
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
@@ -414,36 +444,36 @@ namespace NSspi.Contexts
|
||||
CheckLifecycle();
|
||||
|
||||
sizes = QueryBufferSizes();
|
||||
|
||||
if ( signedMessage.Length < 2 + 4 + sizes.MaxSignature )
|
||||
|
||||
if (signedMessage.Length < 2 + 4 + sizes.MaxSignature)
|
||||
{
|
||||
throw new ArgumentException( "Input message is too small to possibly fit a valid message" );
|
||||
throw new ArgumentException("Input message is too small to possibly fit a valid message");
|
||||
}
|
||||
|
||||
int position = 0;
|
||||
int messageLen;
|
||||
int sigLen;
|
||||
|
||||
messageLen = ByteWriter.ReadInt32_BE( signedMessage, 0 );
|
||||
messageLen = ByteWriter.ReadInt32_BE(signedMessage, 0);
|
||||
position += 4;
|
||||
|
||||
sigLen = ByteWriter.ReadInt16_BE( signedMessage, position );
|
||||
sigLen = ByteWriter.ReadInt16_BE(signedMessage, position);
|
||||
position += 2;
|
||||
|
||||
if ( messageLen + sigLen + 2 + 4 > signedMessage.Length )
|
||||
if (messageLen + sigLen + 2 + 4 > signedMessage.Length)
|
||||
{
|
||||
throw new ArgumentException( "The buffer contains invalid data - the embedded length data does not add up." );
|
||||
throw new ArgumentException("The buffer contains invalid data - the embedded length data does not add up.");
|
||||
}
|
||||
|
||||
dataBuffer = new SecureBuffer( new byte[messageLen], BufferType.Data );
|
||||
Array.Copy( signedMessage, position, dataBuffer.Buffer, 0, messageLen );
|
||||
dataBuffer = new SecureBuffer(new byte[messageLen], BufferType.Data);
|
||||
Array.Copy(signedMessage, position, dataBuffer.Buffer, 0, messageLen);
|
||||
position += messageLen;
|
||||
|
||||
signatureBuffer = new SecureBuffer( new byte[sigLen], BufferType.Token );
|
||||
Array.Copy( signedMessage, position, signatureBuffer.Buffer, 0, sigLen );
|
||||
signatureBuffer = new SecureBuffer(new byte[sigLen], BufferType.Token);
|
||||
Array.Copy(signedMessage, position, signatureBuffer.Buffer, 0, sigLen);
|
||||
position += sigLen;
|
||||
|
||||
using ( adapter = new SecureBufferAdapter( new[] { dataBuffer, signatureBuffer } ) )
|
||||
using (adapter = new SecureBufferAdapter(new[] { dataBuffer, signatureBuffer }))
|
||||
{
|
||||
status = ContextNativeMethods.SafeVerifySignature(
|
||||
this.ContextHandle,
|
||||
@@ -453,20 +483,20 @@ namespace NSspi.Contexts
|
||||
);
|
||||
}
|
||||
|
||||
if ( status == SecurityStatus.OK )
|
||||
if (status == SecurityStatus.OK)
|
||||
{
|
||||
origMessage = dataBuffer.Buffer;
|
||||
return true;
|
||||
}
|
||||
else if ( status == SecurityStatus.MessageAltered ||
|
||||
status == SecurityStatus.OutOfSequence )
|
||||
else if (status == SecurityStatus.MessageAltered ||
|
||||
status == SecurityStatus.OutOfSequence)
|
||||
{
|
||||
origMessage = null;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SSPIException( "Failed to determine the veracity of a signed message.", status );
|
||||
throw new SSPIException("Failed to determine the veracity of a signed message.", status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,11 +513,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||
this.ContextHandle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch ( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
this.ContextHandle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -497,7 +527,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.QueryContextAttributes_Sizes(
|
||||
ref this.ContextHandle.rawHandle,
|
||||
@@ -508,9 +538,9 @@ namespace NSspi.Contexts
|
||||
}
|
||||
}
|
||||
|
||||
if( status != SecurityStatus.OK )
|
||||
if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException( "Failed to query context buffer size attributes", status );
|
||||
throw new SSPIException("Failed to query context buffer size attributes", status);
|
||||
}
|
||||
|
||||
return sizes;
|
||||
@@ -528,9 +558,9 @@ namespace NSspi.Contexts
|
||||
string result = null;
|
||||
bool gotRef = false;
|
||||
|
||||
if( attrib != ContextQueryAttrib.Names && attrib != ContextQueryAttrib.Authority )
|
||||
if (attrib != ContextQueryAttrib.Names && attrib != ContextQueryAttrib.Authority)
|
||||
{
|
||||
throw new InvalidOperationException( "QueryContextString can only be used to query context Name and Authority attributes" );
|
||||
throw new InvalidOperationException("QueryContextString can only be used to query context Name and Authority attributes");
|
||||
}
|
||||
|
||||
stringAttrib = new SecPkgContext_String();
|
||||
@@ -538,11 +568,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||
this.ContextHandle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch ( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
this.ContextHandle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -551,7 +581,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.QueryContextAttributes_String(
|
||||
ref this.ContextHandle.rawHandle,
|
||||
@@ -561,21 +591,21 @@ namespace NSspi.Contexts
|
||||
|
||||
this.ContextHandle.DangerousRelease();
|
||||
|
||||
if ( status == SecurityStatus.OK )
|
||||
if (status == SecurityStatus.OK)
|
||||
{
|
||||
result = Marshal.PtrToStringUni( stringAttrib.StringResult );
|
||||
ContextNativeMethods.FreeContextBuffer( stringAttrib.StringResult );
|
||||
result = Marshal.PtrToStringUni(stringAttrib.StringResult);
|
||||
ContextNativeMethods.FreeContextBuffer(stringAttrib.StringResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( status == SecurityStatus.Unsupported )
|
||||
|
||||
if (status == SecurityStatus.Unsupported)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if( status != SecurityStatus.OK )
|
||||
else if (status != SecurityStatus.OK)
|
||||
{
|
||||
throw new SSPIException( "Failed to query the context's associated user name", status );
|
||||
throw new SSPIException("Failed to query the context's associated user name", status);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -587,13 +617,13 @@ namespace NSspi.Contexts
|
||||
/// </summary>
|
||||
private void CheckLifecycle()
|
||||
{
|
||||
if( this.Initialized == false )
|
||||
if (this.Initialized == false)
|
||||
{
|
||||
throw new InvalidOperationException( "The context is not yet fully formed." );
|
||||
throw new InvalidOperationException("The context is not yet fully formed.");
|
||||
}
|
||||
else if( this.Disposed )
|
||||
else if (this.Disposed)
|
||||
{
|
||||
throw new ObjectDisposedException( "Context" );
|
||||
throw new ObjectDisposedException("Context");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace NSspi.Contexts
|
||||
);
|
||||
*/
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "AcceptSecurityContext",CharSet = CharSet.Unicode )]
|
||||
[DllImport("Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus AcceptSecurityContext_1(
|
||||
ref RawSspiHandle credHandle,
|
||||
IntPtr oldContextHandle,
|
||||
@@ -59,7 +59,7 @@ namespace NSspi.Contexts
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode )]
|
||||
[DllImport("Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus AcceptSecurityContext_2(
|
||||
ref RawSspiHandle credHandle,
|
||||
ref RawSspiHandle oldContextHandle,
|
||||
@@ -73,7 +73,7 @@ namespace NSspi.Contexts
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||
[DllImport("Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus InitializeSecurityContext_1(
|
||||
ref RawSspiHandle credentialHandle,
|
||||
IntPtr zero,
|
||||
@@ -90,7 +90,7 @@ namespace NSspi.Contexts
|
||||
);
|
||||
|
||||
|
||||
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||
[DllImport("Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus InitializeSecurityContext_2(
|
||||
ref RawSspiHandle credentialHandle,
|
||||
ref RawSspiHandle previousHandle,
|
||||
@@ -106,13 +106,13 @@ namespace NSspi.Contexts
|
||||
ref TimeStamp expiry
|
||||
);
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "DeleteSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus DeleteSecurityContext( ref RawSspiHandle contextHandle );
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "DeleteSecurityContext", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus DeleteSecurityContext(ref RawSspiHandle contextHandle);
|
||||
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus EncryptMessage(
|
||||
ref RawSspiHandle contextHandle,
|
||||
int qualityOfProtection,
|
||||
@@ -120,8 +120,8 @@ namespace NSspi.Contexts
|
||||
int sequenceNumber
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "DecryptMessage", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "DecryptMessage", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus DecryptMessage(
|
||||
ref RawSspiHandle contextHandle,
|
||||
IntPtr bufferDescriptor,
|
||||
@@ -129,8 +129,8 @@ namespace NSspi.Contexts
|
||||
int qualityOfProtection
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus MakeSignature(
|
||||
ref RawSspiHandle contextHandle,
|
||||
int qualityOfProtection,
|
||||
@@ -138,8 +138,8 @@ namespace NSspi.Contexts
|
||||
int sequenceNumber
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "VerifySignature", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "VerifySignature", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus VerifySignature(
|
||||
ref RawSspiHandle contextHandle,
|
||||
IntPtr bufferDescriptor,
|
||||
@@ -147,34 +147,111 @@ namespace NSspi.Contexts
|
||||
int qualityOfProtection
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus QueryContextAttributes_Sizes(
|
||||
ref RawSspiHandle contextHandle,
|
||||
ContextQueryAttrib attrib,
|
||||
ref SecPkgContext_Sizes sizes
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus QueryContextAttributes_String(
|
||||
ref RawSspiHandle contextHandle,
|
||||
ContextQueryAttrib attrib,
|
||||
ref SecPkgContext_String names
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus FreeContextBuffer( IntPtr handle );
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus QueryContextAttributes(
|
||||
ref RawSspiHandle contextHandle,
|
||||
ContextQueryAttrib attrib,
|
||||
IntPtr attribute
|
||||
);
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[DllImport("Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode)]
|
||||
internal static extern SecurityStatus FreeContextBuffer(IntPtr handle);
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[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 = "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)]
|
||||
internal static extern SecurityStatus RevertSecurityContext(ref RawSspiHandle contextHandle);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
class KeyStruct
|
||||
{
|
||||
public int size;
|
||||
public IntPtr data;
|
||||
}
|
||||
|
||||
internal static SecurityStatus SafeQueryContextAttribute(
|
||||
SafeContextHandle handle,
|
||||
ContextQueryAttrib attribute,
|
||||
ref byte[] buffer
|
||||
)
|
||||
{
|
||||
bool gotRef = false;
|
||||
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
|
||||
|
||||
int pointerSize = System.Environment.Is64BitOperatingSystem ? 8 : 4; //NOTE: update this when 128 bit processors exist
|
||||
IntPtr alloc_buffer = Marshal.AllocHGlobal(sizeof(uint) + pointerSize); //NOTE: this is at most 4 + sizeof(void*) bytes
|
||||
//see struct SecPkgContext_SessionKey
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380096(v=vs.85).aspx
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (gotRef)
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.QueryContextAttributes(
|
||||
ref handle.rawHandle,
|
||||
attribute,
|
||||
alloc_buffer
|
||||
);
|
||||
if (status == SecurityStatus.OK)
|
||||
{
|
||||
KeyStruct key = new KeyStruct();
|
||||
|
||||
Marshal.PtrToStructure(alloc_buffer, key); // fit to the proper size, read a byte[]
|
||||
|
||||
byte[] sizedBuffer = new byte[key.size];
|
||||
|
||||
for (int i = 0; i < key.size; i++)
|
||||
sizedBuffer[i] = Marshal.ReadByte(key.data, i);
|
||||
|
||||
buffer = sizedBuffer;
|
||||
}
|
||||
handle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
Marshal.FreeHGlobal(alloc_buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle );
|
||||
|
||||
/// <summary>
|
||||
/// Safely invokes the native EncryptMessage function, making sure that handle ref counting is
|
||||
@@ -189,7 +266,7 @@ namespace NSspi.Contexts
|
||||
SafeContextHandle handle,
|
||||
int qualityOfProtection,
|
||||
SecureBufferAdapter bufferAdapter,
|
||||
int sequenceNumber )
|
||||
int sequenceNumber)
|
||||
{
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
bool gotRef = false;
|
||||
@@ -197,11 +274,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef( ref gotRef );
|
||||
handle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch ( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -211,7 +288,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.EncryptMessage(
|
||||
ref handle.rawHandle,
|
||||
@@ -236,11 +313,11 @@ namespace NSspi.Contexts
|
||||
/// <param name="bufferAdapter"></param>
|
||||
/// <param name="sequenceNumber"></param>
|
||||
/// <returns></returns>
|
||||
internal static SecurityStatus SafeDecryptMessage(
|
||||
SafeContextHandle handle,
|
||||
int qualityOfProtection,
|
||||
SecureBufferAdapter bufferAdapter,
|
||||
int sequenceNumber )
|
||||
internal static SecurityStatus SafeDecryptMessage(
|
||||
SafeContextHandle handle,
|
||||
int qualityOfProtection,
|
||||
SecureBufferAdapter bufferAdapter,
|
||||
int sequenceNumber)
|
||||
{
|
||||
SecurityStatus status = SecurityStatus.InvalidHandle;
|
||||
bool gotRef = false;
|
||||
@@ -248,11 +325,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef( ref gotRef );
|
||||
handle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -262,7 +339,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.DecryptMessage(
|
||||
ref handle.rawHandle,
|
||||
@@ -291,7 +368,7 @@ namespace NSspi.Contexts
|
||||
SafeContextHandle handle,
|
||||
int qualityOfProtection,
|
||||
SecureBufferAdapter adapter,
|
||||
int sequenceNumber )
|
||||
int sequenceNumber)
|
||||
{
|
||||
bool gotRef = false;
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
@@ -299,11 +376,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef( ref gotRef );
|
||||
handle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch ( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -313,7 +390,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.MakeSignature(
|
||||
ref handle.rawHandle,
|
||||
@@ -342,7 +419,7 @@ namespace NSspi.Contexts
|
||||
SafeContextHandle handle,
|
||||
int qualityOfProtection,
|
||||
SecureBufferAdapter adapter,
|
||||
int sequenceNumber )
|
||||
int sequenceNumber)
|
||||
{
|
||||
bool gotRef = false;
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
@@ -350,11 +427,11 @@ namespace NSspi.Contexts
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef( ref gotRef );
|
||||
handle.DangerousAddRef(ref gotRef);
|
||||
}
|
||||
catch ( Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
handle.DangerousRelease();
|
||||
gotRef = false;
|
||||
@@ -364,7 +441,7 @@ namespace NSspi.Contexts
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ( gotRef )
|
||||
if (gotRef)
|
||||
{
|
||||
status = ContextNativeMethods.VerifySignature(
|
||||
ref handle.rawHandle,
|
||||
|
||||
@@ -36,5 +36,18 @@ namespace NSspi.Contexts
|
||||
/// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
|
||||
/// </remarks>
|
||||
Authority = 6,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Queries the context for it's neogtiated SessionKey
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Results for a query of this type are stored in a Win32 SecPkgContext_SessionKey structure
|
||||
/// </remarks>
|
||||
SessionKey = 9,
|
||||
|
||||
|
||||
AccessToken = 13, //not implemented yet but this would be cool
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user