libwinpr-sspi: add support for querying user+domain and setting NTLM hash

This commit is contained in:
Marc-André Moreau 2014-06-10 16:38:16 -04:00
parent 723e9a171b
commit 1b93dca6c0
9 changed files with 337 additions and 310 deletions

View File

@ -994,6 +994,29 @@ extern "C" {
/* Custom API */
#define SECPKG_ATTR_AUTH_IDENTITY 1001
#define SECPKG_ATTR_AUTH_PASSWORD 1002
#define SECPKG_ATTR_AUTH_NTLM_HASH 1003
struct _SecPkgContext_AuthIdentity
{
char User[256 + 1];
char Domain[256 + 1];
};
typedef struct _SecPkgContext_AuthIdentity SecPkgContext_AuthIdentity;
struct _SecPkgContext_AuthPassword
{
char Password[256 + 1];
};
typedef struct _SecPkgContext_AuthPassword SecPkgContext_AuthPassword;
struct _SecPkgContext_AuthNtlmHash
{
BYTE NtlmHash[16];
};
typedef struct _SecPkgContext_AuthNtlmHash SecPkgContext_AuthNtlmHash;
#define SSPI_INTERFACE_WINPR 0x00000001
#define SSPI_INTERFACE_NATIVE 0x00000002

View File

@ -363,8 +363,10 @@ int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int
status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar,
*lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
if (status != cbMultiByte)
if ((status != cbMultiByte) && allocate)
{
status = 0;
}
if ((status <= 0) && allocate)
{

View File

@ -609,7 +609,20 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
{
return SEC_E_OK;
NTLM_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->server)
{
status = ntlm_server_AuthenticateComplete(context);
}
return status;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */
@ -632,12 +645,16 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_SIZES)
{
SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
@ -649,6 +666,35 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
return SEC_E_OK;
}
else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
{
int status;
char* UserA = NULL;
char* DomainA = NULL;
SSPI_CREDENTIALS* credentials;
SecPkgContext_AuthIdentity* AuthIdentity = (SecPkgContext_AuthIdentity*) pBuffer;
credentials = context->credentials;
ZeroMemory(AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
UserA = AuthIdentity->User;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.User,
credentials->identity.UserLength,
&UserA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
DomainA = AuthIdentity->Domain;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.Domain,
credentials->identity.DomainLength,
&DomainA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
@ -658,6 +704,38 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, UL
return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INVALID_PARAMETER;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH)
{
SecPkgContext_AuthNtlmHash* AuthNtlmHash = (SecPkgContext_AuthNtlmHash*) pBuffer;
if (cbBuffer < sizeof(SecPkgContext_AuthNtlmHash))
return SEC_E_INVALID_PARAMETER;
CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
{
return SEC_E_OK;
@ -883,7 +961,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
@ -915,7 +993,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecPkgInfoA NTLM_SecPkgInfoA =

View File

@ -80,6 +80,7 @@ enum _NTLM_STATE
NTLM_STATE_NEGOTIATE,
NTLM_STATE_CHALLENGE,
NTLM_STATE_AUTHENTICATE,
NTLM_STATE_COMPLETION,
NTLM_STATE_FINAL
};
typedef enum _NTLM_STATE NTLM_STATE;
@ -262,6 +263,7 @@ struct _NTLM_CONTEXT
SecBuffer TargetName;
SecBuffer NtChallengeResponse;
SecBuffer LmChallengeResponse;
NTLMv2_RESPONSE NTLMv2Response;
BYTE Timestamp[8];
BYTE ChallengeTimestamp[8];
BYTE ServerChallenge[8];
@ -276,6 +278,7 @@ struct _NTLM_CONTEXT
BYTE ServerSigningKey[16];
BYTE ServerSealingKey[16];
BYTE MessageIntegrityCheck[16];
UINT32 MessageIntegrityCheckOffset;
};
typedef struct _NTLM_CONTEXT NTLM_CONTEXT;

View File

@ -671,20 +671,16 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
wStream* s;
int length;
UINT32 flags;
UINT32 MicOffset;
NTLM_AV_PAIR* AvFlags;
NTLMv2_RESPONSE response;
UINT32 PayloadBufferOffset;
NTLM_AUTHENTICATE_MESSAGE* message;
SSPI_CREDENTIALS* credentials = context->credentials;
flags = 0;
MicOffset = 0;
AvFlags = NULL;
message = &context->AUTHENTICATE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
ZeroMemory(&response, sizeof(NTLMv2_RESPONSE));
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
@ -759,7 +755,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (!snt)
return SEC_E_INTERNAL_ERROR;
if (ntlm_read_ntlm_v2_response(snt, &response) < 0)
if (ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)) < 0)
return SEC_E_INVALID_TOKEN;
Stream_Free(snt, FALSE);
@ -768,12 +764,12 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
sspi_SecBufferFree(&(context->ChallengeTargetInfo));
context->ChallengeTargetInfo.pvBuffer = (void*) response.Challenge.AvPairs;
context->ChallengeTargetInfo.pvBuffer = (void*) context->NTLMv2Response.Challenge.AvPairs;
context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8);
CopyMemory(context->ClientChallenge, context->NTLMv2Response.Challenge.ClientChallenge, 8);
AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags);
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs, MsvAvFlags);
if (AvFlags)
flags = *((UINT32*) ntlm_av_pair_get_value_pointer(AvFlags));
@ -796,7 +792,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
MicOffset = Stream_GetPosition(s);
context->MessageIntegrityCheckOffset = (UINT32) Stream_GetPosition(s);
if (Stream_GetRemainingLength(s) < 16)
return SEC_E_INVALID_TOKEN;
@ -851,178 +847,11 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
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 */
return SEC_E_INTERNAL_ERROR;
if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* KeyExchangeKey */
ntlm_generate_key_exchange_key(context);
/* EncryptedRandomSessionKey */
ntlm_decrypt_random_session_key(context);
/* ExportedSessionKey */
ntlm_generate_exported_session_key(context);
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
ZeroMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], 16);
ntlm_compute_message_integrity_check(context);
CopyMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], message->MessageIntegrityCheck, 16);
if (memcmp(context->MessageIntegrityCheck, message->MessageIntegrityCheck, 16) != 0)
{
fprintf(stderr, "Message Integrity Check (MIC) verification failed!\n");
fprintf(stderr, "Expected MIC:\n");
winpr_HexDump(context->MessageIntegrityCheck, 16);
fprintf(stderr, "Actual MIC:\n");
winpr_HexDump(message->MessageIntegrityCheck, 16);
Stream_Free(s, FALSE);
return SEC_E_MESSAGE_ALTERED;
}
}
/* Generate signing keys */
ntlm_generate_client_signing_key(context);
ntlm_generate_server_signing_key(context);
/* Generate sealing keys */
ntlm_generate_client_sealing_key(context);
ntlm_generate_server_sealing_key(context);
/* Initialize RC4 seal state */
ntlm_init_rc4_seal_states(context);
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "ClientChallenge\n");
winpr_HexDump(context->ClientChallenge, 8);
fprintf(stderr, "\n");
fprintf(stderr, "ServerChallenge\n");
winpr_HexDump(context->ServerChallenge, 8);
fprintf(stderr, "\n");
fprintf(stderr, "SessionBaseKey\n");
winpr_HexDump(context->SessionBaseKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "KeyExchangeKey\n");
winpr_HexDump(context->KeyExchangeKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ExportedSessionKey\n");
winpr_HexDump(context->ExportedSessionKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "RandomSessionKey\n");
winpr_HexDump(context->RandomSessionKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ClientSigningKey\n");
winpr_HexDump(context->ClientSigningKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ClientSealingKey\n");
winpr_HexDump(context->ClientSealingKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ServerSigningKey\n");
winpr_HexDump(context->ServerSigningKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ServerSealingKey\n");
winpr_HexDump(context->ServerSealingKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "Timestamp\n");
winpr_HexDump(context->Timestamp, 8);
fprintf(stderr, "\n");
#endif
context->state = NTLM_STATE_FINAL;
Stream_Free(s, FALSE);
ntlm_free_message_fields_buffer(&(message->DomainName));
ntlm_free_message_fields_buffer(&(message->UserName));
ntlm_free_message_fields_buffer(&(message->Workstation));
ntlm_free_message_fields_buffer(&(message->LmChallengeResponse));
ntlm_free_message_fields_buffer(&(message->NtChallengeResponse));
ntlm_free_message_fields_buffer(&(message->EncryptedRandomSessionKey));
/* Computations beyond this point require the NTLM hash of the password */
context->state = NTLM_STATE_COMPLETION;
return SEC_I_COMPLETE_NEEDED;
}
@ -1038,7 +867,6 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
{
wStream* s;
int length;
UINT32 MicOffset = 0;
UINT32 PayloadBufferOffset;
NTLM_AUTHENTICATE_MESSAGE* message;
SSPI_CREDENTIALS* credentials = context->credentials;
@ -1148,7 +976,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (context->UseMIC)
{
MicOffset = Stream_GetPosition(s);
context->MessageIntegrityCheckOffset = (UINT32) Stream_GetPosition(s);
Stream_Zero(s, 16); /* Message Integrity Check (16 bytes) */
}
@ -1180,7 +1008,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
/* Message Integrity Check */
ntlm_compute_message_integrity_check(context);
Stream_SetPosition(s, MicOffset);
Stream_SetPosition(s, context->MessageIntegrityCheckOffset);
Stream_Write(s, context->MessageIntegrityCheck, 16);
Stream_SetPosition(s, length);
}
@ -1222,3 +1050,125 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
return SEC_I_COMPLETE_NEEDED;
}
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context)
{
UINT32 flags = 0;
NTLM_AV_PAIR* AvFlags = NULL;
NTLM_AUTHENTICATE_MESSAGE* message;
if (context->state != NTLM_STATE_COMPLETION)
return SEC_E_OUT_OF_SEQUENCE;
message = &context->AUTHENTICATE_MESSAGE;
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs, MsvAvFlags);
if (AvFlags)
flags = *((UINT32*) ntlm_av_pair_get_value_pointer(AvFlags));
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
return SEC_E_INTERNAL_ERROR;
if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* KeyExchangeKey */
ntlm_generate_key_exchange_key(context);
/* EncryptedRandomSessionKey */
ntlm_decrypt_random_session_key(context);
/* ExportedSessionKey */
ntlm_generate_exported_session_key(context);
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
ZeroMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[context->MessageIntegrityCheckOffset], 16);
ntlm_compute_message_integrity_check(context);
CopyMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[context->MessageIntegrityCheckOffset],
message->MessageIntegrityCheck, 16);
if (memcmp(context->MessageIntegrityCheck, message->MessageIntegrityCheck, 16) != 0)
{
fprintf(stderr, "Message Integrity Check (MIC) verification failed!\n");
fprintf(stderr, "Expected MIC:\n");
winpr_HexDump(context->MessageIntegrityCheck, 16);
fprintf(stderr, "Actual MIC:\n");
winpr_HexDump(message->MessageIntegrityCheck, 16);
return SEC_E_MESSAGE_ALTERED;
}
}
/* Generate signing keys */
ntlm_generate_client_signing_key(context);
ntlm_generate_server_signing_key(context);
/* Generate sealing keys */
ntlm_generate_client_sealing_key(context);
ntlm_generate_server_sealing_key(context);
/* Initialize RC4 seal state */
ntlm_init_rc4_seal_states(context);
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "ClientChallenge\n");
winpr_HexDump(context->ClientChallenge, 8);
fprintf(stderr, "\n");
fprintf(stderr, "ServerChallenge\n");
winpr_HexDump(context->ServerChallenge, 8);
fprintf(stderr, "\n");
fprintf(stderr, "SessionBaseKey\n");
winpr_HexDump(context->SessionBaseKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "KeyExchangeKey\n");
winpr_HexDump(context->KeyExchangeKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ExportedSessionKey\n");
winpr_HexDump(context->ExportedSessionKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "RandomSessionKey\n");
winpr_HexDump(context->RandomSessionKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ClientSigningKey\n");
winpr_HexDump(context->ClientSigningKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ClientSealingKey\n");
winpr_HexDump(context->ClientSealingKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ServerSigningKey\n");
winpr_HexDump(context->ServerSigningKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "ServerSealingKey\n");
winpr_HexDump(context->ServerSealingKey, 16);
fprintf(stderr, "\n");
fprintf(stderr, "Timestamp\n");
winpr_HexDump(context->Timestamp, 8);
fprintf(stderr, "\n");
#endif
context->state = NTLM_STATE_FINAL;
ntlm_free_message_fields_buffer(&(message->DomainName));
ntlm_free_message_fields_buffer(&(message->UserName));
ntlm_free_message_fields_buffer(&(message->Workstation));
ntlm_free_message_fields_buffer(&(message->LmChallengeResponse));
ntlm_free_message_fields_buffer(&(message->NtChallengeResponse));
ntlm_free_message_fields_buffer(&(message->EncryptedRandomSessionKey));
return SEC_E_OK;
}

View File

@ -29,4 +29,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_MESSAGE_H */

View File

@ -178,25 +178,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext)
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiW->QueryContextAttributesW)
status = context->sspiW->QueryContextAttributesW(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
@ -229,6 +210,25 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext)
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiW->QueryContextAttributesW)
status = context->sspiW->QueryContextAttributesW(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
@ -248,6 +248,44 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContex
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiW->SetContextAttributesW)
status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiA->SetContextAttributesA)
status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
@ -424,7 +462,7 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
@ -456,7 +494,7 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesW, /* SetContextAttributes */
};
const SecPkgInfoA NEGOTIATE_SecPkgInfoA =

View File

@ -262,93 +262,6 @@ struct _TEST_NTLM_SERVER
};
typedef struct _TEST_NTLM_SERVER TEST_NTLM_SERVER;
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);
free(User);
free(Domain);
*pStatus = status;
}
int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
{
SECURITY_STATUS status;
@ -369,8 +282,7 @@ int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_INBOUND, NULL, NULL,
test_ntlm_server_get_key, (void*) ntlm,
SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL,
&ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
@ -446,8 +358,27 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm)
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
SecPkgContext_AuthIdentity AuthIdentity;
SecPkgContext_AuthNtlmHash AuthNtlmHash;
ZeroMemory(&AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
ZeroMemory(&AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_IDENTITY, &AuthIdentity);
if (status == SEC_E_OK)
{
if (strcmp(AuthIdentity.User, TEST_NTLM_USER) == 0)
{
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_HASH, 16);
status = ntlm->table->SetContextAttributes(&ntlm->context,
SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
}
}
if (ntlm->table->CompleteAuthToken)
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
status = ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;

View File

@ -273,7 +273,7 @@ int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("EncryptMessage status: 0x%08X\n", status);
printf("EncryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers,
printf("EncryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -342,7 +342,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("DecryptMessage status: 0x%08X\n", status);
printf("DecryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers,
printf("DecryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -351,7 +351,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
if (status != SEC_E_OK)
return -1;
printf("Decrypted Message (%ld)\n", Message.pBuffers[1].cbBuffer);
printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0)
@ -522,9 +522,9 @@ static void* schannel_test_server_thread(void* arg)
else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Server cBuffers: %lu pBuffers[0]: %lu type: %lu\n",
printf("Server cBuffers: %u pBuffers[0]: %u type: %u\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Server Input cBuffers: %ld pBuffers[0]: %lu type: %lu pBuffers[1]: %lu type: %lu\n", SecBufferDesc_in.cBuffers,
printf("Server Input cBuffers: %d pBuffers[0]: %u type: %u pBuffers[1]: %u type: %u\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -543,7 +543,7 @@ static void* schannel_test_server_thread(void* arg)
if (pSecBuffer->cbBuffer > 0)
{
printf("Server > Client (%ld)\n", pSecBuffer->cbBuffer);
printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
@ -713,7 +713,7 @@ int TestSchannel(int argc, char* argv[])
* 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
*/
printf("SupportedAlgs: %ld\n", SupportedAlgs.cSupportedAlgs);
printf("SupportedAlgs: %d\n", SupportedAlgs.cSupportedAlgs);
for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
{
@ -734,7 +734,7 @@ int TestSchannel(int argc, char* argv[])
/* CipherStrengths: Minimum: 40 Maximum: 256 */
printf("CipherStrengths: Minimum: %ld Maximum: %ld\n",
printf("CipherStrengths: Minimum: %d Maximum: %d\n",
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
@ -748,7 +748,7 @@ int TestSchannel(int argc, char* argv[])
/* SupportedProtocols: 0x208A0 */
printf("SupportedProtocols: 0x%04lX\n", SupportedProtocols.grbitProtocol);
printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol);
fContextReq = ISC_REQ_STREAM |
ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
@ -781,7 +781,7 @@ int TestSchannel(int argc, char* argv[])
}
g_ClientWait = TRUE;
printf("NumberOfBytesRead: %ld\n", NumberOfBytesRead);
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn;
@ -821,9 +821,9 @@ int TestSchannel(int argc, char* argv[])
else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Client Output cBuffers: %ld pBuffers[0]: %ld type: %ld\n",
printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Client Input cBuffers: %ld pBuffers[0]: %ld type: %ld pBuffers[1]: %ld type: %ld\n", SecBufferDesc_in.cBuffers,
printf("Client Input cBuffers: %d pBuffers[0]: %d type: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -833,7 +833,7 @@ int TestSchannel(int argc, char* argv[])
if (pSecBuffer->cbBuffer > 0)
{
printf("Client > Server (%ld)\n", pSecBuffer->cbBuffer);
printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))