Merge pull request #8 from mcgov/master

Adding QuerySessionKey, as well as QueryContextAttributes and SafeQue…
This commit is contained in:
Kevin Thompson
2017-09-23 15:00:00 -04:00
committed by GitHub
3 changed files with 272 additions and 152 deletions

View File

@@ -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>

View File

@@ -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.

View File

@@ -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
} }
} }