Added support for querying the context's user name and authority. Still working my way up to EncryptMessage.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
44
Contexts/ContextQueries.cs
Normal file
44
Contexts/ContextQueries.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Contexts/ContextQueryAttrib.cs
Normal file
40
Contexts/ContextQueryAttrib.cs
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
11
Program.cs
11
Program.cs
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user