mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
libwinpr-sspi: add support for passing NTLMv2 hash
This commit is contained in:
@@ -1017,6 +1017,7 @@ typedef struct _SecPkgContext_AuthPassword SecPkgContext_AuthPassword;
|
||||
|
||||
struct _SecPkgContext_AuthNtlmHash
|
||||
{
|
||||
int Version;
|
||||
BYTE NtlmHash[16];
|
||||
};
|
||||
typedef struct _SecPkgContext_AuthNtlmHash SecPkgContext_AuthNtlmHash;
|
||||
|
||||
@@ -168,6 +168,7 @@ NTLM_CONTEXT* ntlm_ContextNew()
|
||||
context->SendSingleHostData = FALSE;
|
||||
context->SendWorkstationName = TRUE;
|
||||
context->NegotiateKeyExchange = TRUE;
|
||||
context->UseSamFileDatabase = TRUE;
|
||||
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
|
||||
@@ -675,6 +676,8 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
|
||||
SSPI_CREDENTIALS* credentials;
|
||||
SecPkgContext_AuthIdentity* AuthIdentity = (SecPkgContext_AuthIdentity*) pBuffer;
|
||||
|
||||
context->UseSamFileDatabase = FALSE;
|
||||
|
||||
credentials = context->credentials;
|
||||
ZeroMemory(AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
|
||||
|
||||
@@ -724,7 +727,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULON
|
||||
if (cbBuffer < sizeof(SecPkgContext_AuthNtlmHash))
|
||||
return SEC_E_INVALID_PARAMETER;
|
||||
|
||||
CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
|
||||
if (AuthNtlmHash->Version == 1)
|
||||
CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
|
||||
else if (AuthNtlmHash->Version == 2)
|
||||
CopyMemory(context->NtlmV2Hash, AuthNtlmHash->NtlmHash, 16);
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
@@ -241,6 +241,7 @@ struct _NTLM_CONTEXT
|
||||
BYTE* SendSealingKey;
|
||||
BYTE* RecvSealingKey;
|
||||
UINT32 NegotiateFlags;
|
||||
BOOL UseSamFileDatabase;
|
||||
int LmCompatibilityLevel;
|
||||
int SuppressExtendedProtection;
|
||||
BOOL SendWorkstationName;
|
||||
|
||||
@@ -299,6 +299,9 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
|
||||
{
|
||||
SSPI_CREDENTIALS* credentials = context->credentials;
|
||||
|
||||
if (memcmp(context->NtlmV2Hash, NTLM_NULL_BUFFER, 16) != 0)
|
||||
return 1;
|
||||
|
||||
if (memcmp(context->NtlmHash, NTLM_NULL_BUFFER, 16) != 0)
|
||||
{
|
||||
NTOWFv2FromHashW(context->NtlmHash,
|
||||
@@ -324,7 +327,7 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
|
||||
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
|
||||
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash);
|
||||
}
|
||||
else
|
||||
else if (context->UseSamFileDatabase)
|
||||
{
|
||||
ntlm_fetch_ntlm_v2_hash(context, hash);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,11 @@ static const char* TEST_NTLM_PASSWORD = "P4ss123!";
|
||||
static const BYTE TEST_NTLM_HASH[16] =
|
||||
{ 0xd5, 0x92, 0x2a, 0x65, 0xc4, 0xd5, 0xc0, 0x82, 0xca, 0x44, 0x4a, 0xf1, 0xbe, 0x00, 0x01, 0xdb };
|
||||
|
||||
//static const char* TEST_NTLM_HASH_V2_STRING = "4c7f706f7dde05a9d1a0f4e7ffe3bfb8";
|
||||
|
||||
static const BYTE TEST_NTLM_V2_HASH[16] =
|
||||
{ 0x4c, 0x7f, 0x70, 0x6f, 0x7d, 0xde, 0x05, 0xa9, 0xd1, 0xa0, 0xf4, 0xe7, 0xff, 0xe3, 0xbf, 0xb8 };
|
||||
|
||||
//#define NTLM_PACKAGE_NAME NEGOSSP_NAME
|
||||
#define NTLM_PACKAGE_NAME NTLMSP_NAME
|
||||
|
||||
@@ -303,6 +308,7 @@ struct _TEST_NTLM_SERVER
|
||||
SecBuffer outputBuffer[2];
|
||||
BOOL haveContext;
|
||||
BOOL haveInputBuffer;
|
||||
BOOL UseNtlmV2Hash;
|
||||
LPTSTR ServicePrincipalName;
|
||||
SecBufferDesc inputBufferDesc;
|
||||
SecBufferDesc outputBufferDesc;
|
||||
@@ -318,6 +324,8 @@ int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
|
||||
ntlm->UseNtlmV2Hash = TRUE;
|
||||
|
||||
SecInvalidateHandle(&(ntlm->context));
|
||||
|
||||
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
|
||||
@@ -422,10 +430,19 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm)
|
||||
{
|
||||
if (strcmp(AuthIdentity.User, TEST_NTLM_USER) == 0)
|
||||
{
|
||||
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_HASH, 16);
|
||||
if (ntlm->UseNtlmV2Hash)
|
||||
{
|
||||
AuthNtlmHash.Version = 2;
|
||||
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_V2_HASH, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthNtlmHash.Version = 1;
|
||||
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_HASH, 16);
|
||||
}
|
||||
|
||||
status = ntlm->table->SetContextAttributes(&ntlm->context,
|
||||
SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
|
||||
SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int index = 1;
|
||||
int format = 0;
|
||||
int version = 1;
|
||||
BYTE NtHash[16];
|
||||
char* User = NULL;
|
||||
UINT32 UserLength;
|
||||
@@ -93,10 +95,40 @@ int main(int argc, char* argv[])
|
||||
|
||||
Password = argv[index];
|
||||
}
|
||||
else if (strcmp("-v", argv[index]) == 0)
|
||||
{
|
||||
index++;
|
||||
|
||||
if (index == argc)
|
||||
{
|
||||
printf("missing version\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
version = atoi(argv[index]);
|
||||
|
||||
if ((version != 1) && (version != 2))
|
||||
version = 1;
|
||||
}
|
||||
else if (strcmp("-f", argv[index]) == 0)
|
||||
{
|
||||
index++;
|
||||
|
||||
if (index == argc)
|
||||
{
|
||||
printf("missing format\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp("default", argv[index]) == 0)
|
||||
format = 0;
|
||||
else if (strcmp("sam", argv[index]) == 0)
|
||||
format = 1;
|
||||
}
|
||||
else if (strcmp("-h", argv[index]) == 0)
|
||||
{
|
||||
printf("winpr-hash: NTLM hashing tool\n");
|
||||
printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>]\n");
|
||||
printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>] -f <default,sam> -v <1,2>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -113,22 +145,44 @@ int main(int argc, char* argv[])
|
||||
PasswordLength = strlen(Password);
|
||||
DomainLength = (Domain) ? strlen(Domain) : 0;
|
||||
|
||||
NTOWFv1A(Password, PasswordLength, NtHash);
|
||||
if (version == 2)
|
||||
{
|
||||
if (!Domain)
|
||||
{
|
||||
printf("missing domain\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%s:", User);
|
||||
|
||||
if (DomainLength > 0)
|
||||
printf("%s:", Domain);
|
||||
NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
NTOWFv1A(Password, PasswordLength, NtHash);
|
||||
}
|
||||
|
||||
if (format == 0)
|
||||
{
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
printf("\n");
|
||||
}
|
||||
else if (format == 1)
|
||||
{
|
||||
printf("%s:", User);
|
||||
|
||||
if (DomainLength > 0)
|
||||
printf("%s:", Domain);
|
||||
else
|
||||
printf(":");
|
||||
|
||||
printf(":");
|
||||
|
||||
printf(":");
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
|
||||
for (index = 0; index < 16; index++)
|
||||
printf("%02x", NtHash[index]);
|
||||
|
||||
printf(":::");
|
||||
printf("\n");
|
||||
printf(":::");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user