diff --git a/Contexts/Context.cs b/Contexts/Context.cs
index f5e5cd3..cd9d922 100644
--- a/Contexts/Context.cs
+++ b/Contexts/Context.cs
@@ -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;
}
+ ///
+ /// 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.
+ ///
+ ///
+ ///
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;
+ }
+
}
}
diff --git a/Contexts/ContextNativeMethods.cs b/Contexts/ContextNativeMethods.cs
index 913f53b..7e1893d 100644
--- a/Contexts/ContextNativeMethods.cs
+++ b/Contexts/ContextNativeMethods.cs
@@ -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 );
}
}
diff --git a/Contexts/ContextQueries.cs b/Contexts/ContextQueries.cs
new file mode 100644
index 0000000..7df6785
--- /dev/null
+++ b/Contexts/ContextQueries.cs
@@ -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;
+ }
+ }
+}
diff --git a/Contexts/ContextQueryAttrib.cs b/Contexts/ContextQueryAttrib.cs
new file mode 100644
index 0000000..a3019e1
--- /dev/null
+++ b/Contexts/ContextQueryAttrib.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NSspi.Contexts
+{
+ ///
+ /// Defines the types of queries that can be performed with QueryContextAttribute.
+ /// Each query has a different result buffer.
+ ///
+ public enum ContextQueryAttrib : int
+ {
+ ///
+ /// Queries the buffer size parameters when performing message functions, such
+ /// as encryption, decryption, signing and signature validation.
+ ///
+ ///
+ /// Results for a query of this type are stored in a Win32 SecPkgContext_Sizes structure.
+ ///
+ Sizes = 0,
+
+ ///
+ /// Queries the context for the name of the user assocated with a security context.
+ ///
+ ///
+ /// Results for a query of this type are stored in a Win32 SecPkgContext_Name structure.
+ ///
+ Names = 1,
+
+ ///
+ /// Queries the name of the authenticating authority for the security context.
+ ///
+ ///
+ /// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
+ ///
+ Authority = 6,
+ }
+}
diff --git a/NSspi.csproj b/NSspi.csproj
index b18a9bc..ddd141a 100644
--- a/NSspi.csproj
+++ b/NSspi.csproj
@@ -49,6 +49,8 @@
+
+
diff --git a/Program.cs b/Program.cs
index 568679d..aea19f0 100644
--- a/Program.cs
+++ b/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