Merge pull request #8 from mcgov/master
Adding QuerySessionKey, as well as QueryContextAttributes and SafeQue…
This commit is contained in:
@@ -389,6 +389,36 @@ namespace NSspi.Contexts
|
|||||||
return outMessage;
|
return outMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the Session Key from a context or null on failure.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Session keys are sometimes needed for other purposes or HMAC functions. This function will run QueryAttribute to get the session key struct, and read and return the key from that struct.
|
||||||
|
/// </remarks>
|
||||||
|
///
|
||||||
|
/// <returns>byte[] with the session key data or null on failure</returns>
|
||||||
|
public byte[] QuerySessionKey()
|
||||||
|
{
|
||||||
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
|
|
||||||
|
byte[] SessionKey = null;
|
||||||
|
|
||||||
|
status = ContextNativeMethods.SafeQueryContextAttribute(
|
||||||
|
this.ContextHandle,
|
||||||
|
ContextQueryAttrib.SessionKey,
|
||||||
|
ref SessionKey
|
||||||
|
);
|
||||||
|
|
||||||
|
if (status != SecurityStatus.OK)
|
||||||
|
{
|
||||||
|
throw new SSPIException("Failed to query session key.", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies the signature of a signed message
|
/// Verifies the signature of a signed message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -163,6 +163,14 @@ namespace NSspi.Contexts
|
|||||||
ref SecPkgContext_String names
|
ref SecPkgContext_String names
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||||
|
[DllImport("Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern SecurityStatus QueryContextAttributes(
|
||||||
|
ref RawSspiHandle contextHandle,
|
||||||
|
ContextQueryAttrib attrib,
|
||||||
|
IntPtr attribute
|
||||||
|
);
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
[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);
|
||||||
@@ -176,6 +184,75 @@ namespace NSspi.Contexts
|
|||||||
[DllImport("Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode)]
|
[DllImport("Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode)]
|
||||||
internal static extern SecurityStatus RevertSecurityContext(ref RawSspiHandle contextHandle);
|
internal static extern SecurityStatus RevertSecurityContext(ref RawSspiHandle contextHandle);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
class KeyStruct
|
||||||
|
{
|
||||||
|
public int size;
|
||||||
|
public IntPtr data;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static SecurityStatus SafeQueryContextAttribute(
|
||||||
|
SafeContextHandle handle,
|
||||||
|
ContextQueryAttrib attribute,
|
||||||
|
ref byte[] buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool gotRef = false;
|
||||||
|
|
||||||
|
SecurityStatus status = SecurityStatus.InternalError;
|
||||||
|
RuntimeHelpers.PrepareConstrainedRegions();
|
||||||
|
|
||||||
|
|
||||||
|
int pointerSize = System.Environment.Is64BitOperatingSystem ? 8 : 4; //NOTE: update this when 128 bit processors exist
|
||||||
|
IntPtr alloc_buffer = Marshal.AllocHGlobal(sizeof(uint) + pointerSize); //NOTE: this is at most 4 + sizeof(void*) bytes
|
||||||
|
//see struct SecPkgContext_SessionKey
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa380096(v=vs.85).aspx
|
||||||
|
try
|
||||||
|
{
|
||||||
|
handle.DangerousAddRef(ref gotRef);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (gotRef)
|
||||||
|
{
|
||||||
|
handle.DangerousRelease();
|
||||||
|
gotRef = false;
|
||||||
|
buffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (gotRef)
|
||||||
|
{
|
||||||
|
status = ContextNativeMethods.QueryContextAttributes(
|
||||||
|
ref handle.rawHandle,
|
||||||
|
attribute,
|
||||||
|
alloc_buffer
|
||||||
|
);
|
||||||
|
if (status == SecurityStatus.OK)
|
||||||
|
{
|
||||||
|
KeyStruct key = new KeyStruct();
|
||||||
|
|
||||||
|
Marshal.PtrToStructure(alloc_buffer, key); // fit to the proper size, read a byte[]
|
||||||
|
|
||||||
|
byte[] sizedBuffer = new byte[key.size];
|
||||||
|
|
||||||
|
for (int i = 0; i < key.size; i++)
|
||||||
|
sizedBuffer[i] = Marshal.ReadByte(key.data, i);
|
||||||
|
|
||||||
|
buffer = sizedBuffer;
|
||||||
|
}
|
||||||
|
handle.DangerousRelease();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Marshal.FreeHGlobal(alloc_buffer);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <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.
|
||||||
|
|||||||
@@ -36,5 +36,18 @@ namespace NSspi.Contexts
|
|||||||
/// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
|
/// Results for a query of this type are stored in a Win32 SecPkgContext_Authority structure.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
Authority = 6,
|
Authority = 6,
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries the context for it's neogtiated SessionKey
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Results for a query of this type are stored in a Win32 SecPkgContext_SessionKey structure
|
||||||
|
/// </remarks>
|
||||||
|
SessionKey = 9,
|
||||||
|
|
||||||
|
|
||||||
|
AccessToken = 13, //not implemented yet but this would be cool
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user