Code cleanup
Fixed code style using CodeMaid.
This commit is contained in:
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -13,7 +8,7 @@ namespace NSspi
|
|||||||
public static class ByteWriter
|
public static class ByteWriter
|
||||||
{
|
{
|
||||||
// Big endian: Most significant byte at lowest address in memory.
|
// Big endian: Most significant byte at lowest address in memory.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes a 2-byte signed integer to the buffer in big-endian format.
|
/// Writes a 2-byte signed integer to the buffer in big-endian format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -37,8 +32,7 @@ namespace NSspi
|
|||||||
buffer[position + 0] = (byte)( value >> 24 );
|
buffer[position + 0] = (byte)( value >> 24 );
|
||||||
buffer[position + 1] = (byte)( value >> 16 );
|
buffer[position + 1] = (byte)( value >> 16 );
|
||||||
buffer[position + 2] = (byte)( value >> 8 );
|
buffer[position + 2] = (byte)( value >> 8 );
|
||||||
buffer[position + 3] = (byte)( value);
|
buffer[position + 3] = (byte)( value );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -77,4 +71,4 @@ namespace NSspi
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Buffers;
|
using NSspi.Buffers;
|
||||||
using NSspi.Credentials;
|
using NSspi.Credentials;
|
||||||
|
|
||||||
@@ -14,7 +9,7 @@ namespace NSspi.Contexts
|
|||||||
/// with the server and to encrypt, decrypt, sign and verify messages to and from the server.
|
/// with the server and to encrypt, decrypt, sign and verify messages to and from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A client and server establish a shared security context by exchanging authentication tokens. Once
|
/// A client and server establish a shared security context by exchanging authentication tokens. Once
|
||||||
/// the shared context is established, the client and server can pass messages to each other, encrypted,
|
/// the shared context is established, the client and server can pass messages to each other, encrypted,
|
||||||
/// signed, etc, using the established parameters of the shared context.
|
/// signed, etc, using the established parameters of the shared context.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
@@ -47,11 +42,11 @@ namespace NSspi.Contexts
|
|||||||
/// This method is performed iteratively to start, continue, and end the authentication cycle with the
|
/// This method is performed iteratively to start, continue, and end the authentication cycle with the
|
||||||
/// server. Each stage works by acquiring a token from one side, presenting it to the other side
|
/// server. Each stage works by acquiring a token from one side, presenting it to the other side
|
||||||
/// which in turn may generate a new token.
|
/// which in turn may generate a new token.
|
||||||
///
|
///
|
||||||
/// The cycle typically starts and ends with the client. On the first invocation on the client,
|
/// The cycle typically starts and ends with the client. On the first invocation on the client,
|
||||||
/// no server token exists, and null is provided in its place. The client returns its status, providing
|
/// no server token exists, and null is provided in its place. The client returns its status, providing
|
||||||
/// its output token for the server. The server accepts the clients token as input and provides a
|
/// its output token for the server. The server accepts the clients token as input and provides a
|
||||||
/// token as output to send back to the client. This cycle continues until the server and client
|
/// token as output to send back to the client. This cycle continues until the server and client
|
||||||
/// both indicate, typically, a SecurityStatus of 'OK'.
|
/// both indicate, typically, a SecurityStatus of 'OK'.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="serverToken">The most recently received token from the server, or null if beginning
|
/// <param name="serverToken">The most recently received token from the server, or null if beginning
|
||||||
@@ -60,7 +55,7 @@ namespace NSspi.Contexts
|
|||||||
/// <returns>A status message indicating the progression of the authentication cycle.
|
/// <returns>A status message indicating the progression of the authentication cycle.
|
||||||
/// A status of 'OK' indicates that the cycle is complete, from the client's perspective. If the outToken
|
/// A status of 'OK' indicates that the cycle is complete, from the client's perspective. If the outToken
|
||||||
/// is not null, it must be sent to the server.
|
/// is not null, it must be sent to the server.
|
||||||
/// A status of 'Continue' indicates that the output token should be sent to the server and
|
/// A status of 'Continue' indicates that the output token should be sent to the server and
|
||||||
/// a response should be anticipated.</returns>
|
/// a response should be anticipated.</returns>
|
||||||
public SecurityStatus Init( byte[] serverToken, out byte[] outToken )
|
public SecurityStatus Init( byte[] serverToken, out byte[] outToken )
|
||||||
{
|
{
|
||||||
@@ -73,7 +68,7 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
SecureBuffer serverBuffer;
|
SecureBuffer serverBuffer;
|
||||||
SecureBufferAdapter serverAdapter;
|
SecureBufferAdapter serverAdapter;
|
||||||
|
|
||||||
if( this.Disposed )
|
if( this.Disposed )
|
||||||
{
|
{
|
||||||
throw new ObjectDisposedException( "ClientContext" );
|
throw new ObjectDisposedException( "ClientContext" );
|
||||||
@@ -86,24 +81,24 @@ namespace NSspi.Contexts
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException( "Must provide the server's response when continuing the init process." );
|
throw new InvalidOperationException( "Must provide the server's response when continuing the init process." );
|
||||||
}
|
}
|
||||||
|
|
||||||
// The security package tells us how big its biggest token will be. We'll allocate a buffer
|
// The security package tells us how big its biggest token will be. We'll allocate a buffer
|
||||||
// that size, and it'll tell us how much it used.
|
// that size, and it'll tell us how much it used.
|
||||||
outTokenBuffer = new SecureBuffer(
|
outTokenBuffer = new SecureBuffer(
|
||||||
new byte[ this.Credential.PackageInfo.MaxTokenLength ],
|
new byte[this.Credential.PackageInfo.MaxTokenLength],
|
||||||
BufferType.Token
|
BufferType.Token
|
||||||
);
|
);
|
||||||
|
|
||||||
serverBuffer = null;
|
serverBuffer = null;
|
||||||
if ( serverToken != null )
|
if( serverToken != null )
|
||||||
{
|
{
|
||||||
serverBuffer = new SecureBuffer( serverToken, BufferType.Token );
|
serverBuffer = new SecureBuffer( serverToken, BufferType.Token );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some notes on handles and invoking InitializeSecurityContext
|
// Some notes on handles and invoking InitializeSecurityContext
|
||||||
// - The first time around, the phContext parameter (the 'old' handle) is a null pointer to what
|
// - 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.
|
// 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
|
// The phNewContext is a pointer (reference) to an RawSspiHandle struct of where to write the
|
||||||
// new handle's values.
|
// new handle's values.
|
||||||
// - The next time you invoke ISC, it takes a pointer to the handle it gave you last time in phContext,
|
// - 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.
|
// and takes a pointer to where it should write the new handle's values in phNewContext.
|
||||||
@@ -111,13 +106,13 @@ namespace NSspi.Contexts
|
|||||||
// "On the second call, phNewContext can be the same as the handle specified in the phContext
|
// "On the second call, phNewContext can be the same as the handle specified in the phContext
|
||||||
// parameter."
|
// parameter."
|
||||||
// It will overwrite the handle you gave it with the new handle value.
|
// 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
|
// - All handle structures themselves are actually *two* pointer variables, eg, 64 bits on 32-bit
|
||||||
// Windows, 128 bits on 64-bit Windows.
|
// 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
|
// - 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.
|
// points to 128 bits of memory (the struct itself) for where to write the handle numbers.
|
||||||
using ( outAdapter = new SecureBufferAdapter( outTokenBuffer ) )
|
using( outAdapter = new SecureBufferAdapter( outTokenBuffer ) )
|
||||||
{
|
{
|
||||||
if ( this.ContextHandle.IsInvalid )
|
if( this.ContextHandle.IsInvalid )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.InitializeSecurityContext_1(
|
status = ContextNativeMethods.InitializeSecurityContext_1(
|
||||||
ref this.Credential.Handle.rawHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
@@ -136,7 +131,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using ( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
|
using( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.InitializeSecurityContext_2(
|
status = ContextNativeMethods.InitializeSecurityContext_2(
|
||||||
ref this.Credential.Handle.rawHandle,
|
ref this.Credential.Handle.rawHandle,
|
||||||
@@ -179,4 +174,4 @@ namespace NSspi.Contexts
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Buffers;
|
using NSspi.Buffers;
|
||||||
using NSspi.Contexts;
|
|
||||||
using NSspi.Credentials;
|
using NSspi.Credentials;
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a security context and provides common functionality required for all security
|
/// Represents a security context and provides common functionality required for all security
|
||||||
/// contexts.
|
/// contexts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This class is abstract and has a protected constructor and Initialize method. The exact
|
/// This class is abstract and has a protected constructor and Initialize method. The exact
|
||||||
/// initialization implementation is provided by a subclasses, which may perform initialization
|
/// initialization implementation is provided by a subclasses, which may perform initialization
|
||||||
/// in a variety of manners.
|
/// in a variety of manners.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public abstract class Context : IDisposable
|
public abstract class Context : IDisposable
|
||||||
@@ -28,7 +23,7 @@ namespace NSspi.Contexts
|
|||||||
/// and the Initialize method has been called.
|
/// and the Initialize method has been called.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cred"></param>
|
/// <param name="cred"></param>
|
||||||
protected Context(Credential cred)
|
protected Context( Credential cred )
|
||||||
{
|
{
|
||||||
this.Credential = cred;
|
this.Credential = cred;
|
||||||
|
|
||||||
@@ -61,7 +56,7 @@ namespace NSspi.Contexts
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
CheckLifecycle();
|
CheckLifecycle();
|
||||||
return QueryContextString(ContextQueryAttrib.Authority);
|
return QueryContextString( ContextQueryAttrib.Authority );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +68,7 @@ namespace NSspi.Contexts
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
CheckLifecycle();
|
CheckLifecycle();
|
||||||
return QueryContextString(ContextQueryAttrib.Names);
|
return QueryContextString( ContextQueryAttrib.Names );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +86,7 @@ namespace NSspi.Contexts
|
|||||||
/// Marks the context as having completed the initialization process, ie, exchanging of authentication tokens.
|
/// Marks the context as having completed the initialization process, ie, exchanging of authentication tokens.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="expiry">The date and time that the context will expire.</param>
|
/// <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.Expiry = expiry;
|
||||||
this.Initialized = true;
|
this.Initialized = true;
|
||||||
@@ -102,19 +97,19 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose( true );
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases resources associated with the context.
|
/// Releases resources associated with the context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="disposing">If true, release managed resources, else release only unmanaged resources.</param>
|
/// <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();
|
this.ContextHandle.Dispose();
|
||||||
}
|
}
|
||||||
@@ -136,7 +131,7 @@ namespace NSspi.Contexts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="input">The raw message to encrypt.</param>
|
/// <param name="input">The raw message to encrypt.</param>
|
||||||
/// <returns>The packed and encrypted message.</returns>
|
/// <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
|
// The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
|
||||||
SecPkgContext_Sizes sizes;
|
SecPkgContext_Sizes sizes;
|
||||||
@@ -153,13 +148,13 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
sizes = QueryBufferSizes();
|
sizes = QueryBufferSizes();
|
||||||
|
|
||||||
trailerBuffer = new SecureBuffer(new byte[sizes.SecurityTrailer], BufferType.Token);
|
trailerBuffer = new SecureBuffer( new byte[sizes.SecurityTrailer], BufferType.Token );
|
||||||
dataBuffer = new SecureBuffer(new byte[input.Length], BufferType.Data);
|
dataBuffer = new SecureBuffer( new byte[input.Length], BufferType.Data );
|
||||||
paddingBuffer = new SecureBuffer(new byte[sizes.BlockSize], BufferType.Padding);
|
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(
|
status = ContextNativeMethods.SafeEncryptMessage(
|
||||||
this.ContextHandle,
|
this.ContextHandle,
|
||||||
@@ -169,9 +164,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;
|
int position = 0;
|
||||||
@@ -183,22 +178,22 @@ namespace NSspi.Contexts
|
|||||||
// -- The encrypted message
|
// -- The encrypted message
|
||||||
result = new byte[2 + 4 + 2 + trailerBuffer.Length + dataBuffer.Length + paddingBuffer.Length];
|
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;
|
position += 2;
|
||||||
|
|
||||||
ByteWriter.WriteInt32_BE(dataBuffer.Length, result, position);
|
ByteWriter.WriteInt32_BE( dataBuffer.Length, result, position );
|
||||||
position += 4;
|
position += 4;
|
||||||
|
|
||||||
ByteWriter.WriteInt16_BE((short)paddingBuffer.Length, result, position);
|
ByteWriter.WriteInt16_BE( (short)paddingBuffer.Length, result, position );
|
||||||
position += 2;
|
position += 2;
|
||||||
|
|
||||||
Array.Copy(trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length);
|
Array.Copy( trailerBuffer.Buffer, 0, result, position, trailerBuffer.Length );
|
||||||
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;
|
position += dataBuffer.Length;
|
||||||
|
|
||||||
Array.Copy(paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length);
|
Array.Copy( paddingBuffer.Buffer, 0, result, position, paddingBuffer.Length );
|
||||||
position += paddingBuffer.Length;
|
position += paddingBuffer.Length;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -218,7 +213,7 @@ namespace NSspi.Contexts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="input">The packed and encrypted data.</param>
|
/// <param name="input">The packed and encrypted data.</param>
|
||||||
/// <returns>The original plaintext message.</returns>
|
/// <returns>The original plaintext message.</returns>
|
||||||
public byte[] Decrypt(byte[] input)
|
public byte[] Decrypt( byte[] input )
|
||||||
{
|
{
|
||||||
SecPkgContext_Sizes sizes;
|
SecPkgContext_Sizes sizes;
|
||||||
|
|
||||||
@@ -241,63 +236,62 @@ namespace NSspi.Contexts
|
|||||||
sizes = QueryBufferSizes();
|
sizes = QueryBufferSizes();
|
||||||
|
|
||||||
// This check is required, but not sufficient. We could be stricter.
|
// 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;
|
position = 0;
|
||||||
|
|
||||||
trailerLength = ByteWriter.ReadInt16_BE(input, position);
|
trailerLength = ByteWriter.ReadInt16_BE( input, position );
|
||||||
position += 2;
|
position += 2;
|
||||||
|
|
||||||
dataLength = ByteWriter.ReadInt32_BE(input, position);
|
dataLength = ByteWriter.ReadInt32_BE( input, position );
|
||||||
position += 4;
|
position += 4;
|
||||||
|
|
||||||
paddingLength = ByteWriter.ReadInt16_BE(input, position);
|
paddingLength = ByteWriter.ReadInt16_BE( input, position );
|
||||||
position += 2;
|
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);
|
trailerBuffer = new SecureBuffer( new byte[trailerLength], BufferType.Token );
|
||||||
dataBuffer = new SecureBuffer(new byte[dataLength], BufferType.Data);
|
dataBuffer = new SecureBuffer( new byte[dataLength], BufferType.Data );
|
||||||
paddingBuffer = new SecureBuffer(new byte[paddingLength], BufferType.Padding);
|
paddingBuffer = new SecureBuffer( new byte[paddingLength], BufferType.Padding );
|
||||||
|
|
||||||
remaining = input.Length - position;
|
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;
|
position += trailerBuffer.Length;
|
||||||
remaining -= trailerBuffer.Length;
|
remaining -= trailerBuffer.Length;
|
||||||
}
|
}
|
||||||
else
|
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;
|
position += dataBuffer.Length;
|
||||||
remaining -= dataBuffer.Length;
|
remaining -= dataBuffer.Length;
|
||||||
}
|
}
|
||||||
else
|
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.
|
// else there was no padding.
|
||||||
|
|
||||||
|
using( adapter = new SecureBufferAdapter( new[] { trailerBuffer, dataBuffer, paddingBuffer } ) )
|
||||||
using (adapter = new SecureBufferAdapter(new[] { trailerBuffer, dataBuffer, paddingBuffer }))
|
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.SafeDecryptMessage(
|
status = ContextNativeMethods.SafeDecryptMessage(
|
||||||
this.ContextHandle,
|
this.ContextHandle,
|
||||||
@@ -307,13 +301,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];
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -330,7 +324,7 @@ namespace NSspi.Contexts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public byte[] MakeSignature(byte[] message)
|
public byte[] MakeSignature( byte[] message )
|
||||||
{
|
{
|
||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
|
|
||||||
@@ -343,12 +337,12 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
sizes = QueryBufferSizes();
|
sizes = QueryBufferSizes();
|
||||||
|
|
||||||
dataBuffer = new SecureBuffer(new byte[message.Length], BufferType.Data);
|
dataBuffer = new SecureBuffer( new byte[message.Length], BufferType.Data );
|
||||||
signatureBuffer = new SecureBuffer(new byte[sizes.MaxSignature], BufferType.Token);
|
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(
|
status = ContextNativeMethods.SafeMakeSignature(
|
||||||
this.ContextHandle,
|
this.ContextHandle,
|
||||||
@@ -358,15 +352,15 @@ 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;
|
byte[] outMessage;
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
||||||
// Enough room for
|
// Enough room for
|
||||||
// - original message length (4 bytes)
|
// - original message length (4 bytes)
|
||||||
// - signature length (2 bytes)
|
// - signature length (2 bytes)
|
||||||
// - original message
|
// - original message
|
||||||
@@ -374,29 +368,28 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
outMessage = new byte[4 + 2 + dataBuffer.Length + signatureBuffer.Length];
|
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;
|
position += 4;
|
||||||
|
|
||||||
ByteWriter.WriteInt16_BE((Int16)signatureBuffer.Length, outMessage, position);
|
ByteWriter.WriteInt16_BE( (Int16)signatureBuffer.Length, outMessage, position );
|
||||||
position += 2;
|
position += 2;
|
||||||
|
|
||||||
Array.Copy(dataBuffer.Buffer, 0, outMessage, position, dataBuffer.Length);
|
Array.Copy( dataBuffer.Buffer, 0, outMessage, position, dataBuffer.Length );
|
||||||
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;
|
position += signatureBuffer.Length;
|
||||||
|
|
||||||
return outMessage;
|
return outMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the Session Key from a context or null on failure.
|
/// Returns the Session Key from a context or null on failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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.
|
/// 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>
|
/// </remarks>
|
||||||
///
|
///
|
||||||
/// <returns>byte[] with the session key data or null on failure</returns>
|
/// <returns>byte[] with the session key data or null on failure</returns>
|
||||||
public byte[] QuerySessionKey()
|
public byte[] QuerySessionKey()
|
||||||
{
|
{
|
||||||
@@ -410,15 +403,14 @@ namespace NSspi.Contexts
|
|||||||
ref SessionKey
|
ref SessionKey
|
||||||
);
|
);
|
||||||
|
|
||||||
if (status != SecurityStatus.OK)
|
if( status != SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
throw new SSPIException("Failed to query session key.", status);
|
throw new SSPIException( "Failed to query session key.", status );
|
||||||
}
|
}
|
||||||
|
|
||||||
return SessionKey;
|
return SessionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies the signature of a signed message
|
/// Verifies the signature of a signed message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -432,7 +424,7 @@ namespace NSspi.Contexts
|
|||||||
/// <param name="signedMessage">The packed signed message.</param>
|
/// <param name="signedMessage">The packed signed message.</param>
|
||||||
/// <param name="origMessage">The extracted original message.</param>
|
/// <param name="origMessage">The extracted original message.</param>
|
||||||
/// <returns>True if the message has a valid signature, false otherwise.</returns>
|
/// <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;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
|
|
||||||
@@ -445,35 +437,35 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
sizes = QueryBufferSizes();
|
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 position = 0;
|
||||||
int messageLen;
|
int messageLen;
|
||||||
int sigLen;
|
int sigLen;
|
||||||
|
|
||||||
messageLen = ByteWriter.ReadInt32_BE(signedMessage, 0);
|
messageLen = ByteWriter.ReadInt32_BE( signedMessage, 0 );
|
||||||
position += 4;
|
position += 4;
|
||||||
|
|
||||||
sigLen = ByteWriter.ReadInt16_BE(signedMessage, position);
|
sigLen = ByteWriter.ReadInt16_BE( signedMessage, position );
|
||||||
position += 2;
|
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);
|
dataBuffer = new SecureBuffer( new byte[messageLen], BufferType.Data );
|
||||||
Array.Copy(signedMessage, position, dataBuffer.Buffer, 0, messageLen);
|
Array.Copy( signedMessage, position, dataBuffer.Buffer, 0, messageLen );
|
||||||
position += messageLen;
|
position += messageLen;
|
||||||
|
|
||||||
signatureBuffer = new SecureBuffer(new byte[sigLen], BufferType.Token);
|
signatureBuffer = new SecureBuffer( new byte[sigLen], BufferType.Token );
|
||||||
Array.Copy(signedMessage, position, signatureBuffer.Buffer, 0, sigLen);
|
Array.Copy( signedMessage, position, signatureBuffer.Buffer, 0, sigLen );
|
||||||
position += sigLen;
|
position += sigLen;
|
||||||
|
|
||||||
using (adapter = new SecureBufferAdapter(new[] { dataBuffer, signatureBuffer }))
|
using( adapter = new SecureBufferAdapter( new[] { dataBuffer, signatureBuffer } ) )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.SafeVerifySignature(
|
status = ContextNativeMethods.SafeVerifySignature(
|
||||||
this.ContextHandle,
|
this.ContextHandle,
|
||||||
@@ -483,20 +475,20 @@ namespace NSspi.Contexts
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == SecurityStatus.OK)
|
if( status == SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
origMessage = dataBuffer.Buffer;
|
origMessage = dataBuffer.Buffer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (status == SecurityStatus.MessageAltered ||
|
else if( status == SecurityStatus.MessageAltered ||
|
||||||
status == SecurityStatus.OutOfSequence)
|
status == SecurityStatus.OutOfSequence )
|
||||||
{
|
{
|
||||||
origMessage = null;
|
origMessage = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,11 +505,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.ContextHandle.DangerousAddRef(ref gotRef);
|
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
this.ContextHandle.DangerousRelease();
|
this.ContextHandle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -527,7 +519,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.QueryContextAttributes_Sizes(
|
status = ContextNativeMethods.QueryContextAttributes_Sizes(
|
||||||
ref this.ContextHandle.rawHandle,
|
ref this.ContextHandle.rawHandle,
|
||||||
@@ -538,9 +530,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;
|
return sizes;
|
||||||
@@ -551,16 +543,16 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attrib">The string-valued attribute to query.</param>
|
/// <param name="attrib">The string-valued attribute to query.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private string QueryContextString(ContextQueryAttrib attrib)
|
private string QueryContextString( ContextQueryAttrib attrib )
|
||||||
{
|
{
|
||||||
SecPkgContext_String stringAttrib;
|
SecPkgContext_String stringAttrib;
|
||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
string result = null;
|
string result = null;
|
||||||
bool gotRef = false;
|
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();
|
stringAttrib = new SecPkgContext_String();
|
||||||
@@ -568,11 +560,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.ContextHandle.DangerousAddRef(ref gotRef);
|
this.ContextHandle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
this.ContextHandle.DangerousRelease();
|
this.ContextHandle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -581,7 +573,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.QueryContextAttributes_String(
|
status = ContextNativeMethods.QueryContextAttributes_String(
|
||||||
ref this.ContextHandle.rawHandle,
|
ref this.ContextHandle.rawHandle,
|
||||||
@@ -591,40 +583,40 @@ namespace NSspi.Contexts
|
|||||||
|
|
||||||
this.ContextHandle.DangerousRelease();
|
this.ContextHandle.DangerousRelease();
|
||||||
|
|
||||||
if (status == SecurityStatus.OK)
|
if( status == SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
result = Marshal.PtrToStringUni(stringAttrib.StringResult);
|
result = Marshal.PtrToStringUni( stringAttrib.StringResult );
|
||||||
ContextNativeMethods.FreeContextBuffer(stringAttrib.StringResult);
|
ContextNativeMethods.FreeContextBuffer( stringAttrib.StringResult );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == SecurityStatus.Unsupported)
|
if( status == SecurityStatus.Unsupported )
|
||||||
{
|
{
|
||||||
return null;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies that the object's lifecycle (initialization / disposition) state is suitable for using the
|
/// Verifies that the object's lifecycle (initialization / disposition) state is suitable for using the
|
||||||
/// object.
|
/// object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CheckLifecycle()
|
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" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines options for creating a security context via win32 InitializeSecurityContext
|
/// Defines options for creating a security context via win32 InitializeSecurityContext
|
||||||
/// (used by clients) and AcceptSecurityContext (used by servers).
|
/// (used by clients) and AcceptSecurityContext (used by servers).
|
||||||
/// Required attribute flags are specified when creating the context. InitializeSecurityContext
|
/// Required attribute flags are specified when creating the context. InitializeSecurityContext
|
||||||
/// and AcceptSecurityContext returns a value indicating what final attributes the created context
|
/// and AcceptSecurityContext returns a value indicating what final attributes the created context
|
||||||
/// actually has.
|
/// actually has.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum ContextAttrib : int
|
public enum ContextAttrib : int
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// No additional attributes are provided.
|
/// No additional attributes are provided.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The server can use the context to authenticate to other servers as the client. The
|
/// The server can use the context to authenticate to other servers as the client. The
|
||||||
/// MutualAuth flag must be set for this flag to work. Valid for Kerberos. Ignore this flag for
|
/// MutualAuth flag must be set for this flag to work. Valid for Kerberos. Ignore this flag for
|
||||||
/// constrained delegation.
|
/// constrained delegation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Delegate = 0x00000001,
|
Delegate = 0x00000001,
|
||||||
@@ -36,17 +32,16 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
MutualAuth = 0x00000002,
|
MutualAuth = 0x00000002,
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature
|
/// Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature
|
||||||
/// message support functionality.
|
/// message support functionality.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ReplayDetect = 0x00000004,
|
ReplayDetect = 0x00000004,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detect messages received out of sequence when using the message support functionality.
|
/// Detect messages received out of sequence when using the message support functionality.
|
||||||
/// This flag implies all of the conditions specified by the Integrity flag - out-of-order sequence
|
/// This flag implies all of the conditions specified by the Integrity flag - out-of-order sequence
|
||||||
/// detection can only be trusted if the integrity of any underlying sequence detection mechanism
|
/// detection can only be trusted if the integrity of any underlying sequence detection mechanism
|
||||||
/// in transmitted data can be trusted.
|
/// in transmitted data can be trusted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SequenceDetect = 0x00000008,
|
SequenceDetect = 0x00000008,
|
||||||
@@ -55,12 +50,12 @@ namespace NSspi.Contexts
|
|||||||
// Confidentiality is supported for NTLM with Microsoft
|
// Confidentiality is supported for NTLM with Microsoft
|
||||||
// Windows NT version 4.0, SP4 and later and with the
|
// Windows NT version 4.0, SP4 and later and with the
|
||||||
// Kerberos protocol in Microsoft Windows 2000 and later.
|
// Kerberos protocol in Microsoft Windows 2000 and later.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The context must protect data while in transit. Encrypt messages by using the EncryptMessage function.
|
/// The context must protect data while in transit. Encrypt messages by using the EncryptMessage function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Confidentiality = 0x00000010,
|
Confidentiality = 0x00000010,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A new session key must be negotiated.
|
/// A new session key must be negotiated.
|
||||||
/// This value is supported only by the Kerberos security package.
|
/// This value is supported only by the Kerberos security package.
|
||||||
@@ -68,13 +63,13 @@ namespace NSspi.Contexts
|
|||||||
UseSessionKey = 0x00000020,
|
UseSessionKey = 0x00000020,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The security package allocates output buffers for you. Buffers allocated by the security package have
|
/// The security package allocates output buffers for you. Buffers allocated by the security package have
|
||||||
/// to be released by the context memory management functions.
|
/// to be released by the context memory management functions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
AllocateMemory = 0x00000100,
|
AllocateMemory = 0x00000100,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The security context will not handle formatting messages. This value is the default for the Kerberos,
|
/// The security context will not handle formatting messages. This value is the default for the Kerberos,
|
||||||
/// Negotiate, and NTLM security packages.
|
/// Negotiate, and NTLM security packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Connection = 0x00000800,
|
Connection = 0x00000800,
|
||||||
@@ -84,7 +79,7 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A client specifies InitExtendedError in InitializeSecurityContext
|
/// A client specifies InitExtendedError in InitializeSecurityContext
|
||||||
/// and the server specifies AcceptExtendedError in AcceptSecurityContext.
|
/// and the server specifies AcceptExtendedError in AcceptSecurityContext.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
InitExtendedError = 0x00004000,
|
InitExtendedError = 0x00004000,
|
||||||
|
|
||||||
@@ -93,7 +88,7 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A client specifies InitExtendedError in InitializeSecurityContext
|
/// A client specifies InitExtendedError in InitializeSecurityContext
|
||||||
/// and the server specifies AcceptExtendedError in AcceptSecurityContext.
|
/// and the server specifies AcceptExtendedError in AcceptSecurityContext.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
AcceptExtendedError = 0x00008000,
|
AcceptExtendedError = 0x00008000,
|
||||||
|
|
||||||
@@ -112,7 +107,7 @@ namespace NSspi.Contexts
|
|||||||
/// Replayed and out-of-sequence messages will not be detected with the setting of this attribute.
|
/// Replayed and out-of-sequence messages will not be detected with the setting of this attribute.
|
||||||
/// Set ReplayDetect and SequenceDetect also if these behaviors are desired.
|
/// Set ReplayDetect and SequenceDetect also if these behaviors are desired.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
InitIntegrity = 0x00010000,
|
InitIntegrity = 0x00010000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.
|
/// Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.
|
||||||
@@ -134,4 +129,4 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
InitUseSuppliedCreds = 0x00000080,
|
InitUseSuppliedCreds = 0x00000080,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Buffers;
|
using NSspi.Buffers;
|
||||||
using NSspi.Contexts;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
@@ -28,7 +23,7 @@ namespace NSspi.Contexts
|
|||||||
_Out_ PULONG pfContextAttr,
|
_Out_ PULONG pfContextAttr,
|
||||||
_Out_opt_ PTimeStamp ptsTimeStamp
|
_Out_opt_ PTimeStamp ptsTimeStamp
|
||||||
);
|
);
|
||||||
|
|
||||||
SECURITY_STATUS SEC_Entry InitializeSecurityContext(
|
SECURITY_STATUS SEC_Entry InitializeSecurityContext(
|
||||||
_In_opt_ PCredHandle phCredential, // [in] handle to the credentials
|
_In_opt_ PCredHandle phCredential, // [in] handle to the credentials
|
||||||
_In_opt_ PCtxtHandle phContext, // [in/out] handle of partially formed context. Always NULL the first time through
|
_In_opt_ PCtxtHandle phContext, // [in/out] handle of partially formed context. Always NULL the first time through
|
||||||
@@ -45,7 +40,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(
|
internal static extern SecurityStatus AcceptSecurityContext_1(
|
||||||
ref RawSspiHandle credHandle,
|
ref RawSspiHandle credHandle,
|
||||||
IntPtr oldContextHandle,
|
IntPtr oldContextHandle,
|
||||||
@@ -58,8 +53,7 @@ namespace NSspi.Contexts
|
|||||||
ref TimeStamp expiry
|
ref TimeStamp expiry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[DllImport( "Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "AcceptSecurityContext", CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern SecurityStatus AcceptSecurityContext_2(
|
internal static extern SecurityStatus AcceptSecurityContext_2(
|
||||||
ref RawSspiHandle credHandle,
|
ref RawSspiHandle credHandle,
|
||||||
ref RawSspiHandle oldContextHandle,
|
ref RawSspiHandle oldContextHandle,
|
||||||
@@ -72,8 +66,7 @@ namespace NSspi.Contexts
|
|||||||
ref TimeStamp expiry
|
ref TimeStamp expiry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern SecurityStatus InitializeSecurityContext_1(
|
internal static extern SecurityStatus InitializeSecurityContext_1(
|
||||||
ref RawSspiHandle credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
IntPtr zero,
|
IntPtr zero,
|
||||||
@@ -89,8 +82,7 @@ namespace NSspi.Contexts
|
|||||||
ref TimeStamp expiry
|
ref TimeStamp expiry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[DllImport( "Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "InitializeSecurityContext", CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern SecurityStatus InitializeSecurityContext_2(
|
internal static extern SecurityStatus InitializeSecurityContext_2(
|
||||||
ref RawSspiHandle credentialHandle,
|
ref RawSspiHandle credentialHandle,
|
||||||
ref RawSspiHandle previousHandle,
|
ref RawSspiHandle previousHandle,
|
||||||
@@ -106,13 +98,12 @@ namespace NSspi.Contexts
|
|||||||
ref TimeStamp expiry
|
ref TimeStamp expiry
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "DeleteSecurityContext", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "DeleteSecurityContext", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus DeleteSecurityContext(ref RawSspiHandle contextHandle);
|
internal static extern SecurityStatus DeleteSecurityContext( ref RawSspiHandle contextHandle );
|
||||||
|
|
||||||
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
[DllImport( "Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "EncryptMessage", CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern SecurityStatus EncryptMessage(
|
internal static extern SecurityStatus EncryptMessage(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
@@ -120,8 +111,8 @@ namespace NSspi.Contexts
|
|||||||
int sequenceNumber
|
int sequenceNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "DecryptMessage", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "DecryptMessage", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus DecryptMessage(
|
internal static extern SecurityStatus DecryptMessage(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
IntPtr bufferDescriptor,
|
IntPtr bufferDescriptor,
|
||||||
@@ -129,8 +120,8 @@ namespace NSspi.Contexts
|
|||||||
int qualityOfProtection
|
int qualityOfProtection
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus MakeSignature(
|
internal static extern SecurityStatus MakeSignature(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
@@ -138,8 +129,8 @@ namespace NSspi.Contexts
|
|||||||
int sequenceNumber
|
int sequenceNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "VerifySignature", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "VerifySignature", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus VerifySignature(
|
internal static extern SecurityStatus VerifySignature(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
IntPtr bufferDescriptor,
|
IntPtr bufferDescriptor,
|
||||||
@@ -147,45 +138,44 @@ namespace NSspi.Contexts
|
|||||||
int qualityOfProtection
|
int qualityOfProtection
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus QueryContextAttributes_Sizes(
|
internal static extern SecurityStatus QueryContextAttributes_Sizes(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
ContextQueryAttrib attrib,
|
ContextQueryAttrib attrib,
|
||||||
ref SecPkgContext_Sizes sizes
|
ref SecPkgContext_Sizes sizes
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus QueryContextAttributes_String(
|
internal static extern SecurityStatus QueryContextAttributes_String(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
ContextQueryAttrib attrib,
|
ContextQueryAttrib attrib,
|
||||||
ref SecPkgContext_String names
|
ref SecPkgContext_String names
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus QueryContextAttributes(
|
internal static extern SecurityStatus QueryContextAttributes(
|
||||||
ref RawSspiHandle contextHandle,
|
ref RawSspiHandle contextHandle,
|
||||||
ContextQueryAttrib attrib,
|
ContextQueryAttrib attrib,
|
||||||
IntPtr attribute
|
IntPtr attribute
|
||||||
);
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus FreeContextBuffer(IntPtr handle);
|
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)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "ImpersonateSecurityContext", CharSet = CharSet.Unicode)]
|
[DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus ImpersonateSecurityContext(ref RawSspiHandle contextHandle);
|
internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle );
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
[DllImport("Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode)]
|
private class KeyStruct
|
||||||
internal static extern SecurityStatus RevertSecurityContext(ref RawSspiHandle contextHandle);
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
class KeyStruct
|
|
||||||
{
|
{
|
||||||
public int size;
|
public int size;
|
||||||
public IntPtr data;
|
public IntPtr data;
|
||||||
@@ -202,18 +192,17 @@ namespace NSspi.Contexts
|
|||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
|
|
||||||
|
|
||||||
int pointerSize = System.Environment.Is64BitOperatingSystem ? 8 : 4; //NOTE: update this when 128 bit processors exist
|
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
|
IntPtr alloc_buffer = Marshal.AllocHGlobal( sizeof( uint ) + pointerSize ); //NOTE: this is at most 4 + sizeof(void*) bytes
|
||||||
//see struct SecPkgContext_SessionKey
|
//see struct SecPkgContext_SessionKey
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380096(v=vs.85).aspx
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380096(v=vs.85).aspx
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle.DangerousAddRef(ref gotRef);
|
handle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -224,37 +213,35 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.QueryContextAttributes(
|
status = ContextNativeMethods.QueryContextAttributes(
|
||||||
ref handle.rawHandle,
|
ref handle.rawHandle,
|
||||||
attribute,
|
attribute,
|
||||||
alloc_buffer
|
alloc_buffer
|
||||||
);
|
);
|
||||||
if (status == SecurityStatus.OK)
|
if( status == SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
KeyStruct key = new KeyStruct();
|
KeyStruct key = new KeyStruct();
|
||||||
|
|
||||||
Marshal.PtrToStructure(alloc_buffer, key); // fit to the proper size, read a byte[]
|
Marshal.PtrToStructure( alloc_buffer, key ); // fit to the proper size, read a byte[]
|
||||||
|
|
||||||
byte[] sizedBuffer = new byte[key.size];
|
byte[] sizedBuffer = new byte[key.size];
|
||||||
|
|
||||||
for (int i = 0; i < key.size; i++)
|
for( int i = 0; i < key.size; i++ )
|
||||||
sizedBuffer[i] = Marshal.ReadByte(key.data, i);
|
sizedBuffer[i] = Marshal.ReadByte( key.data, i );
|
||||||
|
|
||||||
buffer = sizedBuffer;
|
buffer = sizedBuffer;
|
||||||
}
|
}
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Marshal.FreeHGlobal(alloc_buffer);
|
Marshal.FreeHGlobal( alloc_buffer );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Safely invokes the native EncryptMessage function, making sure that handle ref counting is
|
/// Safely invokes the native EncryptMessage function, making sure that handle ref counting is
|
||||||
/// performed in a proper CER.
|
/// performed in a proper CER.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle"></param>
|
/// <param name="handle"></param>
|
||||||
@@ -266,7 +253,7 @@ namespace NSspi.Contexts
|
|||||||
SafeContextHandle handle,
|
SafeContextHandle handle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
SecureBufferAdapter bufferAdapter,
|
SecureBufferAdapter bufferAdapter,
|
||||||
int sequenceNumber)
|
int sequenceNumber )
|
||||||
{
|
{
|
||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
bool gotRef = false;
|
bool gotRef = false;
|
||||||
@@ -274,11 +261,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle.DangerousAddRef(ref gotRef);
|
handle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -288,7 +275,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.EncryptMessage(
|
status = ContextNativeMethods.EncryptMessage(
|
||||||
ref handle.rawHandle,
|
ref handle.rawHandle,
|
||||||
@@ -305,7 +292,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Safely invokes the native DecryptMessage function, making sure that handle ref counting is
|
/// Safely invokes the native DecryptMessage function, making sure that handle ref counting is
|
||||||
/// performed in a proper CER.
|
/// performed in a proper CER.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle"></param>
|
/// <param name="handle"></param>
|
||||||
@@ -317,7 +304,7 @@ namespace NSspi.Contexts
|
|||||||
SafeContextHandle handle,
|
SafeContextHandle handle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
SecureBufferAdapter bufferAdapter,
|
SecureBufferAdapter bufferAdapter,
|
||||||
int sequenceNumber)
|
int sequenceNumber )
|
||||||
{
|
{
|
||||||
SecurityStatus status = SecurityStatus.InvalidHandle;
|
SecurityStatus status = SecurityStatus.InvalidHandle;
|
||||||
bool gotRef = false;
|
bool gotRef = false;
|
||||||
@@ -325,11 +312,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle.DangerousAddRef(ref gotRef);
|
handle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -339,7 +326,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.DecryptMessage(
|
status = ContextNativeMethods.DecryptMessage(
|
||||||
ref handle.rawHandle,
|
ref handle.rawHandle,
|
||||||
@@ -356,7 +343,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Safely invokes the native MakeSignature function, making sure that handle ref counting is
|
/// Safely invokes the native MakeSignature function, making sure that handle ref counting is
|
||||||
/// performed in a proper CER.
|
/// performed in a proper CER.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle"></param>
|
/// <param name="handle"></param>
|
||||||
@@ -368,7 +355,7 @@ namespace NSspi.Contexts
|
|||||||
SafeContextHandle handle,
|
SafeContextHandle handle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
SecureBufferAdapter adapter,
|
SecureBufferAdapter adapter,
|
||||||
int sequenceNumber)
|
int sequenceNumber )
|
||||||
{
|
{
|
||||||
bool gotRef = false;
|
bool gotRef = false;
|
||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
@@ -376,11 +363,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle.DangerousAddRef(ref gotRef);
|
handle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -390,7 +377,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.MakeSignature(
|
status = ContextNativeMethods.MakeSignature(
|
||||||
ref handle.rawHandle,
|
ref handle.rawHandle,
|
||||||
@@ -407,7 +394,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Safely invokes the native VerifySignature function, making sure that handle ref counting is
|
/// Safely invokes the native VerifySignature function, making sure that handle ref counting is
|
||||||
/// performed in a proper CER.
|
/// performed in a proper CER.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle"></param>
|
/// <param name="handle"></param>
|
||||||
@@ -419,7 +406,7 @@ namespace NSspi.Contexts
|
|||||||
SafeContextHandle handle,
|
SafeContextHandle handle,
|
||||||
int qualityOfProtection,
|
int qualityOfProtection,
|
||||||
SecureBufferAdapter adapter,
|
SecureBufferAdapter adapter,
|
||||||
int sequenceNumber)
|
int sequenceNumber )
|
||||||
{
|
{
|
||||||
bool gotRef = false;
|
bool gotRef = false;
|
||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
@@ -427,11 +414,11 @@ namespace NSspi.Contexts
|
|||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle.DangerousAddRef(ref gotRef);
|
handle.DangerousAddRef( ref gotRef );
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch( Exception )
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
handle.DangerousRelease();
|
handle.DangerousRelease();
|
||||||
gotRef = false;
|
gotRef = false;
|
||||||
@@ -441,7 +428,7 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (gotRef)
|
if( gotRef )
|
||||||
{
|
{
|
||||||
status = ContextNativeMethods.VerifySignature(
|
status = ContextNativeMethods.VerifySignature(
|
||||||
ref handle.rawHandle,
|
ref handle.rawHandle,
|
||||||
@@ -457,4 +444,4 @@ namespace NSspi.Contexts
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
@@ -27,4 +23,4 @@ namespace NSspi.Contexts
|
|||||||
{
|
{
|
||||||
public IntPtr StringResult;
|
public IntPtr StringResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
@@ -37,7 +33,6 @@ namespace NSspi.Contexts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
Authority = 6,
|
Authority = 6,
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the context for it's neogtiated SessionKey
|
/// Queries the context for it's neogtiated SessionKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -46,8 +41,6 @@ namespace NSspi.Contexts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
SessionKey = 9,
|
SessionKey = 9,
|
||||||
|
|
||||||
|
|
||||||
AccessToken = 13, //not implemented yet but this would be cool
|
AccessToken = 13, //not implemented yet but this would be cool
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents impersonation performed on a server on behalf of a client.
|
/// Represents impersonation performed on a server on behalf of a client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The handle controls the lifetime of impersonation, and will revert the impersonation
|
/// The handle controls the lifetime of impersonation, and will revert the impersonation
|
||||||
/// if it is disposed, or if it is finalized ie by being leaked and garbage collected.
|
/// if it is disposed, or if it is finalized ie by being leaked and garbage collected.
|
||||||
///
|
///
|
||||||
/// If the handle is accidentally leaked while operations are performed on behalf of the user,
|
/// If the handle is accidentally leaked while operations are performed on behalf of the user,
|
||||||
/// impersonation may be reverted at any arbitrary time, perhaps during those operations.
|
/// impersonation may be reverted at any arbitrary time, perhaps during those operations.
|
||||||
/// This may lead to operations being performed in the security context of the server,
|
/// This may lead to operations being performed in the security context of the server,
|
||||||
/// potentially leading to security vulnerabilities.
|
/// potentially leading to security vulnerabilities.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class ImpersonationHandle : IDisposable
|
public class ImpersonationHandle : IDisposable
|
||||||
@@ -27,7 +23,7 @@ namespace NSspi.Contexts
|
|||||||
/// Initializes a new instance of the ImpersonationHandle. Does not perform impersonation.
|
/// Initializes a new instance of the ImpersonationHandle. Does not perform impersonation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="server">The server context that is performing impersonation.</param>
|
/// <param name="server">The server context that is performing impersonation.</param>
|
||||||
internal ImpersonationHandle(ServerContext server)
|
internal ImpersonationHandle( ServerContext server )
|
||||||
{
|
{
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.disposed = false;
|
this.disposed = false;
|
||||||
@@ -54,6 +50,5 @@ namespace NSspi.Contexts
|
|||||||
this.server.RevertImpersonate();
|
this.server.RevertImpersonate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Contexts
|
namespace NSspi.Contexts
|
||||||
{
|
{
|
||||||
@@ -28,4 +24,4 @@ namespace NSspi.Contexts
|
|||||||
return status == SecurityStatus.OK;
|
return status == SecurityStatus.OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Buffers;
|
using NSspi.Buffers;
|
||||||
using NSspi.Credentials;
|
using NSspi.Credentials;
|
||||||
|
|
||||||
@@ -25,7 +21,7 @@ namespace NSspi.Contexts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cred"></param>
|
/// <param name="cred"></param>
|
||||||
/// <param name="requestedAttribs"></param>
|
/// <param name="requestedAttribs"></param>
|
||||||
public ServerContext(ServerCredential cred, ContextAttrib requestedAttribs) : base ( cred )
|
public ServerContext( ServerCredential cred, ContextAttrib requestedAttribs ) : base( cred )
|
||||||
{
|
{
|
||||||
this.requestedAttribs = requestedAttribs;
|
this.requestedAttribs = requestedAttribs;
|
||||||
this.finalAttribs = ContextAttrib.Zero;
|
this.finalAttribs = ContextAttrib.Zero;
|
||||||
@@ -50,11 +46,11 @@ namespace NSspi.Contexts
|
|||||||
/// This method is performed iteratively to continue and end the authentication cycle with the
|
/// This method is performed iteratively to continue and end the authentication cycle with the
|
||||||
/// client. Each stage works by acquiring a token from one side, presenting it to the other side
|
/// client. Each stage works by acquiring a token from one side, presenting it to the other side
|
||||||
/// which in turn may generate a new token.
|
/// which in turn may generate a new token.
|
||||||
///
|
///
|
||||||
/// The cycle typically starts and ends with the client. On the first invocation on the client,
|
/// The cycle typically starts and ends with the client. On the first invocation on the client,
|
||||||
/// no server token exists, and null is provided in its place. The client returns its status, providing
|
/// no server token exists, and null is provided in its place. The client returns its status, providing
|
||||||
/// its output token for the server. The server accepts the clients token as input and provides a
|
/// its output token for the server. The server accepts the clients token as input and provides a
|
||||||
/// token as output to send back to the client. This cycle continues until the server and client
|
/// token as output to send back to the client. This cycle continues until the server and client
|
||||||
/// both indicate, typically, a SecurityStatus of 'OK'.
|
/// both indicate, typically, a SecurityStatus of 'OK'.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="clientToken">The most recently received token from the client.</param>
|
/// <param name="clientToken">The most recently received token from the client.</param>
|
||||||
@@ -63,7 +59,7 @@ namespace NSspi.Contexts
|
|||||||
/// <returns>A status message indicating the progression of the authentication cycle.
|
/// <returns>A status message indicating the progression of the authentication cycle.
|
||||||
/// A status of 'OK' indicates that the cycle is complete, from the servers's perspective. If the nextToken
|
/// A status of 'OK' indicates that the cycle is complete, from the servers's perspective. If the nextToken
|
||||||
/// is not null, it must be sent to the client.
|
/// is not null, it must be sent to the client.
|
||||||
/// A status of 'Continue' indicates that the output token should be sent to the client and
|
/// A status of 'Continue' indicates that the output token should be sent to the client and
|
||||||
/// a response should be anticipated.</returns>
|
/// a response should be anticipated.</returns>
|
||||||
public SecurityStatus AcceptToken( byte[] clientToken, out byte[] nextToken )
|
public SecurityStatus AcceptToken( byte[] clientToken, out byte[] nextToken )
|
||||||
{
|
{
|
||||||
@@ -82,21 +78,21 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
else if( this.Initialized )
|
else if( this.Initialized )
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
"Attempted to continue initialization of a ServerContext after initialization had completed."
|
"Attempted to continue initialization of a ServerContext after initialization had completed."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
clientBuffer = new SecureBuffer( clientToken, BufferType.Token );
|
||||||
|
|
||||||
outBuffer = new SecureBuffer(
|
outBuffer = new SecureBuffer(
|
||||||
new byte[ this.Credential.PackageInfo.MaxTokenLength ],
|
new byte[this.Credential.PackageInfo.MaxTokenLength],
|
||||||
BufferType.Token
|
BufferType.Token
|
||||||
);
|
);
|
||||||
|
|
||||||
using ( clientAdapter = new SecureBufferAdapter( clientBuffer ) )
|
using( clientAdapter = new SecureBufferAdapter( clientBuffer ) )
|
||||||
{
|
{
|
||||||
using ( outAdapter = new SecureBufferAdapter( outBuffer ) )
|
using( outAdapter = new SecureBufferAdapter( outBuffer ) )
|
||||||
{
|
{
|
||||||
if( this.ContextHandle.IsInvalid )
|
if( this.ContextHandle.IsInvalid )
|
||||||
{
|
{
|
||||||
@@ -125,19 +121,17 @@ namespace NSspi.Contexts
|
|||||||
ref this.finalAttribs,
|
ref this.finalAttribs,
|
||||||
ref rawExpiry
|
ref rawExpiry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( status == SecurityStatus.OK )
|
if( status == SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
nextToken = null;
|
nextToken = null;
|
||||||
|
|
||||||
base.Initialize( rawExpiry.ToDateTime() );
|
base.Initialize( rawExpiry.ToDateTime() );
|
||||||
|
|
||||||
if ( outBuffer.Length != 0 )
|
if( outBuffer.Length != 0 )
|
||||||
{
|
{
|
||||||
nextToken = new byte[outBuffer.Length];
|
nextToken = new byte[outBuffer.Length];
|
||||||
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
||||||
@@ -147,7 +141,7 @@ namespace NSspi.Contexts
|
|||||||
nextToken = null;
|
nextToken = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( status == SecurityStatus.ContinueNeeded )
|
else if( status == SecurityStatus.ContinueNeeded )
|
||||||
{
|
{
|
||||||
nextToken = new byte[outBuffer.Length];
|
nextToken = new byte[outBuffer.Length];
|
||||||
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
|
||||||
@@ -161,17 +155,17 @@ namespace NSspi.Contexts
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the current thread's security context to impersonate the user of the client.
|
/// Changes the current thread's security context to impersonate the user of the client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Requires that the security package provided with the server's credentials, as well as the
|
/// Requires that the security package provided with the server's credentials, as well as the
|
||||||
/// client's credentials, support impersonation.
|
/// client's credentials, support impersonation.
|
||||||
///
|
///
|
||||||
/// Currently, only one thread may initiate impersonation per security context. Impersonation may
|
/// Currently, only one thread may initiate impersonation per security context. Impersonation may
|
||||||
/// follow threads created by the initial impersonation thread, however.
|
/// follow threads created by the initial impersonation thread, however.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <returns>A handle to capture the lifetime of the impersonation. Dispose the handle to revert
|
/// <returns>A handle to capture the lifetime of the impersonation. Dispose the handle to revert
|
||||||
/// impersonation. If the handle is leaked, the impersonation will automatically revert at a
|
/// impersonation. If the handle is leaked, the impersonation will automatically revert at a
|
||||||
/// non-deterministic time when the handle is finalized by the Garbage Collector.</returns>
|
/// non-deterministic time when the handle is finalized by the Garbage Collector.</returns>
|
||||||
public ImpersonationHandle ImpersonateClient()
|
public ImpersonationHandle ImpersonateClient()
|
||||||
{
|
{
|
||||||
@@ -242,7 +236,7 @@ namespace NSspi.Contexts
|
|||||||
{
|
{
|
||||||
throw new SSPIException( "Failed to impersonate the client", status );
|
throw new SSPIException( "Failed to impersonate the client", status );
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,4 +300,4 @@ namespace NSspi.Contexts
|
|||||||
base.Dispose( disposing );
|
base.Dispose( disposing );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -21,4 +16,4 @@ namespace NSspi.Credentials
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices.AccountManagement;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ConstrainedExecution;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Credentials;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -49,7 +42,7 @@ namespace NSspi.Credentials
|
|||||||
|
|
||||||
this.PackageInfo = PackageSupport.GetPackageCapabilities( this.SecurityPackage );
|
this.PackageInfo = PackageSupport.GetPackageCapabilities( this.SecurityPackage );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets metadata for the security package associated with the credential.
|
/// Gets metadata for the security package associated with the credential.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -151,7 +144,7 @@ namespace NSspi.Credentials
|
|||||||
protected set
|
protected set
|
||||||
{
|
{
|
||||||
CheckLifecycle();
|
CheckLifecycle();
|
||||||
|
|
||||||
this.expiry = value;
|
this.expiry = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,9 +180,9 @@ namespace NSspi.Credentials
|
|||||||
|
|
||||||
protected virtual void Dispose( bool disposing )
|
protected virtual void Dispose( bool disposing )
|
||||||
{
|
{
|
||||||
if ( this.disposed == false )
|
if( this.disposed == false )
|
||||||
{
|
{
|
||||||
if ( disposing )
|
if( disposing )
|
||||||
{
|
{
|
||||||
this.safeCredHandle.Dispose();
|
this.safeCredHandle.Dispose();
|
||||||
}
|
}
|
||||||
@@ -206,4 +199,4 @@ namespace NSspi.Credentials
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Credentials;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
internal static class CredentialNativeMethods
|
internal static class CredentialNativeMethods
|
||||||
{
|
{
|
||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
|
||||||
[DllImport( "Secur32.dll", EntryPoint = "AcquireCredentialsHandle", CharSet = CharSet.Unicode )]
|
[DllImport( "Secur32.dll", EntryPoint = "AcquireCredentialsHandle", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus AcquireCredentialsHandle(
|
internal static extern SecurityStatus AcquireCredentialsHandle(
|
||||||
string principleName,
|
string principleName,
|
||||||
@@ -31,7 +26,6 @@ namespace NSspi.Credentials
|
|||||||
ref RawSspiHandle credentialHandle
|
ref RawSspiHandle credentialHandle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The overload of the QueryCredentialsAttribute method that is used for querying the name attribute.
|
/// The overload of the QueryCredentialsAttribute method that is used for querying the name attribute.
|
||||||
/// In this call, it takes a void* to a structure that contains a wide char pointer. The wide character
|
/// In this call, it takes a void* to a structure that contains a wide char pointer. The wide character
|
||||||
@@ -49,4 +43,4 @@ namespace NSspi.Credentials
|
|||||||
ref QueryNameAttribCarrier name
|
ref QueryNameAttribCarrier name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -16,4 +12,4 @@ namespace NSspi.Credentials
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Names = 1,
|
Names = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -29,4 +25,4 @@ namespace NSspi.Credentials
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Both = 3,
|
Both = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -38,7 +34,7 @@ namespace NSspi.Credentials
|
|||||||
this.Handle = new SafeCredentialHandle();
|
this.Handle = new SafeCredentialHandle();
|
||||||
|
|
||||||
// The finally clause is the actual constrained region. The VM pre-allocates any stack space,
|
// 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
|
// performs any allocations it needs to prepare methods for execution, and postpones any
|
||||||
// instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
|
// instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
|
||||||
RuntimeHelpers.PrepareConstrainedRegions();
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
try { }
|
try { }
|
||||||
@@ -57,13 +53,12 @@ namespace NSspi.Credentials
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( status != SecurityStatus.OK )
|
if( status != SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
throw new SSPIException( "Failed to call AcquireCredentialHandle", status );
|
throw new SSPIException( "Failed to call AcquireCredentialHandle", status );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Expiry = rawExpiry.ToDateTime();
|
this.Expiry = rawExpiry.ToDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -14,9 +10,9 @@ namespace NSspi.Credentials
|
|||||||
internal struct QueryNameAttribCarrier
|
internal struct QueryNameAttribCarrier
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A pointer to a null-terminated ascii-encoded containing the principle name
|
/// A pointer to a null-terminated ascii-encoded containing the principle name
|
||||||
/// associated with a credential
|
/// associated with a credential
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IntPtr Name;
|
public IntPtr Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -28,5 +24,4 @@ namespace NSspi.Credentials
|
|||||||
return status == SecurityStatus.OK;
|
return status == SecurityStatus.OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Credentials
|
namespace NSspi.Credentials
|
||||||
{
|
{
|
||||||
@@ -13,7 +8,7 @@ namespace NSspi.Credentials
|
|||||||
public class ServerCredential : CurrentCredential
|
public class ServerCredential : CurrentCredential
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the ServerCredential class, acquiring credentials from
|
/// Initializes a new instance of the ServerCredential class, acquiring credentials from
|
||||||
/// the current thread's security context.
|
/// the current thread's security context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="package">The name of the security package to obtain credentials from.</param>
|
/// <param name="package">The name of the security package to obtain credentials from.</param>
|
||||||
@@ -22,4 +17,4 @@ namespace NSspi.Credentials
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -57,4 +54,4 @@ namespace NSspi
|
|||||||
throw new ArgumentException( "Could not find a matching enumeration value for the text '" + text + "'." );
|
throw new ArgumentException( "Could not find a matching enumeration value for the text '" + text + "'." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Contexts;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
internal static class NativeMethods
|
internal static class NativeMethods
|
||||||
{
|
{
|
||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
[DllImport( "Secur32.dll", EntryPoint = "FreeContextBuffer", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus FreeContextBuffer( IntPtr buffer );
|
internal static extern SecurityStatus FreeContextBuffer( IntPtr buffer );
|
||||||
|
|
||||||
|
|
||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport( "Secur32.dll", EntryPoint = "QuerySecurityPackageInfo", CharSet = CharSet.Unicode )]
|
[DllImport( "Secur32.dll", EntryPoint = "QuerySecurityPackageInfo", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus QuerySecurityPackageInfo( string packageName, ref IntPtr pkgInfo );
|
internal static extern SecurityStatus QuerySecurityPackageInfo( string packageName, ref IntPtr pkgInfo );
|
||||||
@@ -23,6 +17,5 @@ namespace NSspi
|
|||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
[DllImport( "Secur32.dll", EntryPoint = "EnumerateSecurityPackages", CharSet = CharSet.Unicode )]
|
[DllImport( "Secur32.dll", EntryPoint = "EnumerateSecurityPackages", CharSet = CharSet.Unicode )]
|
||||||
internal static extern SecurityStatus EnumerateSecurityPackages( ref int numPackages, ref IntPtr pkgInfoArry );
|
internal static extern SecurityStatus EnumerateSecurityPackages( ref int numPackages, ref IntPtr pkgInfoArry );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -26,4 +22,4 @@ namespace NSspi
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string Ntlm = "NTLM";
|
public const string Ntlm = "NTLM";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -24,7 +20,7 @@ namespace NSspi
|
|||||||
SecurityStatus status = SecurityStatus.InternalError;
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
|
|
||||||
IntPtr rawInfoPtr;
|
IntPtr rawInfoPtr;
|
||||||
|
|
||||||
rawInfoPtr = new IntPtr();
|
rawInfoPtr = new IntPtr();
|
||||||
info = new SecPkgInfo();
|
info = new SecPkgInfo();
|
||||||
|
|
||||||
@@ -35,11 +31,11 @@ namespace NSspi
|
|||||||
{
|
{
|
||||||
status = NativeMethods.QuerySecurityPackageInfo( packageName, ref rawInfoPtr );
|
status = NativeMethods.QuerySecurityPackageInfo( packageName, ref rawInfoPtr );
|
||||||
|
|
||||||
if ( rawInfoPtr != IntPtr.Zero )
|
if( rawInfoPtr != IntPtr.Zero )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ( status == SecurityStatus.OK )
|
if( status == SecurityStatus.OK )
|
||||||
{
|
{
|
||||||
// This performs allocations as it makes room for the strings contained in the SecPkgInfo class.
|
// This performs allocations as it makes room for the strings contained in the SecPkgInfo class.
|
||||||
Marshal.PtrToStructure( rawInfoPtr, info );
|
Marshal.PtrToStructure( rawInfoPtr, info );
|
||||||
@@ -71,7 +67,7 @@ namespace NSspi
|
|||||||
IntPtr pkgArrayPtr;
|
IntPtr pkgArrayPtr;
|
||||||
IntPtr pkgPtr;
|
IntPtr pkgPtr;
|
||||||
int numPackages = 0;
|
int numPackages = 0;
|
||||||
int pkgSize = Marshal.SizeOf( typeof(SecPkgInfo) );
|
int pkgSize = Marshal.SizeOf( typeof( SecPkgInfo ) );
|
||||||
|
|
||||||
pkgArrayPtr = new IntPtr();
|
pkgArrayPtr = new IntPtr();
|
||||||
|
|
||||||
@@ -90,7 +86,7 @@ namespace NSspi
|
|||||||
// Bwooop Bwooop Alocation Alert
|
// Bwooop Bwooop Alocation Alert
|
||||||
// 1) We allocate the array
|
// 1) We allocate the array
|
||||||
// 2) We allocate the individual elements in the array (they're class objects).
|
// 2) We allocate the individual elements in the array (they're class objects).
|
||||||
// 3) We allocate the strings in the individual elements in the array when we
|
// 3) We allocate the strings in the individual elements in the array when we
|
||||||
// call Marshal.PtrToStructure()
|
// call Marshal.PtrToStructure()
|
||||||
|
|
||||||
packages = new SecPkgInfo[numPackages];
|
packages = new SecPkgInfo[numPackages];
|
||||||
@@ -99,7 +95,7 @@ namespace NSspi
|
|||||||
{
|
{
|
||||||
packages[i] = new SecPkgInfo();
|
packages[i] = new SecPkgInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = 0; i < numPackages; i++ )
|
for( int i = 0; i < numPackages; i++ )
|
||||||
{
|
{
|
||||||
pkgPtr = IntPtr.Add( pkgArrayPtr, i * pkgSize );
|
pkgPtr = IntPtr.Add( pkgArrayPtr, i * pkgSize );
|
||||||
@@ -123,4 +119,4 @@ namespace NSspi
|
|||||||
return packages;
|
return packages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,35 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("NSspi")]
|
[assembly: AssemblyTitle( "NSspi" )]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription( "" )]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration( "" )]
|
||||||
[assembly: AssemblyCompany("Kevin Thompson")]
|
[assembly: AssemblyCompany( "Kevin Thompson" )]
|
||||||
[assembly: AssemblyProduct("NSspi")]
|
[assembly: AssemblyProduct( "NSspi" )]
|
||||||
[assembly: AssemblyCopyright("Copyright © Kevin Thompson 2014")]
|
[assembly: AssemblyCopyright( "Copyright © Kevin Thompson 2014" )]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark( "" )]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture( "" )]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible( false )]
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("9abf710c-c646-42aa-8183-76bfa141a07b")]
|
[assembly: Guid( "9abf710c-c646-42aa-8183-76bfa141a07b" )]
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.1.3.0")]
|
[assembly: AssemblyVersion( "0.1.3.0" )]
|
||||||
[assembly: AssemblyFileVersion("0.1.2.0")]
|
[assembly: AssemblyFileVersion( "0.1.2.0" )]
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -26,7 +22,7 @@ namespace NSspi
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
this.errorCode = errorCode;
|
this.errorCode = errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the SSPIException class from serialization data.
|
/// Initializes a new instance of the SSPIException class from serialization data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -35,7 +31,7 @@ namespace NSspi
|
|||||||
protected SSPIException( SerializationInfo info, StreamingContext context )
|
protected SSPIException( SerializationInfo info, StreamingContext context )
|
||||||
: base( info, context )
|
: base( info, context )
|
||||||
{
|
{
|
||||||
this.message = info.GetString("message");
|
this.message = info.GetString( "message" );
|
||||||
this.errorCode = (SecurityStatus)info.GetUInt32( "errorCode" );
|
this.errorCode = (SecurityStatus)info.GetUInt32( "errorCode" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +66,13 @@ namespace NSspi
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return string.Format(
|
return string.Format(
|
||||||
"{0}. Error Code = '0x{1:X}' - \"{2}\".",
|
"{0}. Error Code = '0x{1:X}' - \"{2}\".",
|
||||||
this.message,
|
this.message,
|
||||||
this.errorCode,
|
this.errorCode,
|
||||||
EnumMgr.ToText(this.errorCode)
|
EnumMgr.ToText( this.errorCode )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
@@ -47,55 +43,55 @@ namespace NSspi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes the capabilities of a security package.
|
/// Describes the capabilities of a security package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum SecPkgCapability : uint
|
public enum SecPkgCapability : uint
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the package supports generating messages with integrity information. Required for MakeSignature and VerifySignature.
|
/// Whether the package supports generating messages with integrity information. Required for MakeSignature and VerifySignature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Integrity = 0x1,
|
Integrity = 0x1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the package supports generating encrypted messages. Required for EncryptMessage and DecryptMessage.
|
/// Whether the package supports generating encrypted messages. Required for EncryptMessage and DecryptMessage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Privacy = 0x2,
|
Privacy = 0x2,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the package uses any other buffer information than token buffers.
|
/// Whether the package uses any other buffer information than token buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TokenOnly = 0x4,
|
TokenOnly = 0x4,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the package supports datagram-style authentication.
|
/// Whether the package supports datagram-style authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Datagram = 0x8,
|
Datagram = 0x8,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the package supports creating contexts with connection semantics
|
/// Whether the package supports creating contexts with connection semantics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Connection = 0x10,
|
Connection = 0x10,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiple legs are neccessary for authentication.
|
/// Multiple legs are neccessary for authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MultiLeg = 0x20,
|
MultiLeg = 0x20,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Server authentication is not supported.
|
/// Server authentication is not supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ClientOnly = 0x40,
|
ClientOnly = 0x40,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports extended error handling facilities.
|
/// Supports extended error handling facilities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ExtendedError = 0x80,
|
ExtendedError = 0x80,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports client impersonation on the server.
|
/// Supports client impersonation on the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Impersonation = 0x100,
|
Impersonation = 0x100,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Understands Windows princple and target names.
|
/// Understands Windows princple and target names.
|
||||||
@@ -105,45 +101,45 @@ namespace NSspi
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports stream semantics
|
/// Supports stream semantics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Stream = 0x400,
|
Stream = 0x400,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Package may be used by the Negiotiate meta-package.
|
/// Package may be used by the Negiotiate meta-package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Negotiable = 0x800,
|
Negotiable = 0x800,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compatible with GSS.
|
/// Compatible with GSS.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
GssCompatible = 0x1000,
|
GssCompatible = 0x1000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports LsaLogonUser
|
/// Supports LsaLogonUser
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Logon = 0x2000,
|
Logon = 0x2000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Token buffers are in Ascii format.
|
/// Token buffers are in Ascii format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
AsciiBuffers = 0x4000,
|
AsciiBuffers = 0x4000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports separating large tokens into multiple buffers.
|
/// Supports separating large tokens into multiple buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Fragment = 0x8000,
|
Fragment = 0x8000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports mutual authentication between a client and server.
|
/// Supports mutual authentication between a client and server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MutualAuth = 0x10000,
|
MutualAuth = 0x10000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports credential delegation from the server to a third context.
|
/// Supports credential delegation from the server to a third context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Delegation = 0x20000,
|
Delegation = 0x20000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supports calling EncryptMessage with the read-only-checksum flag, which protects data only
|
/// Supports calling EncryptMessage with the read-only-checksum flag, which protects data only
|
||||||
/// with a checksum and does not encrypt it.
|
/// with a checksum and does not encrypt it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ReadOnlyChecksum = 0x40000,
|
ReadOnlyChecksum = 0x40000,
|
||||||
@@ -157,11 +153,11 @@ namespace NSspi
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extends the negotiate package; only one such package may be registered at any time.
|
/// Extends the negotiate package; only one such package may be registered at any time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ExtendsNego = 0x00100000,
|
ExtendsNego = 0x00100000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This package is negotiated by the package of type ExtendsNego.
|
/// This package is negotiated by the package of type ExtendsNego.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Negotiable2 = 0x00200000,
|
Negotiable2 = 0x00200000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Buffers
|
namespace NSspi.Buffers
|
||||||
{
|
{
|
||||||
@@ -37,10 +33,10 @@ namespace NSspi.Buffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>The buffer is translated into a SecureBufferInternal for the actual call.
|
/// <remarks>The buffer is translated into a SecureBufferInternal for the actual call.
|
||||||
/// To keep the call setup code simple, and to centralize the buffer pinning code,
|
/// To keep the call setup code simple, and to centralize the buffer pinning code,
|
||||||
/// this class stores and returns buffers as regular byte arrays. The buffer
|
/// this class stores and returns buffers as regular byte arrays. The buffer
|
||||||
/// pinning support code in SecureBufferAdapter handles conversion to SecureBufferInternal
|
/// pinning support code in SecureBufferAdapter handles conversion to SecureBufferInternal
|
||||||
/// for pass to the managed api, as well as pinning relevant chunks of memory.
|
/// for pass to the managed api, as well as pinning relevant chunks of memory.
|
||||||
///
|
///
|
||||||
/// Furthermore, the native API may not use the entire buffer, and so a mechanism
|
/// Furthermore, the native API may not use the entire buffer, and so a mechanism
|
||||||
/// is needed to communicate the usage of the buffer separate from the length
|
/// is needed to communicate the usage of the buffer separate from the length
|
||||||
/// of the buffer.</remarks>
|
/// of the buffer.</remarks>
|
||||||
@@ -50,7 +46,7 @@ namespace NSspi.Buffers
|
|||||||
/// Initializes a new instance of the SecureBuffer class.
|
/// Initializes a new instance of the SecureBuffer class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="buffer">The buffer to wrap.</param>
|
/// <param name="buffer">The buffer to wrap.</param>
|
||||||
/// <param name="type">The type or purpose of the buffer, for purposes of
|
/// <param name="type">The type or purpose of the buffer, for purposes of
|
||||||
/// invoking the native API.</param>
|
/// invoking the native API.</param>
|
||||||
public SecureBuffer( byte[] buffer, BufferType type )
|
public SecureBuffer( byte[] buffer, BufferType type )
|
||||||
{
|
{
|
||||||
@@ -75,4 +71,4 @@ namespace NSspi.Buffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Length { get; internal set; }
|
public int Length { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Buffers
|
namespace NSspi.Buffers
|
||||||
{
|
{
|
||||||
@@ -13,52 +10,52 @@ namespace NSspi.Buffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The native APIs consume lists of buffers, with each buffer indicating its type or purpose.
|
/// The native APIs consume lists of buffers, with each buffer indicating its type or purpose.
|
||||||
///
|
///
|
||||||
/// The buffers themselves are simple byte arrays, and the native APIs consume arrays of buffers.
|
/// The buffers themselves are simple byte arrays, and the native APIs consume arrays of buffers.
|
||||||
///
|
///
|
||||||
/// Since winapi calling convention, perhaps as an extension of C calling convention, does not
|
/// Since winapi calling convention, perhaps as an extension of C calling convention, does not
|
||||||
/// provide a standard convention means of communicating the length of any array, custom structures
|
/// provide a standard convention means of communicating the length of any array, custom structures
|
||||||
/// must be created to carry the buffer length and usage.
|
/// must be created to carry the buffer length and usage.
|
||||||
///
|
///
|
||||||
/// Not only does the API need to know how long each buffer is, and how long the array of buffers is,
|
/// Not only does the API need to know how long each buffer is, and how long the array of buffers is,
|
||||||
/// it needs to communicate back how much of each buffer was filled; we may provide it a token buffer
|
/// it needs to communicate back how much of each buffer was filled; we may provide it a token buffer
|
||||||
/// that is 12288 bytes long, but it might only use 125 bytes of that, which we need a way of knowing.
|
/// that is 12288 bytes long, but it might only use 125 bytes of that, which we need a way of knowing.
|
||||||
///
|
///
|
||||||
/// As a result of this, the API requires byte arrays to be carried in structs that are natively known as
|
/// As a result of this, the API requires byte arrays to be carried in structs that are natively known as
|
||||||
/// SecureBuffers (known as SecureBufferInternal in this project), and then arrays of SecureBuffers are
|
/// SecureBuffers (known as SecureBufferInternal in this project), and then arrays of SecureBuffers are
|
||||||
/// carried in a SecureBufferDescriptor structure.
|
/// carried in a SecureBufferDescriptor structure.
|
||||||
///
|
///
|
||||||
/// As such, this class has to do a significant amount of marshaling work just to get the buffers back and
|
/// As such, this class has to do a significant amount of marshaling work just to get the buffers back and
|
||||||
/// forth to the native APIs.
|
/// forth to the native APIs.
|
||||||
/// * We have to pin all buffers
|
/// * We have to pin all buffers
|
||||||
/// * We have to pin the array of buffers
|
/// * We have to pin the array of buffers
|
||||||
/// * We have to obtain IntPtr handles to each of the buffers and to the array of buffers.
|
/// * We have to obtain IntPtr handles to each of the buffers and to the array of buffers.
|
||||||
/// * Since we provide EasyToUse SecureBuffer classes from the rest of the project, but we
|
/// * Since we provide EasyToUse SecureBuffer classes from the rest of the project, but we
|
||||||
/// provide SecureBufferInternal structures from the native API, we have to copy back values
|
/// provide SecureBufferInternal structures from the native API, we have to copy back values
|
||||||
/// from the SecureBufferInternal structs to our SecureBuffer class.
|
/// from the SecureBufferInternal structs to our SecureBuffer class.
|
||||||
///
|
///
|
||||||
/// To make this class easy to use, it accepts either one or many buffers as its constructor; and
|
/// To make this class easy to use, it accepts either one or many buffers as its constructor; and
|
||||||
/// implements IDisposable to know when to marshal values back from the unmanaged structures and to
|
/// implements IDisposable to know when to marshal values back from the unmanaged structures and to
|
||||||
/// release pinned handles.
|
/// release pinned handles.
|
||||||
///
|
///
|
||||||
/// Additionally, in case the adapter is leaked without disposing, the adapter implements a Critical
|
/// Additionally, in case the adapter is leaked without disposing, the adapter implements a Critical
|
||||||
/// Finalizer, to ensure that the GCHandles are released, else we will permanently pin handles.
|
/// Finalizer, to ensure that the GCHandles are released, else we will permanently pin handles.
|
||||||
///
|
///
|
||||||
/// The typical flow is to take one or many buffers; create and fill the neccessary unmanaged structures;
|
/// The typical flow is to take one or many buffers; create and fill the neccessary unmanaged structures;
|
||||||
/// pin memory; acquire the IntPtr handles; let the caller access the top-level IntPtr representing
|
/// pin memory; acquire the IntPtr handles; let the caller access the top-level IntPtr representing
|
||||||
/// the SecureBufferDescriptor, to provide to the native APIs; wait for the caller to invoke the native
|
/// the SecureBufferDescriptor, to provide to the native APIs; wait for the caller to invoke the native
|
||||||
/// API; wait for the caller to invoke our Dispose; marshal back any data from the native structures
|
/// API; wait for the caller to invoke our Dispose; marshal back any data from the native structures
|
||||||
/// (buffer write counts); release all GCHandles to unpin memory.
|
/// (buffer write counts); release all GCHandles to unpin memory.
|
||||||
///
|
///
|
||||||
/// The total descriptor structure is as follows:
|
/// The total descriptor structure is as follows:
|
||||||
/// |-- Descriptor handle
|
/// |-- Descriptor handle
|
||||||
/// |-- Array of buffers
|
/// |-- Array of buffers
|
||||||
/// |-- Buffer 1
|
/// |-- Buffer 1
|
||||||
/// |-- Buffer 2
|
/// |-- Buffer 2
|
||||||
/// ...
|
/// ...
|
||||||
/// |-- Buffer N.
|
/// |-- Buffer N.
|
||||||
///
|
///
|
||||||
/// Each object in that structure must be pinned and passed as an IntPtr to the native APIs.
|
/// Each object in that structure must be pinned and passed as an IntPtr to the native APIs.
|
||||||
/// All this to pass what boils down to a List of byte arrays..
|
/// All this to pass what boils down to a List of byte arrays..
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal sealed class SecureBufferAdapter : CriticalFinalizerObject, IDisposable
|
internal sealed class SecureBufferAdapter : CriticalFinalizerObject, IDisposable
|
||||||
@@ -120,7 +117,7 @@ namespace NSspi.Buffers
|
|||||||
this.bufferHandles = new GCHandle[this.buffers.Count];
|
this.bufferHandles = new GCHandle[this.buffers.Count];
|
||||||
this.bufferCarrier = new SecureBufferInternal[this.buffers.Count];
|
this.bufferCarrier = new SecureBufferInternal[this.buffers.Count];
|
||||||
|
|
||||||
for ( int i = 0; i < this.buffers.Count; i++ )
|
for( int i = 0; i < this.buffers.Count; i++ )
|
||||||
{
|
{
|
||||||
this.bufferHandles[i] = GCHandle.Alloc( this.buffers[i].Buffer, GCHandleType.Pinned );
|
this.bufferHandles[i] = GCHandle.Alloc( this.buffers[i].Buffer, GCHandleType.Pinned );
|
||||||
|
|
||||||
@@ -156,7 +153,7 @@ namespace NSspi.Buffers
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if ( this.disposed )
|
if( this.disposed )
|
||||||
{
|
{
|
||||||
throw new ObjectDisposedException( "Cannot use SecureBufferListHandle after it has been disposed" );
|
throw new ObjectDisposedException( "Cannot use SecureBufferListHandle after it has been disposed" );
|
||||||
}
|
}
|
||||||
@@ -184,11 +181,11 @@ namespace NSspi.Buffers
|
|||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
private void Dispose( bool disposing )
|
private void Dispose( bool disposing )
|
||||||
{
|
{
|
||||||
if ( this.disposed == true ) { return; }
|
if( this.disposed == true ) { return; }
|
||||||
|
|
||||||
if ( disposing )
|
if( disposing )
|
||||||
{
|
{
|
||||||
// When this class is actually being used for its original purpose - to convey buffers
|
// When this class is actually being used for its original purpose - to convey buffers
|
||||||
// back and forth to SSPI calls - we need to copy the potentially modified structure members
|
// back and forth to SSPI calls - we need to copy the potentially modified structure members
|
||||||
// back to our caller's buffer.
|
// back to our caller's buffer.
|
||||||
for( int i = 0; i < this.buffers.Count; i++ )
|
for( int i = 0; i < this.buffers.Count; i++ )
|
||||||
@@ -218,4 +215,4 @@ namespace NSspi.Buffers
|
|||||||
this.disposed = true;
|
this.disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Buffers
|
namespace NSspi.Buffers
|
||||||
{
|
{
|
||||||
@@ -22,4 +18,4 @@ namespace NSspi.Buffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Network = 0x00
|
Network = 0x00
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Buffers
|
namespace NSspi.Buffers
|
||||||
{
|
{
|
||||||
@@ -12,7 +7,7 @@ namespace NSspi.Buffers
|
|||||||
/// Represents the native layout of the secure buffer descriptor that is provided directly
|
/// Represents the native layout of the secure buffer descriptor that is provided directly
|
||||||
/// to native API calls.
|
/// to native API calls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[StructLayout( LayoutKind.Sequential)]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
internal struct SecureBufferDescInternal
|
internal struct SecureBufferDescInternal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,4 +30,4 @@ namespace NSspi.Buffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const int ApiVersion = 0;
|
public const int ApiVersion = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi.Buffers
|
namespace NSspi.Buffers
|
||||||
{
|
{
|
||||||
@@ -38,7 +34,7 @@ namespace NSspi.Buffers
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The buffer passed to an API call contained more data than was necessary for completing the action,
|
/// The buffer passed to an API call contained more data than was necessary for completing the action,
|
||||||
/// such as the case when a streaming-mode connection that does not preserve message bounders, such as TCP
|
/// such as the case when a streaming-mode connection that does not preserve message bounders, such as TCP
|
||||||
/// is used as the transport. The extra data is returned back to the caller in a buffer of this type.
|
/// is used as the transport. The extra data is returned back to the caller in a buffer of this type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Extra = 0x05,
|
Extra = 0x05,
|
||||||
@@ -57,7 +53,7 @@ namespace NSspi.Buffers
|
|||||||
Stream = 0x0A,
|
Stream = 0x0A,
|
||||||
ChannelBindings = 0x0E,
|
ChannelBindings = 0x0E,
|
||||||
TargetHost = 0x10,
|
TargetHost = 0x10,
|
||||||
ReadOnlyFlag = unchecked( (int)0x80000000 ),
|
ReadOnlyFlag = unchecked((int)0x80000000),
|
||||||
ReadOnlyWithChecksum = 0x10000000
|
ReadOnlyWithChecksum = 0x10000000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
// From winerror.h
|
// From winerror.h
|
||||||
#define SEC_E_OK ((HRESULT)0x00000000L)
|
#define SEC_E_OK ((HRESULT)0x00000000L)
|
||||||
#define SEC_E_INSUFFICIENT_MEMORY _HRESULT_TYPEDEF_(0x80090300L)
|
#define SEC_E_INSUFFICIENT_MEMORY _HRESULT_TYPEDEF_(0x80090300L)
|
||||||
#define SEC_E_INVALID_HANDLE _HRESULT_TYPEDEF_(0x80090301L)
|
#define SEC_E_INVALID_HANDLE _HRESULT_TYPEDEF_(0x80090301L)
|
||||||
@@ -31,8 +27,8 @@ namespace NSspi
|
|||||||
/// The request completed successfully
|
/// The request completed successfully
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EnumString( "No error" )]
|
[EnumString( "No error" )]
|
||||||
OK = 0x00000000,
|
OK = 0x00000000,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The token returned by the context needs to be provided to the cooperating party
|
/// The token returned by the context needs to be provided to the cooperating party
|
||||||
/// to continue construction of the context.
|
/// to continue construction of the context.
|
||||||
@@ -45,7 +41,7 @@ namespace NSspi
|
|||||||
/// must call CompleteAuthToken.
|
/// must call CompleteAuthToken.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EnumString( "Authentication cycle needs to perform a 'complete'." )]
|
[EnumString( "Authentication cycle needs to perform a 'complete'." )]
|
||||||
CompleteNeeded = 0x00090313,
|
CompleteNeeded = 0x00090313,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs after a client calls InitializeSecurityContext to indicate that the client
|
/// Occurs after a client calls InitializeSecurityContext to indicate that the client
|
||||||
@@ -64,66 +60,65 @@ namespace NSspi
|
|||||||
CredentialsNeeded = 0x00090320,
|
CredentialsNeeded = 0x00090320,
|
||||||
|
|
||||||
[EnumString( "The context data must be re-negotiated with the peer" )]
|
[EnumString( "The context data must be re-negotiated with the peer" )]
|
||||||
Renegotiate = 0x00090321,
|
Renegotiate = 0x00090321,
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
[EnumString( "Not enough memory.")]
|
[EnumString( "Not enough memory." )]
|
||||||
OutOfMemory = 0x80090300,
|
OutOfMemory = 0x80090300,
|
||||||
|
|
||||||
[EnumString( "The handle provided to the API was invalid.")]
|
[EnumString( "The handle provided to the API was invalid." )]
|
||||||
InvalidHandle = 0x80090301,
|
InvalidHandle = 0x80090301,
|
||||||
|
|
||||||
[EnumString( "The attempted operation is not supported")]
|
[EnumString( "The attempted operation is not supported" )]
|
||||||
Unsupported = 0x80090302,
|
Unsupported = 0x80090302,
|
||||||
|
|
||||||
|
[EnumString( "The specified principle is not known in the authentication system." )]
|
||||||
|
TargetUnknown = 0x80090303,
|
||||||
|
|
||||||
[EnumString( "The specified principle is not known in the authentication system.")]
|
|
||||||
TargetUnknown = 0x80090303,
|
|
||||||
|
|
||||||
[EnumString( "An internal error occurred" )]
|
[EnumString( "An internal error occurred" )]
|
||||||
InternalError = 0x80090304,
|
InternalError = 0x80090304,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// No security provider package was found with the given name.
|
/// No security provider package was found with the given name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EnumString( "The requested security package was not found.")]
|
[EnumString( "The requested security package was not found." )]
|
||||||
PackageNotFound = 0x80090305,
|
PackageNotFound = 0x80090305,
|
||||||
|
|
||||||
NotOwner = 0x80090306,
|
NotOwner = 0x80090306,
|
||||||
CannotInstall = 0x80090307,
|
CannotInstall = 0x80090307,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A token was provided that contained incorrect or corrupted data.
|
/// A token was provided that contained incorrect or corrupted data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EnumString("The provided authentication token is invalid or corrupted.")]
|
[EnumString( "The provided authentication token is invalid or corrupted." )]
|
||||||
InvalidToken = 0x80090308,
|
InvalidToken = 0x80090308,
|
||||||
|
|
||||||
CannotPack = 0x80090309,
|
CannotPack = 0x80090309,
|
||||||
QopNotSupported = 0x8009030A,
|
QopNotSupported = 0x8009030A,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Impersonation is not supported.
|
/// Impersonation is not supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EnumString("Impersonation is not supported with the current security package.")]
|
[EnumString( "Impersonation is not supported with the current security package." )]
|
||||||
NoImpersonation = 0x8009030B,
|
NoImpersonation = 0x8009030B,
|
||||||
|
|
||||||
[EnumString("The logon was denied, perhaps because the provided credentials were incorrect.")]
|
[EnumString( "The logon was denied, perhaps because the provided credentials were incorrect." )]
|
||||||
LogonDenied = 0x8009030C,
|
LogonDenied = 0x8009030C,
|
||||||
|
|
||||||
|
[EnumString( "The credentials provided are not recognized by the selected security package." )]
|
||||||
|
UnknownCredentials = 0x8009030D,
|
||||||
|
|
||||||
[EnumString( "The credentials provided are not recognized by the selected security package.")]
|
[EnumString( "No credentials are available in the selected security package." )]
|
||||||
UnknownCredentials = 0x8009030D,
|
NoCredentials = 0x8009030E,
|
||||||
|
|
||||||
[EnumString( "No credentials are available in the selected security package.")]
|
|
||||||
NoCredentials = 0x8009030E,
|
|
||||||
|
|
||||||
[EnumString( "A message that was provided to the Decrypt or VerifySignature functions was altered " +
|
[EnumString( "A message that was provided to the Decrypt or VerifySignature functions was altered " +
|
||||||
"after it was created.")]
|
"after it was created." )]
|
||||||
MessageAltered = 0x8009030F,
|
MessageAltered = 0x8009030F,
|
||||||
|
|
||||||
[EnumString( "A message was received out of the expected order.")]
|
[EnumString( "A message was received out of the expected order." )]
|
||||||
OutOfSequence = 0x80090310,
|
OutOfSequence = 0x80090310,
|
||||||
|
|
||||||
[EnumString( "The current security package cannot contact an authenticating authority.")]
|
[EnumString( "The current security package cannot contact an authenticating authority." )]
|
||||||
NoAuthenticatingAuthority = 0x80090311,
|
NoAuthenticatingAuthority = 0x80090311,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -132,25 +127,26 @@ namespace NSspi
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This occurs regularly with SSPI contexts that exchange data using a streaming context,
|
/// This occurs regularly with SSPI contexts that exchange data using a streaming context,
|
||||||
/// where the data returned from the streaming communications channel, such as a TCP socket,
|
/// where the data returned from the streaming communications channel, such as a TCP socket,
|
||||||
/// did not contain the complete message.
|
/// did not contain the complete message.
|
||||||
/// Similarly, a streaming channel may return too much data, in which case the API function
|
/// Similarly, a streaming channel may return too much data, in which case the API function
|
||||||
/// will indicate success, but will save off the extra, unrelated data in a buffer of
|
/// will indicate success, but will save off the extra, unrelated data in a buffer of
|
||||||
/// type 'extra'.
|
/// type 'extra'.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
IncompleteMessage = 0x80090318,
|
IncompleteMessage = 0x80090318,
|
||||||
|
|
||||||
IncompleteCredentials = 0x80090320,
|
IncompleteCredentials = 0x80090320,
|
||||||
BufferNotEnough = 0x80090321,
|
BufferNotEnough = 0x80090321,
|
||||||
WrongPrincipal = 0x80090322,
|
WrongPrincipal = 0x80090322,
|
||||||
TimeSkew = 0x80090324,
|
TimeSkew = 0x80090324,
|
||||||
UntrustedRoot = 0x80090325,
|
UntrustedRoot = 0x80090325,
|
||||||
IllegalMessage = 0x80090326,
|
IllegalMessage = 0x80090326,
|
||||||
CertUnknown = 0x80090327,
|
CertUnknown = 0x80090327,
|
||||||
CertExpired = 0x80090328,
|
CertExpired = 0x80090328,
|
||||||
AlgorithmMismatch = 0x80090331,
|
AlgorithmMismatch = 0x80090331,
|
||||||
SecurityQosFailed = 0x80090332,
|
SecurityQosFailed = 0x80090332,
|
||||||
SmartcardLogonRequired = 0x8009033E,
|
SmartcardLogonRequired = 0x8009033E,
|
||||||
UnsupportedPreauth = 0x80090343,
|
UnsupportedPreauth = 0x80090343,
|
||||||
BadBinding = 0x80090346
|
BadBinding = 0x80090346
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -168,5 +164,4 @@ namespace NSspi
|
|||||||
return (uint)status > 0x80000000u;
|
return (uint)status > 0x80000000u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
@@ -1,31 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NSspi.Contexts;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the raw structure for any handle created for the SSPI API, for example, credential
|
/// Represents the raw structure for any handle created for the SSPI API, for example, credential
|
||||||
/// handles, context handles, and security package handles. Any SSPI handle is always the size
|
/// handles, context handles, and security package handles. Any SSPI handle is always the size
|
||||||
/// of two native pointers.
|
/// of two native pointers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The documentation for SSPI handles can be found here:
|
/// The documentation for SSPI handles can be found here:
|
||||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa380495(v=vs.85).aspx
|
/// 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,
|
/// 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.
|
/// 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
|
/// 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 performed a CER
|
/// to this handle for performing work (InitializeSecurityContext, eg) should be performed a CER
|
||||||
/// that employs handle reference counting across the native API invocation.
|
/// that employs handle reference counting across the native API invocation.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[StructLayout( LayoutKind.Sequential, Pack = 1 ) ]
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
internal struct RawSspiHandle
|
internal struct RawSspiHandle
|
||||||
{
|
{
|
||||||
private IntPtr lowPart;
|
private IntPtr lowPart;
|
||||||
@@ -46,7 +40,7 @@ namespace NSspi
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This method is executed in a CER during handle release.
|
/// This method is executed in a CER during handle release.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success)]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
public void SetInvalid()
|
public void SetInvalid()
|
||||||
{
|
{
|
||||||
this.lowPart = IntPtr.Zero;
|
this.lowPart = IntPtr.Zero;
|
||||||
@@ -69,7 +63,7 @@ namespace NSspi
|
|||||||
|
|
||||||
public override bool IsInvalid
|
public override bool IsInvalid
|
||||||
{
|
{
|
||||||
get { return IsClosed || this.rawHandle.IsZero(); }
|
get { return IsClosed || this.rawHandle.IsZero(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||||
@@ -79,4 +73,4 @@ namespace NSspi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NSspi
|
namespace NSspi
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a Windows API Timestamp structure, which stores time in units of 100 nanosecond
|
/// Represents a Windows API Timestamp structure, which stores time in units of 100 nanosecond
|
||||||
/// ticks, counting from January 1st, year 1601 at 00:00 UTC. Time is stored as a 64-bit value.
|
/// ticks, counting from January 1st, year 1601 at 00:00 UTC. Time is stored as a 64-bit value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
@@ -29,13 +25,13 @@ namespace NSspi
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public DateTime ToDateTime()
|
public DateTime ToDateTime()
|
||||||
{
|
{
|
||||||
ulong test = (ulong)this.time + (ulong)(Epoch.Ticks);
|
ulong test = (ulong)this.time + (ulong)( Epoch.Ticks );
|
||||||
|
|
||||||
// Sometimes the value returned is massive, eg, 0x7fffff154e84ffff, which is a value
|
// Sometimes the value returned is massive, eg, 0x7fffff154e84ffff, which is a value
|
||||||
// somewhere in the year 30848. This would overflow DateTime, since it peaks at 31-Dec-9999.
|
// somewhere in the year 30848. This would overflow DateTime, since it peaks at 31-Dec-9999.
|
||||||
// It turns out that this value corresponds to a TimeStamp's maximum value, reduced by my local timezone
|
// It turns out that this value corresponds to a TimeStamp's maximum value, reduced by my local timezone
|
||||||
// http://stackoverflow.com/questions/24478056/
|
// http://stackoverflow.com/questions/24478056/
|
||||||
if ( test > (ulong)DateTime.MaxValue.Ticks )
|
if( test > (ulong)DateTime.MaxValue.Ticks )
|
||||||
{
|
{
|
||||||
return DateTime.MaxValue;
|
return DateTime.MaxValue;
|
||||||
}
|
}
|
||||||
@@ -45,4 +41,4 @@ namespace NSspi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
|
||||||
</startup>
|
</startup>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -35,19 +35,18 @@ namespace NSspi
|
|||||||
|
|
||||||
Console.Out.WriteLine( clientCred.PrincipleName );
|
Console.Out.WriteLine( clientCred.PrincipleName );
|
||||||
|
|
||||||
client = new ClientContext(
|
client = new ClientContext(
|
||||||
clientCred,
|
clientCred,
|
||||||
serverCred.PrincipleName,
|
serverCred.PrincipleName,
|
||||||
ContextAttrib.MutualAuth |
|
ContextAttrib.MutualAuth |
|
||||||
ContextAttrib.InitIdentify |
|
ContextAttrib.InitIdentify |
|
||||||
ContextAttrib.Confidentiality |
|
ContextAttrib.Confidentiality |
|
||||||
ContextAttrib.ReplayDetect |
|
ContextAttrib.ReplayDetect |
|
||||||
ContextAttrib.SequenceDetect |
|
ContextAttrib.SequenceDetect |
|
||||||
ContextAttrib.Connection |
|
ContextAttrib.Connection |
|
||||||
ContextAttrib.Delegate
|
ContextAttrib.Delegate
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
server = new ServerContext(
|
server = new ServerContext(
|
||||||
serverCred,
|
serverCred,
|
||||||
ContextAttrib.MutualAuth |
|
ContextAttrib.MutualAuth |
|
||||||
@@ -64,18 +63,17 @@ namespace NSspi
|
|||||||
|
|
||||||
clientStatus = client.Init( serverToken, out clientToken );
|
clientStatus = client.Init( serverToken, out clientToken );
|
||||||
|
|
||||||
while ( true )
|
while( true )
|
||||||
{
|
{
|
||||||
serverStatus = server.AcceptToken( clientToken, out serverToken );
|
serverStatus = server.AcceptToken( clientToken, out serverToken );
|
||||||
|
|
||||||
if ( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
|
if( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
|
||||||
|
|
||||||
clientStatus = client.Init( serverToken, out clientToken );
|
clientStatus = client.Init( serverToken, out clientToken );
|
||||||
|
|
||||||
if ( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
|
if( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Console.Out.WriteLine( "Server authority: " + server.AuthorityName );
|
Console.Out.WriteLine( "Server authority: " + server.AuthorityName );
|
||||||
Console.Out.WriteLine( "Server context user: " + server.ContextUserName );
|
Console.Out.WriteLine( "Server context user: " + server.ContextUserName );
|
||||||
|
|
||||||
@@ -102,7 +100,7 @@ namespace NSspi
|
|||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i= 0; i < plainText.Length; i++ )
|
for( int i = 0; i < plainText.Length; i++ )
|
||||||
{
|
{
|
||||||
if( plainText[i] != roundTripPlaintext[i] )
|
if( plainText[i] != roundTripPlaintext[i] )
|
||||||
{
|
{
|
||||||
@@ -117,25 +115,23 @@ namespace NSspi
|
|||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using( server.ImpersonateClient() )
|
using( server.ImpersonateClient() )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cipherText = client.MakeSignature( plainText );
|
cipherText = client.MakeSignature( plainText );
|
||||||
|
|
||||||
bool goodSig = server.VerifySignature( cipherText, out roundTripPlaintext );
|
bool goodSig = server.VerifySignature( cipherText, out roundTripPlaintext );
|
||||||
|
|
||||||
if ( goodSig == false ||
|
if( goodSig == false ||
|
||||||
roundTripPlaintext.Length != plainText.Length )
|
roundTripPlaintext.Length != plainText.Length )
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < plainText.Length; i++ )
|
for( int i = 0; i < plainText.Length; i++ )
|
||||||
{
|
{
|
||||||
if ( plainText[i] != roundTripPlaintext[i] )
|
if( plainText[i] != roundTripPlaintext[i] )
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
@@ -145,12 +141,12 @@ namespace NSspi
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if ( server != null )
|
if( server != null )
|
||||||
{
|
{
|
||||||
server.Dispose();
|
server.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( client != null )
|
if( client != null )
|
||||||
{
|
{
|
||||||
client.Dispose();
|
client.Dispose();
|
||||||
}
|
}
|
||||||
@@ -160,11 +156,11 @@ namespace NSspi
|
|||||||
clientCred.Dispose();
|
clientCred.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( serverCred != null )
|
if( serverCred != null )
|
||||||
{
|
{
|
||||||
serverCred.Dispose();
|
serverCred.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle( "NsspiDemo" )]
|
[assembly: AssemblyTitle( "NsspiDemo" )]
|
||||||
@@ -14,8 +13,8 @@ using System.Runtime.InteropServices;
|
|||||||
[assembly: AssemblyTrademark( "" )]
|
[assembly: AssemblyTrademark( "" )]
|
||||||
[assembly: AssemblyCulture( "" )]
|
[assembly: AssemblyCulture( "" )]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible( false )]
|
[assembly: ComVisible( false )]
|
||||||
|
|
||||||
@@ -25,12 +24,12 @@ using System.Runtime.InteropServices;
|
|||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
|
||||||
</startup>
|
</startup>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using NSspi;
|
using NSspi;
|
||||||
using NSspi.Contexts;
|
using NSspi.Contexts;
|
||||||
@@ -53,11 +47,11 @@ namespace TestClient
|
|||||||
this.context = new ClientContext(
|
this.context = new ClientContext(
|
||||||
cred,
|
cred,
|
||||||
"",
|
"",
|
||||||
ContextAttrib.InitIntegrity |
|
ContextAttrib.InitIntegrity |
|
||||||
ContextAttrib.ReplayDetect |
|
ContextAttrib.ReplayDetect |
|
||||||
ContextAttrib.SequenceDetect |
|
ContextAttrib.SequenceDetect |
|
||||||
ContextAttrib.MutualAuth |
|
ContextAttrib.MutualAuth |
|
||||||
ContextAttrib.Delegate |
|
ContextAttrib.Delegate |
|
||||||
ContextAttrib.Confidentiality
|
ContextAttrib.Confidentiality
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -107,7 +101,6 @@ namespace TestClient
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +109,6 @@ namespace TestClient
|
|||||||
this.connection.Stop();
|
this.connection.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void encryptButton_Click( object sender, EventArgs e )
|
private void encryptButton_Click( object sender, EventArgs e )
|
||||||
{
|
{
|
||||||
byte[] plaintext;
|
byte[] plaintext;
|
||||||
@@ -149,7 +141,7 @@ namespace TestClient
|
|||||||
|
|
||||||
private void connection_Received( Message message )
|
private void connection_Received( Message message )
|
||||||
{
|
{
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
if( message.Operation == ProtocolOp.ServerToken )
|
if( message.Operation == ProtocolOp.ServerToken )
|
||||||
{
|
{
|
||||||
@@ -180,11 +172,11 @@ namespace TestClient
|
|||||||
this.initializing = false;
|
this.initializing = false;
|
||||||
this.lastServerToken = null;
|
this.lastServerToken = null;
|
||||||
|
|
||||||
this.BeginInvoke( (Action)delegate()
|
this.BeginInvoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
this.context.Dispose();
|
this.context.Dispose();
|
||||||
this.context = new ClientContext(
|
this.context = new ClientContext(
|
||||||
this.cred,
|
this.cred,
|
||||||
"",
|
"",
|
||||||
ContextAttrib.InitIntegrity |
|
ContextAttrib.InitIntegrity |
|
||||||
ContextAttrib.ReplayDetect |
|
ContextAttrib.ReplayDetect |
|
||||||
@@ -195,9 +187,9 @@ namespace TestClient
|
|||||||
);
|
);
|
||||||
|
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoInit()
|
private void DoInit()
|
||||||
{
|
{
|
||||||
SecurityStatus status;
|
SecurityStatus status;
|
||||||
@@ -253,4 +245,4 @@ namespace TestClient
|
|||||||
this.signButton.Enabled = this.connected;
|
this.signButton.Enabled = this.connected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TestClient
|
namespace TestClient
|
||||||
{
|
{
|
||||||
static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
private static void Main()
|
||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault( false );
|
Application.SetCompatibleTextRenderingDefault( false );
|
||||||
Application.Run( new ClientForm() );
|
Application.Run( new ClientForm() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle( "TestClient" )]
|
[assembly: AssemblyTitle( "TestClient" )]
|
||||||
@@ -14,8 +13,8 @@ using System.Runtime.InteropServices;
|
|||||||
[assembly: AssemblyTrademark( "" )]
|
[assembly: AssemblyTrademark( "" )]
|
||||||
[assembly: AssemblyCulture( "" )]
|
[assembly: AssemblyCulture( "" )]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible( false )]
|
[assembly: ComVisible( false )]
|
||||||
|
|
||||||
@@ -25,11 +24,11 @@ using System.Runtime.InteropServices;
|
|||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
|
||||||
</startup>
|
</startup>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using NSspi;
|
using NSspi;
|
||||||
|
|
||||||
@@ -13,7 +9,7 @@ namespace TestProtocol
|
|||||||
public class CustomConnection
|
public class CustomConnection
|
||||||
{
|
{
|
||||||
private Thread receiveThread;
|
private Thread receiveThread;
|
||||||
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
private bool running;
|
private bool running;
|
||||||
@@ -24,7 +20,7 @@ namespace TestProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
public delegate void ReceivedAction( Message message );
|
public delegate void ReceivedAction( Message message );
|
||||||
|
|
||||||
public event ReceivedAction Received;
|
public event ReceivedAction Received;
|
||||||
|
|
||||||
public event Action Disconnected;
|
public event Action Disconnected;
|
||||||
@@ -33,7 +29,7 @@ namespace TestProtocol
|
|||||||
{
|
{
|
||||||
if( this.running )
|
if( this.running )
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Already running");
|
throw new InvalidOperationException( "Already running" );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
|
this.socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
|
||||||
@@ -65,7 +61,7 @@ namespace TestProtocol
|
|||||||
throw new InvalidOperationException( "Not connected" );
|
throw new InvalidOperationException( "Not connected" );
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] outBuffer = new byte[ message.Data.Length + 8 ];
|
byte[] outBuffer = new byte[message.Data.Length + 8];
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
||||||
ByteWriter.WriteInt32_BE( (int)message.Operation, outBuffer, position );
|
ByteWriter.WriteInt32_BE( (int)message.Operation, outBuffer, position );
|
||||||
@@ -124,16 +120,15 @@ namespace TestProtocol
|
|||||||
// |--4 bytes--|--4 bytes--|---N--|
|
// |--4 bytes--|--4 bytes--|---N--|
|
||||||
// Every command is a TLV - | Operation | Length | Data |
|
// Every command is a TLV - | Operation | Length | Data |
|
||||||
|
|
||||||
|
|
||||||
// Read the operation.
|
// Read the operation.
|
||||||
this.socket.Receive( readBuffer, 4, SocketFlags.None );
|
this.socket.Receive( readBuffer, 4, SocketFlags.None );
|
||||||
|
|
||||||
// Check if we popped out of a receive call after we were shut down.
|
// Check if we popped out of a receive call after we were shut down.
|
||||||
if( this.running == false ) { break; }
|
if( this.running == false ) { break; }
|
||||||
|
|
||||||
operation = (ProtocolOp)ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
operation = (ProtocolOp)ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
||||||
|
|
||||||
// Read the length
|
// Read the length
|
||||||
this.socket.Receive( readBuffer, 4, SocketFlags.None );
|
this.socket.Receive( readBuffer, 4, SocketFlags.None );
|
||||||
messageLength = ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
messageLength = ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
||||||
|
|
||||||
@@ -153,14 +148,13 @@ namespace TestProtocol
|
|||||||
remaining -= chunkLength;
|
remaining -= chunkLength;
|
||||||
position += chunkLength;
|
position += chunkLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( SocketException e )
|
catch( SocketException e )
|
||||||
{
|
{
|
||||||
if( e.SocketErrorCode == SocketError.ConnectionAborted ||
|
if( e.SocketErrorCode == SocketError.ConnectionAborted ||
|
||||||
e.SocketErrorCode == SocketError.Interrupted ||
|
e.SocketErrorCode == SocketError.Interrupted ||
|
||||||
e.SocketErrorCode == SocketError.OperationAborted ||
|
e.SocketErrorCode == SocketError.OperationAborted ||
|
||||||
e.SocketErrorCode == SocketError.Shutdown ||
|
e.SocketErrorCode == SocketError.Shutdown ||
|
||||||
e.SocketErrorCode == SocketError.ConnectionReset )
|
e.SocketErrorCode == SocketError.ConnectionReset )
|
||||||
{
|
{
|
||||||
// Shutting down.
|
// Shutting down.
|
||||||
@@ -179,7 +173,7 @@ namespace TestProtocol
|
|||||||
byte[] dataCopy = new byte[messageLength];
|
byte[] dataCopy = new byte[messageLength];
|
||||||
Array.Copy( readBuffer, 0, dataCopy, 0, messageLength );
|
Array.Copy( readBuffer, 0, dataCopy, 0, messageLength );
|
||||||
Message message = new Message( operation, dataCopy );
|
Message message = new Message( operation, dataCopy );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.Received( message );
|
this.Received( message );
|
||||||
@@ -187,8 +181,7 @@ namespace TestProtocol
|
|||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ namespace TestProtocol
|
|||||||
|
|
||||||
operation = (ProtocolOp)ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
operation = (ProtocolOp)ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
||||||
|
|
||||||
// Read the length
|
// Read the length
|
||||||
this.readSocket.Receive( readBuffer, 4, SocketFlags.None );
|
this.readSocket.Receive( readBuffer, 4, SocketFlags.None );
|
||||||
messageLength = ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
messageLength = ByteWriter.ReadInt32_BE( readBuffer, 0 );
|
||||||
|
|
||||||
@@ -212,7 +212,6 @@ namespace TestProtocol
|
|||||||
catch( Exception )
|
catch( Exception )
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -225,5 +224,4 @@ namespace TestProtocol
|
|||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace TestProtocol
|
namespace TestProtocol
|
||||||
{
|
{
|
||||||
public class Message
|
public class Message
|
||||||
{
|
{
|
||||||
public Message(ProtocolOp op, byte[] data)
|
public Message( ProtocolOp op, byte[] data )
|
||||||
{
|
{
|
||||||
this.Operation = op;
|
this.Operation = op;
|
||||||
this.Data = data;
|
this.Data = data;
|
||||||
@@ -18,4 +14,4 @@ namespace TestProtocol
|
|||||||
|
|
||||||
public byte[] Data { get; private set; }
|
public byte[] Data { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle( "TestProtocol" )]
|
[assembly: AssemblyTitle( "TestProtocol" )]
|
||||||
@@ -14,8 +13,8 @@ using System.Runtime.InteropServices;
|
|||||||
[assembly: AssemblyTrademark( "" )]
|
[assembly: AssemblyTrademark( "" )]
|
||||||
[assembly: AssemblyCulture( "" )]
|
[assembly: AssemblyCulture( "" )]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible( false )]
|
[assembly: ComVisible( false )]
|
||||||
|
|
||||||
@@ -25,12 +24,12 @@ using System.Runtime.InteropServices;
|
|||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace TestProtocol
|
namespace TestProtocol
|
||||||
{
|
{
|
||||||
@@ -14,4 +10,4 @@ namespace TestProtocol
|
|||||||
EncryptedMessage = 3,
|
EncryptedMessage = 3,
|
||||||
SignedMessage = 4,
|
SignedMessage = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
|
||||||
</startup>
|
</startup>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TestServer
|
namespace TestServer
|
||||||
{
|
{
|
||||||
static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
private static void Main()
|
||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault( false );
|
Application.SetCompatibleTextRenderingDefault( false );
|
||||||
Application.Run( new ServerForm() );
|
Application.Run( new ServerForm() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle( "TestServer" )]
|
[assembly: AssemblyTitle( "TestServer" )]
|
||||||
@@ -14,8 +13,8 @@ using System.Runtime.InteropServices;
|
|||||||
[assembly: AssemblyTrademark( "" )]
|
[assembly: AssemblyTrademark( "" )]
|
||||||
[assembly: AssemblyCulture( "" )]
|
[assembly: AssemblyCulture( "" )]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible( false )]
|
[assembly: ComVisible( false )]
|
||||||
|
|
||||||
@@ -25,12 +24,12 @@ using System.Runtime.InteropServices;
|
|||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
||||||
@@ -1,11 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TestProtocol;
|
using TestProtocol;
|
||||||
|
|
||||||
@@ -37,13 +31,13 @@ namespace TestServer
|
|||||||
|
|
||||||
this.serverCred = new ServerCredential( PackageNames.Negotiate );
|
this.serverCred = new ServerCredential( PackageNames.Negotiate );
|
||||||
|
|
||||||
this.serverContext = new ServerContext(
|
this.serverContext = new ServerContext(
|
||||||
serverCred,
|
serverCred,
|
||||||
ContextAttrib.AcceptIntegrity |
|
ContextAttrib.AcceptIntegrity |
|
||||||
ContextAttrib.ReplayDetect |
|
ContextAttrib.ReplayDetect |
|
||||||
ContextAttrib.SequenceDetect |
|
ContextAttrib.SequenceDetect |
|
||||||
ContextAttrib.MutualAuth |
|
ContextAttrib.MutualAuth |
|
||||||
ContextAttrib.Delegate |
|
ContextAttrib.Delegate |
|
||||||
ContextAttrib.Confidentiality
|
ContextAttrib.Confidentiality
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -129,11 +123,11 @@ namespace TestServer
|
|||||||
{
|
{
|
||||||
MessageBox.Show( "Starting impersonation: " + Environment.UserName );
|
MessageBox.Show( "Starting impersonation: " + Environment.UserName );
|
||||||
|
|
||||||
FileStream stream = File.Create( Environment.GetFolderPath( Environment.SpecialFolder.DesktopDirectory) + @"\test.txt" );
|
FileStream stream = File.Create( Environment.GetFolderPath( Environment.SpecialFolder.DesktopDirectory ) + @"\test.txt" );
|
||||||
StreamWriter writer = new StreamWriter( stream, Encoding.UTF8 );
|
StreamWriter writer = new StreamWriter( stream, Encoding.UTF8 );
|
||||||
|
|
||||||
writer.WriteLine( "Hello world." );
|
writer.WriteLine( "Hello world." );
|
||||||
|
|
||||||
writer.Close();
|
writer.Close();
|
||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
@@ -150,7 +144,6 @@ namespace TestServer
|
|||||||
this.signButton.Enabled = this.connected;
|
this.signButton.Enabled = this.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void server_Received( Message message )
|
private void server_Received( Message message )
|
||||||
{
|
{
|
||||||
if( message.Operation == ProtocolOp.ClientToken )
|
if( message.Operation == ProtocolOp.ClientToken )
|
||||||
@@ -177,7 +170,6 @@ namespace TestServer
|
|||||||
this.initializing = true;
|
this.initializing = true;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
|
||||||
|
|
||||||
this.serverContext.Dispose();
|
this.serverContext.Dispose();
|
||||||
this.serverContext = new ServerContext(
|
this.serverContext = new ServerContext(
|
||||||
serverCred,
|
serverCred,
|
||||||
@@ -189,14 +181,13 @@ namespace TestServer
|
|||||||
ContextAttrib.Confidentiality
|
ContextAttrib.Confidentiality
|
||||||
);
|
);
|
||||||
|
|
||||||
this.BeginInvoke( (Action)delegate()
|
this.BeginInvoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
this.clientUsernameTextBox.Text = "";
|
this.clientUsernameTextBox.Text = "";
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void HandleInit( Message message )
|
private void HandleInit( Message message )
|
||||||
{
|
{
|
||||||
byte[] nextToken;
|
byte[] nextToken;
|
||||||
@@ -218,8 +209,8 @@ namespace TestServer
|
|||||||
this.initializing = false;
|
this.initializing = false;
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
|
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
this.clientUsernameTextBox.Text = serverContext.ContextUserName;
|
this.clientUsernameTextBox.Text = serverContext.ContextUserName;
|
||||||
} );
|
} );
|
||||||
@@ -227,29 +218,28 @@ namespace TestServer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
MessageBox.Show( "Failed to accept token from client. Sspi error code: " + status );
|
MessageBox.Show( "Failed to accept token from client. Sspi error code: " + status );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleEncrypted( Message message )
|
private void HandleEncrypted( Message message )
|
||||||
{
|
{
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
byte[] plainText = this.serverContext.Decrypt( message.Data );
|
byte[] plainText = this.serverContext.Decrypt( message.Data );
|
||||||
string text = Encoding.UTF8.GetString( plainText );
|
string text = Encoding.UTF8.GetString( plainText );
|
||||||
|
|
||||||
this.receivedTextbox.Text += "Received encrypted message from client:\r\n" + text + "\r\n";
|
this.receivedTextbox.Text += "Received encrypted message from client:\r\n" + text + "\r\n";
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleSigned( Message message )
|
private void HandleSigned( Message message )
|
||||||
{
|
{
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
byte[] plainText;
|
byte[] plainText;
|
||||||
|
|
||||||
@@ -268,11 +258,10 @@ namespace TestServer
|
|||||||
|
|
||||||
private void HandleUnknown( Message message )
|
private void HandleUnknown( Message message )
|
||||||
{
|
{
|
||||||
this.Invoke( (Action)delegate()
|
this.Invoke( (Action)delegate ()
|
||||||
{
|
{
|
||||||
MessageBox.Show( "Received unexpected message from server. Message type: " + message.Operation );
|
MessageBox.Show( "Received unexpected message from server. Message type: " + message.Operation );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user