Added support for querying the context's user name and authority. Still working my way up to EncryptMessage.

This commit is contained in:
antiduh
2014-06-23 18:30:26 +00:00
parent 1be2b9c7ef
commit 9785183f31
6 changed files with 215 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace NSspi
{
@@ -27,6 +28,22 @@ namespace NSspi
public long ContextHandle { get; protected set; }
public string AuthorityName
{
get
{
return QueryContextString( ContextQueryAttrib.Authority );
}
}
public string ContextUserName
{
get
{
return QueryContextString( ContextQueryAttrib.Names );
}
}
public void Dispose()
{
Dispose( true );
@@ -50,8 +67,79 @@ namespace NSspi
this.disposed = true;
}
/// <summary>
/// Encrypts the byte array using the context's session key. The encrypted data is stored in a new
/// byte array, which is formatted such that the first four bytes are the original message length
/// as an unsigned integer and the remaining bytes are the encrypted bytes of the original message.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public byte[] Encrypt( byte[] input )
{
// The message is encrypted in place in the buffer we provide to Win32 EncryptMessage
return null;
}
internal SecPkgContext_Sizes QueryBufferSizes()
{
SecPkgContext_Sizes sizes = new SecPkgContext_Sizes();
long contextHandle = this.ContextHandle;
SecurityStatus status;
status = ContextNativeMethods.QueryContextAttributes_Sizes(
ref contextHandle,
ContextQueryAttrib.Sizes,
ref sizes
);
if( status != SecurityStatus.OK )
{
throw new SSPIException( "Failed to query context buffer size attributes", status );
}
return sizes;
}
internal string QueryContextString(ContextQueryAttrib attrib)
{
SecPkgContext_String stringAttrib;
long contextHandle;
SecurityStatus status;
string result;
if( attrib != ContextQueryAttrib.Names && attrib != ContextQueryAttrib.Authority )
{
throw new InvalidOperationException( "QueryContextString can only be used to query context Name and Authority attributes" );
}
stringAttrib = new SecPkgContext_String();
contextHandle = this.ContextHandle;
status = ContextNativeMethods.QueryContextAttributes_String(
ref contextHandle,
attrib,
ref stringAttrib
);
if( status == SecurityStatus.Unsupported )
{
return null;
}
else if( status == SecurityStatus.OK )
{
// TODO handle this safely.
result = Marshal.PtrToStringUni( stringAttrib.StringResult );
ContextNativeMethods.FreeContextBuffer( stringAttrib.StringResult );
}
else
{
throw new SSPIException( "Failed to query the context's associated user name", status );
}
return result;
}
}
}

View File

@@ -151,7 +151,7 @@ namespace NSspi.Contexts
[DllImport(
"Secur32.dll",
EntryPoint = "EncryptMessag",
EntryPoint = "EncryptMessage",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode,
SetLastError = true
@@ -162,5 +162,35 @@ namespace NSspi.Contexts
IntPtr bufferDescriptor,
int sequenceNumber
);
[DllImport(
"Secur32.dll",
EntryPoint = "QueryContextAttributes",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode )]
public static extern SecurityStatus QueryContextAttributes_Sizes(
ref long contextHandle,
ContextQueryAttrib attrib,
ref SecPkgContext_Sizes sizes
);
[DllImport(
"Secur32.dll",
EntryPoint = "QueryContextAttributes",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode )]
public static extern SecurityStatus QueryContextAttributes_String(
ref long contextHandle,
ContextQueryAttrib attrib,
ref SecPkgContext_String names
);
[DllImport(
"Secur32.dll",
EntryPoint = "FreeContextBuffer",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Unicode )]
public static extern SecurityStatus FreeContextBuffer( IntPtr handle );
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace NSspi.Contexts
{
[StructLayout( LayoutKind.Sequential )]
public struct SecPkgContext_Sizes
{
public int MaxToken;
public int MaxSignature;
public int BlockSize;
public int SecurityTrailer;
}
[StructLayout( LayoutKind.Sequential )]
public struct SecPkgContext_String
{
public IntPtr StringResult;
}
public class ContextQueryHandle : SafeHandle
{
public ContextQueryHandle() :
base( IntPtr.Zero, true )
{
}
public override bool IsInvalid
{
get { return base.handle.Equals( IntPtr.Zero ); }
}
protected override bool ReleaseHandle()
{
return ContextNativeMethods.FreeContextBuffer( base.handle ) == SecurityStatus.OK;
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NSspi.Contexts
{
/// <summary>
/// Defines the types of queries that can be performed with QueryContextAttribute.
/// Each query has a different result buffer.
/// </summary>
public enum ContextQueryAttrib : int
{
/// <summary>
/// Queries the buffer size parameters when performing message functions, such
/// as encryption, decryption, signing and signature validation.
/// </summary>
/// <remarks>
/// Results for a query of this type are stored in a Win32 SecPkgContext_Sizes structure.
/// </remarks>
Sizes = 0,
/// <summary>
/// Queries the context for the name of the user assocated with a security context.
/// </summary>
/// <remarks>
/// Results for a query of this type are stored in a Win32 SecPkgContext_Name structure.
/// </remarks>
Names = 1,
/// <summary>
/// Queries the name of the authenticating authority for the security context.
/// </summary>
/// <remarks>
/// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
/// </remarks>
Authority = 6,
}
}

View File

@@ -49,6 +49,8 @@
<Compile Include="Contexts\Context.cs" />
<Compile Include="Contexts\ContextAttrib.cs" />
<Compile Include="Contexts\ContextNativeMethods.cs" />
<Compile Include="Contexts\ContextQueries.cs" />
<Compile Include="Contexts\ContextQueryAttrib.cs" />
<Compile Include="Contexts\ServerContext.cs" />
<Compile Include="Credentials\ClientCredential.cs" />
<Compile Include="Credentials\Credential.cs" />

View File

@@ -91,7 +91,16 @@ namespace NSspi
if ( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
}
Console.Out.WriteLine( "Server authority: " + server.AuthorityName );
Console.Out.WriteLine( "Server context user: " + server.ContextUserName );
Console.Out.WriteLine();
Console.Out.WriteLine( "Client authority: " + client.AuthorityName );
Console.Out.WriteLine( "Client context user: " + client.ContextUserName );
Console.Out.Flush();
}
finally