libwinpr-sspi: add custom API for passing NTLM hashes and credentials dynamically
This commit is contained in:
parent
ac9b527991
commit
0ebc7e2ab4
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -3,6 +3,17 @@
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user