mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-07-03 08:13:18 +02:00
Windows Authentication: Improved implementation
This commit is contained in:
parent
acea85ca8c
commit
d7e33e465d
2 changed files with 78 additions and 65 deletions
|
@ -147,7 +147,7 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
);
|
);
|
||||||
|
|
||||||
[DllImport("Secur32.dll")]
|
[DllImport("Secur32.dll")]
|
||||||
private extern static int DeleteSecurityContext(
|
public extern static int DeleteSecurityContext(
|
||||||
ref SecHandle phContext
|
ref SecHandle phContext
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -205,13 +205,14 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
|
|
||||||
public static byte[] GetType1Message(string domainName, string userName, string password, out SecHandle clientContext)
|
public static byte[] GetType1Message(string domainName, string userName, string password, out SecHandle clientContext)
|
||||||
{
|
{
|
||||||
SecHandle handle = AcquireNTLMCredentialsHandle(domainName, userName, password);
|
SecHandle credentialsHandle = AcquireNTLMCredentialsHandle(domainName, userName, password);
|
||||||
clientContext = new SecHandle();
|
clientContext = new SecHandle();
|
||||||
SecBufferDesc output = new SecBufferDesc(MAX_TOKEN_SIZE);
|
SecBuffer outputBuffer = new SecBuffer(MAX_TOKEN_SIZE);
|
||||||
|
SecBufferDesc output = new SecBufferDesc(outputBuffer);
|
||||||
uint contextAttributes;
|
uint contextAttributes;
|
||||||
SECURITY_INTEGER expiry;
|
SECURITY_INTEGER expiry;
|
||||||
|
|
||||||
int result = InitializeSecurityContext(ref handle, IntPtr.Zero, null, ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY, 0, SECURITY_NATIVE_DREP, IntPtr.Zero, 0, ref clientContext, ref output, out contextAttributes, out expiry);
|
int result = InitializeSecurityContext(ref credentialsHandle, IntPtr.Zero, null, ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY, 0, SECURITY_NATIVE_DREP, IntPtr.Zero, 0, ref clientContext, ref output, out contextAttributes, out expiry);
|
||||||
if (result != SEC_E_OK && result != SEC_I_CONTINUE_NEEDED)
|
if (result != SEC_E_OK && result != SEC_I_CONTINUE_NEEDED)
|
||||||
{
|
{
|
||||||
if ((uint)result == SEC_E_INVALID_HANDLE)
|
if ((uint)result == SEC_E_INVALID_HANDLE)
|
||||||
|
@ -227,14 +228,20 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
throw new Exception("InitializeSecurityContext failed, Error code " + ((uint)result).ToString("X"));
|
throw new Exception("InitializeSecurityContext failed, Error code " + ((uint)result).ToString("X"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output.GetSecBufferBytes();
|
FreeCredentialsHandle(ref credentialsHandle);
|
||||||
|
byte[] messageBytes = outputBuffer.GetBufferBytes();
|
||||||
|
outputBuffer.Dispose();
|
||||||
|
output.Dispose();
|
||||||
|
return messageBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] GetType3Message(SecHandle clientContext, byte[] type2Message)
|
public static byte[] GetType3Message(SecHandle clientContext, byte[] type2Message)
|
||||||
{
|
{
|
||||||
SecHandle newContext = new SecHandle();
|
SecHandle newContext = new SecHandle();
|
||||||
SecBufferDesc input = new SecBufferDesc(type2Message);
|
SecBuffer inputBuffer = new SecBuffer(type2Message);
|
||||||
SecBufferDesc output = new SecBufferDesc(MAX_TOKEN_SIZE);
|
SecBufferDesc input = new SecBufferDesc(inputBuffer);
|
||||||
|
SecBuffer outputBuffer = new SecBuffer(MAX_TOKEN_SIZE);
|
||||||
|
SecBufferDesc output = new SecBufferDesc(outputBuffer);
|
||||||
uint contextAttributes;
|
uint contextAttributes;
|
||||||
SECURITY_INTEGER expiry;
|
SECURITY_INTEGER expiry;
|
||||||
|
|
||||||
|
@ -254,19 +261,26 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
throw new Exception("InitializeSecurityContext failed, error code " + ((uint)result).ToString("X"));
|
throw new Exception("InitializeSecurityContext failed, error code " + ((uint)result).ToString("X"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output.GetSecBufferBytes();
|
byte[] messageBytes = outputBuffer.GetBufferBytes();
|
||||||
|
inputBuffer.Dispose();
|
||||||
|
input.Dispose();
|
||||||
|
outputBuffer.Dispose();
|
||||||
|
output.Dispose();
|
||||||
|
return messageBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] GetType2Message(byte[] type1MessageBytes, out SecHandle serverContext)
|
public static byte[] GetType2Message(byte[] type1MessageBytes, out SecHandle serverContext)
|
||||||
{
|
{
|
||||||
SecHandle handle = AcquireNTLMCredentialsHandle();
|
SecHandle credentialsHandle = AcquireNTLMCredentialsHandle();
|
||||||
SecBufferDesc type1Message = new SecBufferDesc(type1MessageBytes);
|
SecBuffer inputBuffer = new SecBuffer(type1MessageBytes);
|
||||||
|
SecBufferDesc input = new SecBufferDesc(inputBuffer);
|
||||||
serverContext = new SecHandle();
|
serverContext = new SecHandle();
|
||||||
SecBufferDesc output = new SecBufferDesc(MAX_TOKEN_SIZE);
|
SecBuffer outputBuffer = new SecBuffer(MAX_TOKEN_SIZE);
|
||||||
|
SecBufferDesc output = new SecBufferDesc(outputBuffer);
|
||||||
uint contextAttributes;
|
uint contextAttributes;
|
||||||
SECURITY_INTEGER timestamp;
|
SECURITY_INTEGER timestamp;
|
||||||
|
|
||||||
int result = AcceptSecurityContext(ref handle, IntPtr.Zero, ref type1Message, ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY, SECURITY_NATIVE_DREP, ref serverContext, ref output, out contextAttributes, out timestamp);
|
int result = AcceptSecurityContext(ref credentialsHandle, IntPtr.Zero, ref input, ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY, SECURITY_NATIVE_DREP, ref serverContext, ref output, out contextAttributes, out timestamp);
|
||||||
if (result != SEC_E_OK && result != SEC_I_CONTINUE_NEEDED)
|
if (result != SEC_E_OK && result != SEC_I_CONTINUE_NEEDED)
|
||||||
{
|
{
|
||||||
if ((uint)result == SEC_E_INVALID_HANDLE)
|
if ((uint)result == SEC_E_INVALID_HANDLE)
|
||||||
|
@ -282,8 +296,13 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
throw new Exception("AcceptSecurityContext failed, error code " + ((uint)result).ToString("X"));
|
throw new Exception("AcceptSecurityContext failed, error code " + ((uint)result).ToString("X"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FreeCredentialsHandle(ref handle);
|
FreeCredentialsHandle(ref credentialsHandle);
|
||||||
return output.GetSecBufferBytes();
|
byte[] messageBytes = outputBuffer.GetBufferBytes();
|
||||||
|
inputBuffer.Dispose();
|
||||||
|
input.Dispose();
|
||||||
|
outputBuffer.Dispose();
|
||||||
|
output.Dispose();
|
||||||
|
return messageBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -303,12 +322,19 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
public static bool AuthenticateType3Message(SecHandle serverContext, byte[] type3MessageBytes)
|
public static bool AuthenticateType3Message(SecHandle serverContext, byte[] type3MessageBytes)
|
||||||
{
|
{
|
||||||
SecHandle newContext = new SecHandle();
|
SecHandle newContext = new SecHandle();
|
||||||
SecBufferDesc type3Message = new SecBufferDesc(type3MessageBytes);
|
SecBuffer inputBuffer = new SecBuffer(type3MessageBytes);
|
||||||
SecBufferDesc output = new SecBufferDesc(MAX_TOKEN_SIZE);
|
SecBufferDesc input = new SecBufferDesc(inputBuffer);
|
||||||
|
SecBuffer outputBuffer = new SecBuffer(MAX_TOKEN_SIZE);
|
||||||
|
SecBufferDesc output = new SecBufferDesc(outputBuffer);
|
||||||
uint contextAttributes;
|
uint contextAttributes;
|
||||||
SECURITY_INTEGER timestamp;
|
SECURITY_INTEGER timestamp;
|
||||||
|
|
||||||
int result = AcceptSecurityContext(IntPtr.Zero, ref serverContext, ref type3Message, ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY, SECURITY_NATIVE_DREP, ref newContext, ref output, out contextAttributes, out timestamp);
|
int result = AcceptSecurityContext(IntPtr.Zero, ref serverContext, ref input, ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY, SECURITY_NATIVE_DREP, ref newContext, ref output, out contextAttributes, out timestamp);
|
||||||
|
|
||||||
|
inputBuffer.Dispose();
|
||||||
|
input.Dispose();
|
||||||
|
outputBuffer.Dispose();
|
||||||
|
output.Dispose();
|
||||||
|
|
||||||
if (result == SEC_E_OK)
|
if (result == SEC_E_OK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
||||||
*
|
*
|
||||||
* You can redistribute this program and/or modify it under the terms of
|
* You can redistribute this program and/or modify it under the terms of
|
||||||
* the GNU Lesser Public License as published by the Free Software Foundation,
|
* the GNU Lesser Public License as published by the Free Software Foundation,
|
||||||
|
@ -11,7 +11,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace SMBLibrary.Authentication.Win32
|
namespace SMBLibrary.Authentication.Win32
|
||||||
{
|
{
|
||||||
public enum SecBufferType
|
public enum SecBufferType : uint
|
||||||
{
|
{
|
||||||
SECBUFFER_VERSION = 0,
|
SECBUFFER_VERSION = 0,
|
||||||
SECBUFFER_EMPTY = 0,
|
SECBUFFER_EMPTY = 0,
|
||||||
|
@ -20,33 +20,33 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct SecBuffer
|
public struct SecBuffer : IDisposable
|
||||||
{
|
{
|
||||||
public int cbBuffer;
|
public uint cbBuffer; // Specifies the size, in bytes, of the buffer pointed to by the pvBuffer member.
|
||||||
public int BufferType;
|
public uint BufferType;
|
||||||
public IntPtr pvBuffer;
|
public IntPtr pvBuffer; // A pointer to a buffer.
|
||||||
|
|
||||||
public SecBuffer(int bufferSize)
|
public SecBuffer(int bufferSize)
|
||||||
{
|
{
|
||||||
cbBuffer = bufferSize;
|
cbBuffer = (uint)bufferSize;
|
||||||
BufferType = (int)SecBufferType.SECBUFFER_TOKEN;
|
BufferType = (uint)SecBufferType.SECBUFFER_TOKEN;
|
||||||
pvBuffer = Marshal.AllocHGlobal(bufferSize);
|
pvBuffer = Marshal.AllocHGlobal(bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecBuffer(byte[] secBufferBytes)
|
public SecBuffer(byte[] secBufferBytes)
|
||||||
{
|
{
|
||||||
cbBuffer = secBufferBytes.Length;
|
cbBuffer = (uint)secBufferBytes.Length;
|
||||||
BufferType = (int)SecBufferType.SECBUFFER_TOKEN;
|
BufferType = (uint)SecBufferType.SECBUFFER_TOKEN;
|
||||||
pvBuffer = Marshal.AllocHGlobal(cbBuffer);
|
pvBuffer = Marshal.AllocHGlobal(secBufferBytes.Length);
|
||||||
Marshal.Copy(secBufferBytes, 0, pvBuffer, cbBuffer);
|
Marshal.Copy(secBufferBytes, 0, pvBuffer, secBufferBytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecBuffer(byte[] secBufferBytes, SecBufferType bufferType)
|
public SecBuffer(byte[] secBufferBytes, SecBufferType bufferType)
|
||||||
{
|
{
|
||||||
cbBuffer = secBufferBytes.Length;
|
cbBuffer = (uint)secBufferBytes.Length;
|
||||||
BufferType = (int)bufferType;
|
BufferType = (uint)bufferType;
|
||||||
pvBuffer = Marshal.AllocHGlobal(cbBuffer);
|
pvBuffer = Marshal.AllocHGlobal(secBufferBytes.Length);
|
||||||
Marshal.Copy(secBufferBytes, 0, pvBuffer, cbBuffer);
|
Marshal.Copy(secBufferBytes, 0, pvBuffer, secBufferBytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -58,63 +58,50 @@ namespace SMBLibrary.Authentication.Win32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetBytes()
|
public byte[] GetBufferBytes()
|
||||||
{
|
{
|
||||||
byte[] buffer = null;
|
byte[] buffer = null;
|
||||||
if (cbBuffer > 0)
|
if (cbBuffer > 0)
|
||||||
{
|
{
|
||||||
buffer = new byte[cbBuffer];
|
buffer = new byte[cbBuffer];
|
||||||
Marshal.Copy(pvBuffer, buffer, 0, cbBuffer);
|
Marshal.Copy(pvBuffer, buffer, 0, (int)cbBuffer);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Simplified SecBufferDesc struct with only one SecBuffer
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct SecBufferDesc
|
public struct SecBufferDesc : IDisposable
|
||||||
{
|
{
|
||||||
public int ulVersion;
|
public uint ulVersion;
|
||||||
public int cBuffers;
|
public uint cBuffers; // Indicates the number of SecBuffer structures in the pBuffers array.
|
||||||
public IntPtr pBuffers;
|
public IntPtr pBuffers; // Pointer to an array of SecBuffer structures.
|
||||||
|
|
||||||
public SecBufferDesc(int bufferSize)
|
public SecBufferDesc(SecBuffer buffer) : this(new SecBuffer[] { buffer })
|
||||||
{
|
{
|
||||||
ulVersion = (int)SecBufferType.SECBUFFER_VERSION;
|
|
||||||
cBuffers = 1;
|
|
||||||
SecBuffer secBuffer = new SecBuffer(bufferSize);
|
|
||||||
pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(secBuffer));
|
|
||||||
Marshal.StructureToPtr(secBuffer, pBuffers, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecBufferDesc(byte[] secBufferBytes)
|
public SecBufferDesc(SecBuffer[] buffers)
|
||||||
{
|
{
|
||||||
ulVersion = (int)SecBufferType.SECBUFFER_VERSION;
|
int secBufferSize = Marshal.SizeOf(typeof(SecBuffer));
|
||||||
cBuffers = 1;
|
ulVersion = (uint)SecBufferType.SECBUFFER_VERSION;
|
||||||
SecBuffer secBuffer = new SecBuffer(secBufferBytes);
|
cBuffers = (uint)buffers.Length;
|
||||||
pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(secBuffer));
|
pBuffers = Marshal.AllocHGlobal(buffers.Length * secBufferSize);
|
||||||
Marshal.StructureToPtr(secBuffer, pBuffers, false);
|
IntPtr currentBuffer = pBuffers;
|
||||||
|
for (int index = 0; index < buffers.Length; index++)
|
||||||
|
{
|
||||||
|
Marshal.StructureToPtr(buffers[index], currentBuffer, false);
|
||||||
|
currentBuffer = new IntPtr(currentBuffer.ToInt64() + secBufferSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (pBuffers != IntPtr.Zero)
|
if (pBuffers != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
SecBuffer secBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers, typeof(SecBuffer));
|
|
||||||
secBuffer.Dispose();
|
|
||||||
Marshal.FreeHGlobal(pBuffers);
|
Marshal.FreeHGlobal(pBuffers);
|
||||||
pBuffers = IntPtr.Zero;
|
pBuffers = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetSecBufferBytes()
|
|
||||||
{
|
|
||||||
if (pBuffers == IntPtr.Zero)
|
|
||||||
throw new ObjectDisposedException("SecBufferDesc");
|
|
||||||
SecBuffer secBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers, typeof(SecBuffer));
|
|
||||||
return secBuffer.GetBytes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue