From 0ebc7e2ab463648b57ee88a30c598e2af1770ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 9 Jun 2014 15:25:00 -0400 Subject: [PATCH] libwinpr-sspi: add custom API for passing NTLM hashes and credentials dynamically --- winpr/libwinpr/sspi/CredSSP/credssp.c | 14 +-- winpr/libwinpr/sspi/NTLM/ntlm.c | 120 ++++++++------------ winpr/libwinpr/sspi/NTLM/ntlm.h | 4 +- winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 87 ++++++++------- winpr/libwinpr/sspi/NTLM/ntlm_compute.h | 2 +- winpr/libwinpr/sspi/NTLM/ntlm_message.c | 98 +++++++++++++--- winpr/libwinpr/sspi/Negotiate/negotiate.c | 130 +++++++++------------- winpr/libwinpr/sspi/sspi.h | 11 +- winpr/libwinpr/sspi/sspi_winpr.c | 8 +- winpr/libwinpr/sspi/test/TestNTLM.c | 117 ++++++++++++++++--- 10 files changed, 359 insertions(+), 232 deletions(-) diff --git a/winpr/libwinpr/sspi/CredSSP/credssp.c b/winpr/libwinpr/sspi/CredSSP/credssp.c index b854da06f..962ad080d 100644 --- a/winpr/libwinpr/sspi/CredSSP/credssp.c +++ b/winpr/libwinpr/sspi/CredSSP/credssp.c @@ -44,7 +44,7 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { CREDSSP_CONTEXT* context; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; context = (CREDSSP_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -55,7 +55,7 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede if (!context) return SEC_E_INSUFFICIENT_MEMORY; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME); @@ -106,7 +106,7 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincip ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; if (fCredentialUse == SECPKG_CRED_OUTBOUND) @@ -138,9 +138,9 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred { if (ulAttribute == SECPKG_CRED_ATTR_NAMES) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); return SEC_E_OK; } @@ -150,12 +150,12 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; if (!phCredential) return SEC_E_INVALID_HANDLE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); if (!credentials) return SEC_E_INVALID_HANDLE; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index cfdfbfd0c..1fab586b8 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -246,10 +246,6 @@ void ntlm_ContextFree(NTLM_CONTEXT* context) sspi_SecBufferFree(&context->LmChallengeResponse); free(context->ServicePrincipalName.Buffer); - - free(context->identity.User); - free(context->identity.Password); - free(context->identity.Domain); free(context->Workstation.Buffer); free(context); } @@ -258,43 +254,32 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; - if (fCredentialUse == SECPKG_CRED_OUTBOUND) + if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INSUFFICIENT_MEMORY; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); - - return SEC_E_OK; + return SEC_E_INVALID_PARAMETER; } - else if (fCredentialUse == SECPKG_CRED_INBOUND) - { - credentials = sspi_CredentialsNew(); - if (!credentials) - return SEC_E_INSUFFICIENT_MEMORY; + credentials = sspi_CredentialsNew(); - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; + if (!credentials) + return SEC_E_INTERNAL_ERROR; - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); + credentials->fCredentialUse = fCredentialUse; + credentials->pGetKeyFn = pGetKeyFn; + credentials->pvGetKeyArgument = pvGetKeyArgument; - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); + identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - return SEC_E_OK; - } + if (identity) + sspi_CopyAuthIdentity(&(credentials->identity), identity); + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); return SEC_E_OK; } @@ -303,55 +288,44 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; - if (fCredentialUse == SECPKG_CRED_OUTBOUND) + if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INSUFFICIENT_MEMORY; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); - - return SEC_E_OK; + return SEC_E_INVALID_PARAMETER; } - else if (fCredentialUse == SECPKG_CRED_INBOUND) - { - credentials = sspi_CredentialsNew(); - if (!credentials) - return SEC_E_INSUFFICIENT_MEMORY; + credentials = sspi_CredentialsNew(); - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; + if (!credentials) + return SEC_E_INTERNAL_ERROR; - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); + credentials->fCredentialUse = fCredentialUse; + credentials->pGetKeyFn = pGetKeyFn; + credentials->pvGetKeyArgument = pvGetKeyArgument; - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); + identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - return SEC_E_OK; - } + if (identity) + sspi_CopyAuthIdentity(&(credentials->identity), identity); + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); return SEC_E_OK; } SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; if (!phCredential) return SEC_E_INVALID_HANDLE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); if (!credentials) return SEC_E_INVALID_HANDLE; @@ -385,7 +359,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P { NTLM_CONTEXT* context; SECURITY_STATUS status; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; PSecBuffer input_buffer; PSecBuffer output_buffer; @@ -403,10 +377,8 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P if (fContextReq & ASC_REQ_CONFIDENTIALITY) context->confidentiality = TRUE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - - if (sspi_CopyAuthIdentity(&context->identity, &credentials->identity) < 0) - return SEC_E_INSUFFICIENT_MEMORY; + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + context->credentials = credentials; ntlm_SetContextTargetName(context, NULL); @@ -502,7 +474,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti { NTLM_CONTEXT* context; SECURITY_STATUS status; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; PSecBuffer input_buffer = NULL; PSecBuffer output_buffer = NULL; PSecBuffer channel_bindings = NULL; @@ -519,19 +491,17 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti if (fContextReq & ISC_REQ_CONFIDENTIALITY) context->confidentiality = TRUE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + context->credentials = credentials; if (context->Workstation.Length < 1) { if (ntlm_SetContextWorkstation(context, NULL) < 0) - return SEC_E_INSUFFICIENT_MEMORY; + return SEC_E_INTERNAL_ERROR; } if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0) - return SEC_E_INSUFFICIENT_MEMORY; - - if (sspi_CopyAuthIdentity(&context->identity, &credentials->identity) < 0) - return SEC_E_INSUFFICIENT_MEMORY; + return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME); @@ -624,7 +594,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti if (pszTargetName) { if (ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0) <= 0) - return SEC_E_INSUFFICIENT_MEMORY; + return SEC_E_INTERNAL_ERROR; } status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq, diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index b867bac91..229debcc3 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -228,6 +228,8 @@ struct _NTLM_CONTEXT NTLM_STATE state; int SendSeqNum; int RecvSeqNum; + BYTE NtlmHash[16]; + BYTE NtlmV2Hash[16]; BYTE MachineID[32]; BOOL SendVersionInfo; BOOL confidentiality; @@ -243,7 +245,7 @@ struct _NTLM_CONTEXT BOOL SendWorkstationName; UNICODE_STRING Workstation; UNICODE_STRING ServicePrincipalName; - SEC_WINNT_AUTH_IDENTITY identity; + SSPI_CREDENTIALS* credentials; BYTE* ChannelBindingToken; BYTE ChannelBindingsHash[16]; SecPkgContext_Bindings Bindings; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index 0d6383848..52d5cfce5 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -39,6 +39,9 @@ static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client si static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server sealing key magic constant"; static const char NTLM_SERVER_SEAL_MAGIC[] = "session key to server-to-client sealing key magic constant"; +static const BYTE NTLM_NULL_HASH[16] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + /** * Populate VERSION structure.\n * VERSION @msdn{cc236654} @@ -200,10 +203,11 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context) ntlm_current_time(context->Timestamp); } -int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) +int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) { WINPR_SAM* sam; WINPR_SAM_ENTRY* entry; + SSPI_CREDENTIALS* credentials = context->credentials; sam = SamOpen(TRUE); @@ -211,8 +215,8 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) return -1; entry = SamLookupUserW(sam, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, - (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2); if (entry) { @@ -222,8 +226,8 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) #endif NTOWFv2FromHashW(entry->NtHash, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, - (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); SamFreeEntry(sam, entry); @@ -233,7 +237,7 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) } entry = SamLookupUserW(sam, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, NULL, 0); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, NULL, 0); if (entry) { @@ -243,8 +247,8 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) #endif NTOWFv2FromHashW(entry->NtHash, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, - (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); SamFreeEntry(sam, entry); @@ -269,12 +273,14 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) int i, hn, ln; char* PasswordHash = NULL; UINT32 PasswordHashLength = 0; + SSPI_CREDENTIALS* credentials = context->credentials; /* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */ - PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR; + PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR; - status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL); + status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password, + PasswordHashLength, &PasswordHash, 0, NULL, NULL); if (status <= 0) return -1; @@ -293,27 +299,34 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) return 1; } -int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) +int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) { - if (context->identity.PasswordLength > 256) + SSPI_CREDENTIALS* credentials = context->credentials; + + if (memcmp(context->NtlmHash, NTLM_NULL_HASH, 16) != 0) { - BYTE PasswordHash[16]; - - /* Special case for WinPR: password hash */ - - if (ntlm_convert_password_hash(context, PasswordHash) < 0) - return -1; - - NTOWFv2FromHashW(PasswordHash, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, - (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, + NTOWFv2FromHashW(context->NtlmHash, + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); } - else if (context->identity.PasswordLength > 0) + else if (credentials->identity.PasswordLength > 256) { - NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2, - (LPWSTR) context->identity.User, context->identity.UserLength * 2, - (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (BYTE*) hash); + /* Special case for WinPR: password hash */ + + if (ntlm_convert_password_hash(context, context->NtlmHash) < 0) + return -1; + + NTOWFv2FromHashW(context->NtlmHash, + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, + (BYTE*) hash); + } + else if (credentials->identity.PasswordLength > 0) + { + NTOWFv2W((LPWSTR) credentials->identity.Password, credentials->identity.PasswordLength * 2, + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); } else { @@ -325,9 +338,8 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { - char* response; - char value[16]; - char ntlm_v2_hash[16]; + BYTE* response; + BYTE value[16]; if (context->LmCompatibilityLevel < 2) { @@ -341,7 +353,7 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) /* Compute the NTLMv2 hash */ - if (ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash) < 0) + if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0) return -1; /* Concatenate the server and client challenges */ @@ -351,10 +363,10 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24)) return -1; - response = (char*) context->LmChallengeResponse.pvBuffer; + response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ - HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL); + HMAC(EVP_md5(), (void*) context->NtlmV2Hash, 16, (BYTE*) value, 16, (BYTE*) response, NULL); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); @@ -372,7 +384,6 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; - BYTE ntlm_v2_hash[16]; BYTE nt_proof_str[16]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; @@ -388,7 +399,7 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) /* Compute the NTLMv2 hash */ - if (ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash) < 0) + if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0) return -1; #ifdef WITH_DEBUG_NTLM @@ -409,7 +420,7 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) fprintf(stderr, "\n"); fprintf(stderr, "NTOWFv2, NTLMv2 Hash\n"); - winpr_HexDump(ntlm_v2_hash, 16); + winpr_HexDump(context->NtlmV2Hash, 16); fprintf(stderr, "\n"); #endif @@ -438,8 +449,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); - HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer, - ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL); + HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer, + ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, NULL); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -451,7 +462,7 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ - HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) context->SessionBaseKey, NULL); + HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) nt_proof_str, 16, (BYTE*) context->SessionBaseKey, NULL); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.h b/winpr/libwinpr/sspi/NTLM/ntlm_compute.h index 9da3c32f0..ba99c81ae 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.h @@ -38,7 +38,7 @@ void ntlm_output_channel_bindings(NTLM_CONTEXT* context); void ntlm_current_time(BYTE* timestamp); void ntlm_generate_timestamp(NTLM_CONTEXT* context); -int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash); +int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash); int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context); int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c index e09051dad..88e841685 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -676,6 +676,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer NTLMv2_RESPONSE response; UINT32 PayloadBufferOffset; NTLM_AUTHENTICATE_MESSAGE* message; + SSPI_CREDENTIALS* credentials = context->credentials; flags = 0; MicOffset = 0; @@ -821,24 +822,94 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer if (message->UserName.Len > 0) { - context->identity.User = (UINT16*) malloc(message->UserName.Len); + credentials->identity.User = (UINT16*) malloc(message->UserName.Len); - if (!context->identity.User) + if (!credentials->identity.User) return SEC_E_INTERNAL_ERROR; - CopyMemory(context->identity.User, message->UserName.Buffer, message->UserName.Len); - context->identity.UserLength = message->UserName.Len / 2; + CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len); + credentials->identity.UserLength = message->UserName.Len / 2; } if (message->DomainName.Len > 0) { - context->identity.Domain = (UINT16*) malloc(message->DomainName.Len); + credentials->identity.Domain = (UINT16*) malloc(message->DomainName.Len); - if (!context->identity.Domain) + if (!credentials->identity.Domain) return SEC_E_INTERNAL_ERROR; - CopyMemory(context->identity.Domain, message->DomainName.Buffer, message->DomainName.Len); - context->identity.DomainLength = message->DomainName.Len / 2; + CopyMemory(credentials->identity.Domain, message->DomainName.Buffer, message->DomainName.Len); + credentials->identity.DomainLength = message->DomainName.Len / 2; + } + + /* Computations beyond this point require the NTLM hash of the password */ + + if (credentials->pGetKeyFn) + { + BYTE* value; + void* pKey = NULL; + SECURITY_STATUS GetKeyStatus = SEC_E_UNSUPPORTED_FUNCTION; + + if (GetKeyStatus != SEC_E_OK) + { + pKey = &(credentials->identity); + GetKeyStatus = SEC_E_UNSUPPORTED_FUNCTION; + + /* plaintext password */ + credentials->pGetKeyFn(credentials->pvGetKeyArgument, "NTLM", 0, &pKey, &GetKeyStatus); + + if (GetKeyStatus == SEC_E_OK) + { + int status; + + value = (BYTE*) pKey; + credentials->identity.Password = NULL; + + status = ConvertToUnicode(CP_UTF8, 0, (char*) value, -1, + (LPWSTR*) &credentials->identity.Password, 0); + + if (status <= 0) + return SEC_E_INTERNAL_ERROR; + + credentials->identity.PasswordLength = (ULONG) (status - 1); + } + } + + if (GetKeyStatus != SEC_E_OK) + { + pKey = &(credentials->identity); + GetKeyStatus = SEC_E_UNSUPPORTED_FUNCTION; + + /* NTLMv1 Hash */ + credentials->pGetKeyFn(credentials->pvGetKeyArgument, "NTLM", 1, &pKey, &GetKeyStatus); + + if (GetKeyStatus == SEC_E_OK) + { + value = (BYTE*) pKey; + CopyMemory(context->NtlmHash, value, 16); + } + } + + if (GetKeyStatus != SEC_E_OK) + { + pKey = &(credentials->identity); + GetKeyStatus = SEC_E_UNSUPPORTED_FUNCTION; + + /* NTLMv2 Hash */ + credentials->pGetKeyFn(credentials->pvGetKeyArgument, "NTLM", 2, &pKey, &GetKeyStatus); + + if (GetKeyStatus == SEC_E_OK) + { + value = (BYTE*) pKey; + CopyMemory(context->NtlmHash, value, 16); + } + } + + if (GetKeyStatus != SEC_E_OK) + { + /* no credentials on the server */ + return SEC_E_LOGON_DENIED; + } } if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */ @@ -961,6 +1032,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer UINT32 MicOffset = 0; UINT32 PayloadBufferOffset; NTLM_AUTHENTICATE_MESSAGE* message; + SSPI_CREDENTIALS* credentials = context->credentials; message = &context->AUTHENTICATE_MESSAGE; ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE)); @@ -1007,15 +1079,15 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer message->Workstation.Buffer = (BYTE*) context->Workstation.Buffer; } - if (context->identity.DomainLength > 0) + if (credentials->identity.DomainLength > 0) { message->NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; - message->DomainName.Len = (UINT16) context->identity.DomainLength * 2; - message->DomainName.Buffer = (BYTE*) context->identity.Domain; + message->DomainName.Len = (UINT16) credentials->identity.DomainLength * 2; + message->DomainName.Buffer = (BYTE*) credentials->identity.Domain; } - message->UserName.Len = (UINT16) context->identity.UserLength * 2; - message->UserName.Buffer = (BYTE*) context->identity.User; + message->UserName.Len = (UINT16) credentials->identity.UserLength * 2; + message->UserName.Buffer = (BYTE*) credentials->identity.User; message->LmChallengeResponse.Len = (UINT16) context->LmChallengeResponse.cbBuffer; message->LmChallengeResponse.Buffer = (BYTE*) context->LmChallengeResponse.pvBuffer; diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c b/winpr/libwinpr/sspi/Negotiate/negotiate.c index 72b1ca5fd..fa7e38e8d 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.c +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c @@ -68,7 +68,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCre { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -79,7 +79,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCre if (!context) return SEC_E_INTERNAL_ERROR; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); sspi_CopyAuthIdentity(&context->identity, &credentials->identity); sspi_SecureHandleSetLowerPointer(phNewContext, context); @@ -100,7 +100,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCre { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -111,7 +111,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCre if (!context) return SEC_E_INTERNAL_ERROR; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); sspi_CopyAuthIdentity(&context->identity, &credentials->identity); sspi_SecureHandleSetLowerPointer(phNewContext, context); @@ -131,7 +131,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredenti { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -142,7 +142,7 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredenti if (!context) return SEC_E_INTERNAL_ERROR; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); sspi_CopyAuthIdentity(&context->identity, &credentials->identity); sspi_SecureHandleSetLowerPointer(phNewContext, context); @@ -264,90 +264,68 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrin ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; - if (fCredentialUse == SECPKG_CRED_OUTBOUND) + if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INTERNAL_ERROR; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - - return SEC_E_OK; - } - else if (fCredentialUse == SECPKG_CRED_INBOUND) - { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INTERNAL_ERROR; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - - return SEC_E_OK; + return SEC_E_INVALID_PARAMETER; } - return SEC_E_UNSUPPORTED_FUNCTION; + credentials = sspi_CredentialsNew(); + + if (!credentials) + return SEC_E_INTERNAL_ERROR; + + credentials->fCredentialUse = fCredentialUse; + credentials->pGetKeyFn = pGetKeyFn; + credentials->pvGetKeyArgument = pvGetKeyArgument; + + identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; + + if (identity) + sspi_CopyAuthIdentity(&(credentials->identity), identity); + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); + + return SEC_E_OK; } SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; - if (fCredentialUse == SECPKG_CRED_OUTBOUND) + if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INTERNAL_ERROR; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - - return SEC_E_OK; - } - else if (fCredentialUse == SECPKG_CRED_INBOUND) - { - credentials = sspi_CredentialsNew(); - - if (!credentials) - return SEC_E_INTERNAL_ERROR; - - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - - if (identity) - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - - return SEC_E_OK; + return SEC_E_INVALID_PARAMETER; } - return SEC_E_UNSUPPORTED_FUNCTION; + credentials = sspi_CredentialsNew(); + + if (!credentials) + return SEC_E_INTERNAL_ERROR; + + credentials->fCredentialUse = fCredentialUse; + credentials->pGetKeyFn = pGetKeyFn; + credentials->pvGetKeyArgument = pvGetKeyArgument; + + identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; + + if (identity) + sspi_CopyAuthIdentity(&(credentials->identity), identity); + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); + + return SEC_E_OK; } SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) @@ -362,12 +340,12 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCr SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential) { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; if (!phCredential) return SEC_E_INVALID_HANDLE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); if (!credentials) return SEC_E_INVALID_HANDLE; diff --git a/winpr/libwinpr/sspi/sspi.h b/winpr/libwinpr/sspi/sspi.h index 60401c7f2..dd34aafaf 100644 --- a/winpr/libwinpr/sspi/sspi.h +++ b/winpr/libwinpr/sspi/sspi.h @@ -28,15 +28,18 @@ #define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64 -struct _CREDENTIALS +struct _SSPI_CREDENTIALS { DWORD flags; + ULONG fCredentialUse; + SEC_GET_KEY_FN pGetKeyFn; + void* pvGetKeyArgument; SEC_WINNT_AUTH_IDENTITY identity; }; -typedef struct _CREDENTIALS CREDENTIALS; +typedef struct _SSPI_CREDENTIALS SSPI_CREDENTIALS; -CREDENTIALS* sspi_CredentialsNew(void); -void sspi_CredentialsFree(CREDENTIALS* credentials); +SSPI_CREDENTIALS* sspi_CredentialsNew(void); +void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials); PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType); diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index ccafa9db3..493bc83c9 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -216,16 +216,16 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) return sspi_ContextBufferAlloc(allocatorIndex, size); } -CREDENTIALS* sspi_CredentialsNew() +SSPI_CREDENTIALS* sspi_CredentialsNew() { - CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials; - credentials = (CREDENTIALS*) calloc(1, sizeof(CREDENTIALS)); + credentials = (SSPI_CREDENTIALS*) calloc(1, sizeof(SSPI_CREDENTIALS)); return credentials; } -void sspi_CredentialsFree(CREDENTIALS* credentials) +void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) { if (!credentials) return; diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c index 19e8d3e87..1ab6936de 100644 --- a/winpr/libwinpr/sspi/test/TestNTLM.c +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -3,6 +3,17 @@ #include #include +#define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR + +static const char* TEST_NTLM_USER = "Username"; +static const char* TEST_NTLM_DOMAIN = "Domain"; +static const char* TEST_NTLM_PASSWORD = "P4ss123!"; + +static const char* TEST_NTLM_HASH_STRING = "d5922a65c4d5c082ca444af1be0001db"; + +static const BYTE TEST_NTLM_HASH[16] = + { 0xd5, 0x92, 0x2a, 0x65, 0xc4, 0xd5, 0xc0, 0x82, 0xca, 0x44, 0x4a, 0xf1, 0xbe, 0x00, 0x01, 0xdb }; + struct _TEST_NTLM_CLIENT { CtxtHandle context; @@ -33,7 +44,7 @@ int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* SecInvalidateHandle(&(ntlm->context)); - ntlm->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR); + ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE); sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); @@ -177,7 +188,7 @@ int test_ntlm_client_authenticate(TEST_NTLM_CLIENT* ntlm) 0, &ntlm->context, &ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration); - if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) + if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { if (ntlm->table->CompleteAuthToken) ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc); @@ -252,15 +263,97 @@ struct _TEST_NTLM_SERVER }; typedef struct _TEST_NTLM_SERVER TEST_NTLM_SERVER; -int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm, const char* user, const char* domain, const char* password) +void SEC_ENTRY test_ntlm_server_get_key(void* pArg, void* pPrincipal, ULONG KeyVer, void** ppKey, SECURITY_STATUS* pStatus) +{ + char* User = NULL; + char* Domain = NULL; + TEST_NTLM_SERVER* ntlm; + SEC_WINNT_AUTH_IDENTITY* identity; + SECURITY_STATUS status = SEC_E_NO_CREDENTIALS; + + if (!pPrincipal || !ppKey) + { + *pStatus = SEC_E_INVALID_PARAMETER; + return; + } + + ntlm = (TEST_NTLM_SERVER*) pArg; + identity = (SEC_WINNT_AUTH_IDENTITY*) *ppKey; + + if (!ntlm || !identity) + { + *pStatus = SEC_E_INVALID_PARAMETER; + return; + } + + if (strcmp((char*) pPrincipal, "NTLM") != 0) + { + *pStatus = SEC_E_UNSUPPORTED_FUNCTION; + return; + } + + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) identity->User, identity->UserLength, &User, 0, NULL, NULL); + + if (identity->Domain) + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) identity->Domain, identity->DomainLength, &Domain, 0, NULL, NULL); + + if (KeyVer == 0) /* plaintext password */ + { +#if 0 + char* password; + + if (strcmp(User, TEST_NTLM_USER) == 0) + { + password = _strdup(TEST_NTLM_PASSWORD); + *ppKey = (void*) password; + status = SEC_E_OK; + } +#endif + } + else if (KeyVer == 1) /* NTLMv1 Hash */ + { + BYTE* hash; + + status = SEC_E_NO_CREDENTIALS; + + hash = (BYTE*) calloc(1, 16); + + if (!hash) + { + *pStatus = SEC_E_INTERNAL_ERROR; + return; + } + + if (strcmp(User, TEST_NTLM_USER) == 0) + { + CopyMemory(hash, TEST_NTLM_HASH, 16); + *ppKey = (void*) hash; + status = SEC_E_OK; + } + } + else if (KeyVer == 2) /* NTLMv2 Hash */ + { + status = SEC_E_NO_CREDENTIALS; + } + else + { + /* unknown */ + status = SEC_E_UNSUPPORTED_FUNCTION; + } + + fprintf(stderr, "SecGetKey %s\\%s status: %s (0x%04X)\n", + Domain, User, GetSecurityStatusString(status), status); + + *pStatus = status; +} + +int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm) { SECURITY_STATUS status; SecInvalidateHandle(&(ntlm->context)); - ntlm->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR); - - sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); + ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE); status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); @@ -274,7 +367,9 @@ int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm, const char* user, const char* ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, - SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); + SECPKG_CRED_INBOUND, NULL, NULL, + test_ntlm_server_get_key, (void*) ntlm, + &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { @@ -387,10 +482,6 @@ void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm) free(ntlm); } -static const char* TEST_NTLM_USERNAME = "Username"; -static const char* TEST_NTLM_DOMAIN = "Domain"; -static const char* TEST_NTLM_PASSWORD = "P4ss123!"; - int TestNTLM(int argc, char* argv[]) { int status; @@ -404,7 +495,7 @@ int TestNTLM(int argc, char* argv[]) client = test_ntlm_client_new(); - status = test_ntlm_client_init(client, TEST_NTLM_USERNAME, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD); + status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD); if (status < 0) { @@ -418,7 +509,7 @@ int TestNTLM(int argc, char* argv[]) server = test_ntlm_server_new(); - status = test_ntlm_server_init(server, TEST_NTLM_USERNAME, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD); + status = test_ntlm_server_init(server); if (status < 0) {