21#include <winpr/config.h>
24#include <winpr/wtypes.h>
25#include <winpr/assert.h>
26#include <winpr/sspi.h>
27#include <winpr/tchar.h>
28#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
29#include <winpr/registry.h>
31#include <winpr/build-config.h>
32#include <winpr/asn1.h>
33#include <winpr/path.h>
34#include <winpr/config-readers.h>
38#include "../NTLM/ntlm.h"
39#include "../NTLM/ntlm_export.h"
40#include "../Kerberos/kerberos.h"
42#include "../../utils.h"
44#define TAG WINPR_TAG("negotiate")
46#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
47#define NEGO_REG_KEY "Software\\%s\\SSPI\\Negotiate"
50static const char PACKAGE_NAME_DISABLE_ALL[] =
"none";
51static const char PACKAGE_NAME_NTLM[] =
"ntlm";
52static const char PACKAGE_NAME_KERBEROS[] =
"kerberos";
53static const char PACKAGE_NAME_KERBEROS_U2U[] =
"u2u";
83 "Microsoft Package Negotiator"
86static WCHAR NEGOTIATE_SecPkgInfoW_NameBuffer[32] = WINPR_C_ARRAY_INIT;
87static WCHAR NEGOTIATE_SecPkgInfoW_CommentBuffer[32] = WINPR_C_ARRAY_INIT;
94 NEGOTIATE_SecPkgInfoW_NameBuffer,
95 NEGOTIATE_SecPkgInfoW_CommentBuffer
98static const WinPrAsn1_OID spnego_OID = { 6, (BYTE*)
"\x2b\x06\x01\x05\x05\x02" };
100 (BYTE*)
"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03" };
101static const WinPrAsn1_OID kerberos_OID = { 9, (BYTE*)
"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
103 (BYTE*)
"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02" };
104static const WinPrAsn1_OID ntlm_OID = { 10, (BYTE*)
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
106static const WinPrAsn1_OID negoex_OID = { 10, (BYTE*)
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e" };
109static const SecPkg SecPkgTable[] = {
110 { KERBEROS_SSP_NAME, &KERBEROS_SecurityFunctionTableA, &KERBEROS_SecurityFunctionTableW },
111 { KERBEROS_SSP_NAME, &KERBEROS_SecurityFunctionTableA, &KERBEROS_SecurityFunctionTableW },
112 { NTLM_SSP_NAME, &NTLM_SecurityFunctionTableA, &NTLM_SecurityFunctionTableW }
115static const Mech MechTable[] = {
116 { &kerberos_u2u_OID, &SecPkgTable[0], ISC_REQ_INTEGRITY | ISC_REQ_USE_SESSION_KEY, TRUE },
117 { &kerberos_OID, &SecPkgTable[1], ISC_REQ_INTEGRITY, TRUE },
118 { &ntlm_OID, &SecPkgTable[2], 0, FALSE },
121static const SecPkg SecPkgTable[] = { { NTLM_SSP_NAME, &NTLM_SecurityFunctionTableA,
122 &NTLM_SecurityFunctionTableW } };
124static const Mech MechTable[] = {
125 { &ntlm_OID, &SecPkgTable[0], 0, FALSE },
129static const size_t MECH_COUNT = ARRAYSIZE(MechTable);
142 enum NegState negState;
150static const NegToken empty_neg_token = { NOSTATE, FALSE,
151 { 0,
nullptr }, { 0, 0,
nullptr },
152 { 0, 0,
nullptr }, { 0, 0,
nullptr } };
158 WINPR_ASSERT(init_context);
164 if (init_context->spnego)
166 init_context->mechTypes.pvBuffer = malloc(init_context->mechTypes.cbBuffer);
167 if (!init_context->mechTypes.pvBuffer)
174 *context = *init_context;
181 WINPR_ASSERT(context);
183 if (context->mechTypes.pvBuffer)
184 free(context->mechTypes.pvBuffer);
188static const char* negotiate_mech_name(
const WinPrAsn1_OID* oid)
190 if (sspi_gss_oid_compare(oid, &spnego_OID))
191 return "SPNEGO (1.3.6.1.5.5.2)";
192 else if (sspi_gss_oid_compare(oid, &kerberos_u2u_OID))
193 return "Kerberos user to user (1.2.840.113554.1.2.2.3)";
194 else if (sspi_gss_oid_compare(oid, &kerberos_OID))
195 return "Kerberos (1.2.840.113554.1.2.2)";
196 else if (sspi_gss_oid_compare(oid, &kerberos_wrong_OID))
197 return "Kerberos [wrong OID] (1.2.840.48018.1.2.2)";
198 else if (sspi_gss_oid_compare(oid, &ntlm_OID))
199 return "NTLM (1.3.6.1.4.1.311.2.2.10)";
200 else if (sspi_gss_oid_compare(oid, &negoex_OID))
201 return "NegoEx (1.3.6.1.4.1.311.2.2.30)";
203 return "Unknown mechanism";
206static const Mech* negotiate_GetMechByOID(
const WinPrAsn1_OID* oid)
212 if (sspi_gss_oid_compare(&testOid, &kerberos_wrong_OID))
214 testOid.len = kerberos_OID.len;
215 testOid.data = kerberos_OID.data;
218 for (
size_t i = 0; i < MECH_COUNT; i++)
220 if (sspi_gss_oid_compare(&testOid, MechTable[i].oid))
221 return &MechTable[i];
226static PSecHandle negotiate_FindCredential(MechCred* creds,
const Mech* mech)
233 for (
size_t i = 0; i < MECH_COUNT; i++)
235 MechCred* cred = &creds[i];
237 if (cred->mech == mech)
248#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
249static BOOL negotiate_get_dword(HKEY hKey,
const char* subkey, DWORD* pdwValue)
253 DWORD dwSize =
sizeof(dwValue);
254 LONG rc = RegQueryValueExA(hKey, subkey,
nullptr, &dwType, (BYTE*)&dwValue, &dwSize);
256 if (rc != ERROR_SUCCESS)
258 if (dwType != REG_DWORD)
266static BOOL negotiate_get_config_from_auth_package_list(
void* pAuthData, BOOL* kerberos, BOOL* ntlm,
270 char* tok_ctx =
nullptr;
271 char* PackageList =
nullptr;
276 char* tok_ptr = strtok_s(PackageList,
",", &tok_ctx);
280 const char* PackageName = tok_ptr;
281 BOOL PackageInclude = TRUE;
283 if (PackageName[0] ==
'!')
285 PackageName = &PackageName[1];
286 PackageInclude = FALSE;
289 if (_stricmp(PackageName, PACKAGE_NAME_NTLM) == 0)
291 *ntlm = PackageInclude;
293 else if (_stricmp(PackageName, PACKAGE_NAME_KERBEROS) == 0)
295 *kerberos = PackageInclude;
297 else if (_stricmp(PackageName, PACKAGE_NAME_KERBEROS_U2U) == 0)
299 *u2u = PackageInclude;
301 else if (_stricmp(PackageName, PACKAGE_NAME_DISABLE_ALL) == 0)
307 if (PackageName != PackageList)
309 WLog_WARN(TAG,
"Special keyword '%s' not first in list, aborting", PackageName);
315 WLog_WARN(TAG,
"Unknown authentication package name: %s, ignoring", PackageName);
318 tok_ptr = strtok_s(
nullptr,
",", &tok_ctx);
327static BOOL negotiate_get_config(
void* pAuthData, BOOL* kerberos, BOOL* ntlm, BOOL* u2u)
329 WINPR_ASSERT(kerberos);
333#if !defined(WITH_KRB5_NO_NTLM_FALLBACK)
338#if defined(WITH_KRB5)
346 if (negotiate_get_config_from_auth_package_list(pAuthData, kerberos, ntlm, u2u))
351 const char config[] =
"negotiate.json";
353#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
355 char* key = winpr_getApplicatonDetailsRegKey(NEGO_REG_KEY);
360 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
362 if (rc == ERROR_SUCCESS)
364 WLog_WARN(TAG,
"HKLM.reg is deprecated since 3.33.0. ATTENTION: Use %s instead!",
369 if (negotiate_get_dword(hKey, PACKAGE_NAME_KERBEROS, &dwValue))
370 *kerberos = (dwValue != 0);
372 if (negotiate_get_dword(hKey, PACKAGE_NAME_KERBEROS_U2U, &dwValue))
373 *u2u = (dwValue != 0);
375#if !defined(WITH_KRB5_NO_NTLM_FALLBACK)
376 if (negotiate_get_dword(hKey, PACKAGE_NAME_NTLM, &dwValue))
377 *ntlm = (dwValue != 0);
386 WINPR_JSON* json = winpr_GetJSONConfigFile(TRUE, config);
389 winpr_config_apply_bool(config, json, PACKAGE_NAME_KERBEROS, kerberos);
390 winpr_config_apply_bool(config, json, PACKAGE_NAME_KERBEROS_U2U, u2u);
391#if !defined(WITH_KRB5_NO_NTLM_FALLBACK)
392 winpr_config_apply_bool(config, json, PACKAGE_NAME_NTLM, ntlm);
400static BOOL negotiate_write_neg_token(
PSecBuffer output_buffer, NegToken* token)
402 WINPR_ASSERT(output_buffer);
406 WinPrAsn1Encoder* enc =
nullptr;
413 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
421 if (!WinPrAsn1EncAppContainer(enc, 0))
425 if (!WinPrAsn1EncOID(enc, &spnego_OID))
430 if (!WinPrAsn1EncContextualSeqContainer(enc, token->init ? 0 : 1))
433 WLog_DBG(TAG, token->init ?
"Writing negTokenInit..." :
"Writing negTokenResp...");
438 if (!WinPrAsn1EncContextualRawContent(enc, 0, &mechTypes))
440 WLog_DBG(TAG,
"\tmechTypes [0] (%" PRIu32
" bytes)", token->mechTypes.cbBuffer);
443 else if (token->negState != NOSTATE)
445 if (!WinPrAsn1EncContextualEnumerated(enc, 0, token->negState))
447 WLog_DBG(TAG,
"\tnegState [0] (%d)", token->negState);
451 if (token->supportedMech.len)
453 if (!WinPrAsn1EncContextualOID(enc, 1, &token->supportedMech))
455 WLog_DBG(TAG,
"\tsupportedMech [1] (%s)", negotiate_mech_name(&token->supportedMech));
459 if (token->mechToken.cbBuffer)
461 if (WinPrAsn1EncContextualOctetString(enc, 2, &mechToken) == 0)
463 WLog_DBG(TAG,
"\tmechToken [2] (%" PRIu32
" bytes)", token->mechToken.cbBuffer);
467 if (token->mic.cbBuffer)
469 if (WinPrAsn1EncContextualOctetString(enc, 3, &mechListMic) == 0)
471 WLog_DBG(TAG,
"\tmechListMIC [3] (%" PRIu32
" bytes)", token->mic.cbBuffer);
475 if (!WinPrAsn1EncEndContainer(enc))
481 if (!WinPrAsn1EncEndContainer(enc))
485 if (!WinPrAsn1EncStreamSize(enc, &len) || len > output_buffer->cbBuffer)
488 if (len > UINT32_MAX)
491 Stream_StaticInit(&s, output_buffer->pvBuffer, len);
493 if (WinPrAsn1EncToStream(enc, &s))
495 output_buffer->cbBuffer = (UINT32)len;
500 WinPrAsn1Encoder_Free(&enc);
504static BOOL negotiate_read_neg_token(
PSecBuffer input, NegToken* token)
509 WinPrAsn1_tagId contextual = 0;
510 WinPrAsn1_tag tag = 0;
518 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, input->pvBuffer, input->cbBuffer);
520 if (!WinPrAsn1DecPeekTag(&dec, &tag))
526 if (!WinPrAsn1DecReadApp(&dec, &tag, &dec2) || tag != 0)
531 if (!WinPrAsn1DecReadOID(&dec, &oid, FALSE))
534 if (!sspi_gss_oid_compare(&spnego_OID, &oid))
538 if (!WinPrAsn1DecReadContextualSequence(&dec, 0, &err, &dec2))
544 else if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &err, &dec2))
548 WLog_DBG(TAG, token->init ?
"Reading negTokenInit..." :
"Reading negTokenResp...");
553 if (!WinPrAsn1DecReadContextualTag(&dec, &contextual, &dec2))
562 wStream s = WinPrAsn1DecGetStream(&dec2);
563 token->mechTypes.BufferType = SECBUFFER_TOKEN;
564 const size_t mlen = Stream_Length(&s);
565 if (mlen > UINT32_MAX)
567 token->mechTypes.cbBuffer = (UINT32)mlen;
568 token->mechTypes.pvBuffer = Stream_Buffer(&s);
569 WLog_DBG(TAG,
"\tmechTypes [0] (%" PRIu32
" bytes)", token->mechTypes.cbBuffer);
574 WinPrAsn1_ENUMERATED rd = 0;
575 if (!WinPrAsn1DecReadEnumerated(&dec2, &rd))
580 case ACCEPT_COMPLETED:
581 case ACCEPT_INCOMPLETE:
586 WLog_ERR(TAG,
"Invalid negState enumeration value %d", rd);
590 token->negState = WINPR_ASSERTING_INT_CAST(
enum NegState, rd);
591 WLog_DBG(TAG,
"\tnegState [0] (%d)", rd);
598 if (!WinPrAsn1DecPeekTagAndLen(&dec2, &tag, &len) || (tag != ER_TAG_BIT_STRING))
600 WLog_DBG(TAG,
"\treqFlags [1] (%" PRIuz
" bytes)", len);
605 if (!WinPrAsn1DecReadOID(&dec2, &token->supportedMech, FALSE))
607 WLog_DBG(TAG,
"\tsupportedMech [1] (%s)",
608 negotiate_mech_name(&token->supportedMech));
613 if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
615 if (octet_string.len > UINT32_MAX)
617 token->mechToken.cbBuffer = (UINT32)octet_string.len;
618 token->mechToken.pvBuffer = octet_string.data;
619 token->mechToken.BufferType = SECBUFFER_TOKEN;
620 WLog_DBG(TAG,
"\tmechToken [2] (%" PRIuz
" bytes)", octet_string.len);
624 if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
626 if (octet_string.len > UINT32_MAX)
628 token->mic.cbBuffer = (UINT32)octet_string.len;
629 token->mic.pvBuffer = octet_string.data;
630 token->mic.BufferType = SECBUFFER_TOKEN;
631 WLog_DBG(TAG,
"\tmechListMIC [3] (%" PRIuz
" bytes)", octet_string.len);
634 WLog_ERR(TAG,
"unknown contextual item %d", contextual);
637 }
while (WinPrAsn1DecPeekTag(&dec, &tag));
642static SECURITY_STATUS negotiate_mic_exchange(
NEGOTIATE_CONTEXT* context, NegToken* input_token,
643 NegToken* output_token,
PSecBuffer output_buffer)
645 SecBuffer mic_buffers[2] = WINPR_C_ARRAY_INIT;
646 SecBufferDesc mic_buffer_desc = { SECBUFFER_VERSION, 2, mic_buffers };
647 SECURITY_STATUS status = 0;
649 WINPR_ASSERT(context);
650 WINPR_ASSERT(input_token);
651 WINPR_ASSERT(output_token);
652 WINPR_ASSERT(context->mech);
653 WINPR_ASSERT(context->mech->pkg);
658 mic_buffers[0] = context->mechTypes;
661 if (input_token->mic.cbBuffer > 0)
663 mic_buffers[1] = input_token->mic;
665 status = table->VerifySignature(&context->sub_context, &mic_buffer_desc, 0,
nullptr);
666 if (status != SEC_E_OK)
669 output_token->negState = ACCEPT_COMPLETED;
673 if (input_token->negState != ACCEPT_COMPLETED)
676 output_token->mic.BufferType = SECBUFFER_TOKEN;
679 output_token->mic.cbBuffer = output_buffer->cbBuffer - output_token->mechToken.cbBuffer;
680 output_token->mic.pvBuffer =
681 (BYTE*)output_buffer->pvBuffer + output_token->mechToken.cbBuffer;
683 mic_buffers[1] = output_token->mic;
685 status = table->MakeSignature(&context->sub_context, 0, &mic_buffer_desc, 0);
686 if (status != SEC_E_OK)
689 output_token->mic = mic_buffers[1];
693 const SSPI_PACKAGE_ID sub_id = sspi_SecureHandleGetPackageId(&context->sub_context);
695 return SEC_E_INTERNAL_ERROR;
697 if (sub_id == SSPI_PACKAGE_NTLM)
699 if (!ntlm_reset_cipher_state(&context->sub_context))
700 return SEC_E_INTERNAL_ERROR;
706static SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(
708 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
713 MechCred* creds =
nullptr;
716 NegToken input_token = empty_neg_token;
717 NegToken output_token = empty_neg_token;
721 SecBuffer mech_input_buffers[2] = WINPR_C_ARRAY_INIT;
722 SecBufferDesc mech_input = { SECBUFFER_VERSION, 2, mech_input_buffers };
723 SecBufferDesc mech_output = { SECBUFFER_VERSION, 1, &output_token.mechToken };
724 SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
725 SECURITY_STATUS sub_status = SEC_E_INTERNAL_ERROR;
726 WinPrAsn1Encoder* enc =
nullptr;
728 const Mech* mech =
nullptr;
730 if (!phCredential || !SecIsValidHandle(phCredential))
731 return SEC_E_NO_CREDENTIALS;
733 creds = sspi_SecureHandleGetLowerPointer(phCredential);
736 if (phContext && !phContext->dwLower && !phContext->dwUpper)
737 return SEC_E_INVALID_HANDLE;
739 context = sspi_SecureHandleGetLowerPointer(phContext);
743 input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
744 bindings_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_CHANNEL_BINDINGS);
747 output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
751 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
753 return SEC_E_INSUFFICIENT_MEMORY;
755 if (!WinPrAsn1EncSeqContainer(enc))
758 for (
size_t i = 0; i < MECH_COUNT; i++)
760 MechCred* cred = &creds[i];
761 const SecPkg* pkg = MechTable[i].pkg;
763 WINPR_ASSERT(pkg->table_w);
767 WLog_DBG(TAG,
"Unavailable mechanism: %s", negotiate_mech_name(cred->mech->oid));
772 if (!init_context.mech)
778 CopyMemory(&output_token.mechToken, output_buffer,
sizeof(
SecBuffer));
781 mech_input_buffers[0] = *bindings_buffer;
783 WINPR_ASSERT(pkg->table_w->InitializeSecurityContextW);
784 sub_status = pkg->table_w->InitializeSecurityContextW(
785 &cred->cred,
nullptr, pszTargetName, fContextReq | cred->mech->flags, Reserved1,
786 TargetDataRep, &mech_input, Reserved2, &init_context.sub_context, &mech_output,
787 pfContextAttr, ptsExpiry);
790 if (IsSecurityStatusError(sub_status))
792 if (SecIsValidHandle(&init_context.sub_context))
794 WINPR_ASSERT(pkg->table_w->DeleteSecurityContext);
795 pkg->table_w->DeleteSecurityContext(&init_context.sub_context);
801 init_context.mech = cred->mech;
804 if (!WinPrAsn1EncOID(enc, cred->mech->oid))
806 WLog_DBG(TAG,
"Available mechanism: %s", negotiate_mech_name(cred->mech->oid));
810 if (!init_context.mech)
814 if (init_context.mech->oid == &ntlm_OID)
816 init_context.spnego = FALSE;
817 output_buffer->cbBuffer = output_token.mechToken.cbBuffer;
818 WLog_DBG(TAG,
"Using direct NTLM");
822 init_context.spnego = TRUE;
823 init_context.mechTypes.BufferType = SECBUFFER_DATA;
824 const size_t cb = WinPrAsn1EncEndContainer(enc);
825 WINPR_ASSERT(cb <= UINT32_MAX);
826 init_context.mechTypes.cbBuffer = (UINT32)cb;
830 context = negotiate_ContextNew(&init_context);
833 init_context.mech->pkg->table->DeleteSecurityContext(&init_context.sub_context);
834 WinPrAsn1Encoder_Free(&enc);
835 return SEC_E_INSUFFICIENT_MEMORY;
838 sspi_SecureHandleSetPackageId(phNewContext, SSPI_PACKAGE_NEGOTIATE);
839 sspi_SecureHandleSetLowerPointer(phNewContext, context);
841 if (!context->spnego)
848 Stream_StaticInit(&s, context->mechTypes.pvBuffer, context->mechTypes.cbBuffer);
849 if (!WinPrAsn1EncToStream(enc, &s))
852 output_token.mechTypes.cbBuffer = context->mechTypes.cbBuffer;
853 output_token.mechTypes.pvBuffer = context->mechTypes.pvBuffer;
854 output_token.init = TRUE;
856 if (sub_status == SEC_E_OK)
857 context->state = NEGOTIATE_STATE_FINAL_OPTIMISTIC;
862 return SEC_E_INVALID_TOKEN;
864 sub_context = &context->sub_context;
865 sub_cred = negotiate_FindCredential(creds, context->mech);
867 if (!context->spnego)
869 return context->mech->pkg->table_w->InitializeSecurityContextW(
870 sub_cred, sub_context, pszTargetName, fContextReq | context->mech->flags, Reserved1,
871 TargetDataRep, pInput, Reserved2, sub_context, pOutput, pfContextAttr, ptsExpiry);
874 if (!negotiate_read_neg_token(input_buffer, &input_token))
875 return SEC_E_INVALID_TOKEN;
878 if (context->state < NEGOTIATE_STATE_NEGORESP && input_token.supportedMech.len &&
879 !sspi_gss_oid_compare(&input_token.supportedMech, context->mech->oid))
881 mech = negotiate_GetMechByOID(&input_token.supportedMech);
883 return SEC_E_INVALID_TOKEN;
886 sub_cred = negotiate_FindCredential(creds, mech);
888 return SEC_E_INVALID_TOKEN;
891 context->mech->pkg->table_w->DeleteSecurityContext(&context->sub_context);
892 sub_context =
nullptr;
894 context->mech = mech;
899 if (context->state < NEGOTIATE_STATE_NEGORESP)
901 switch (input_token.negState)
904 return SEC_E_INVALID_TOKEN;
906 return SEC_E_LOGON_DENIED;
911 case ACCEPT_INCOMPLETE:
912 context->state = NEGOTIATE_STATE_NEGORESP;
914 case ACCEPT_COMPLETED:
915 if (context->state == NEGOTIATE_STATE_INITIAL)
916 context->state = NEGOTIATE_STATE_NEGORESP;
918 context->state = NEGOTIATE_STATE_FINAL;
924 WLog_DBG(TAG,
"Negotiated mechanism: %s", negotiate_mech_name(context->mech->oid));
927 if (context->state == NEGOTIATE_STATE_NEGORESP)
932 CopyMemory(&output_token.mechToken, output_buffer,
sizeof(
SecBuffer));
934 mech_input_buffers[0] = input_token.mechToken;
936 mech_input_buffers[1] = *bindings_buffer;
938 status = context->mech->pkg->table_w->InitializeSecurityContextW(
939 sub_cred, sub_context, pszTargetName, fContextReq | context->mech->flags, Reserved1,
940 TargetDataRep, input_token.mechToken.cbBuffer ? &mech_input : nullptr, Reserved2,
941 &context->sub_context, &mech_output, pfContextAttr, ptsExpiry);
943 if (IsSecurityStatusError(status))
947 if (status == SEC_E_OK)
949 if (output_token.mechToken.cbBuffer > 0)
950 context->state = NEGOTIATE_STATE_MIC;
952 context->state = NEGOTIATE_STATE_FINAL;
956 if (context->state == NEGOTIATE_STATE_FINAL && input_token.mic.cbBuffer == 0)
958 if (context->mic || input_token.negState != ACCEPT_COMPLETED)
959 return SEC_E_INVALID_TOKEN;
962 output_buffer->cbBuffer = 0;
966 if ((context->state == NEGOTIATE_STATE_MIC && context->mic) ||
967 context->state == NEGOTIATE_STATE_FINAL)
969 status = negotiate_mic_exchange(context, &input_token, &output_token, output_buffer);
970 if (status != SEC_E_OK)
975 if (input_token.negState == ACCEPT_COMPLETED)
978 output_buffer->cbBuffer = 0;
982 if (output_token.negState == ACCEPT_COMPLETED)
985 status = SEC_I_CONTINUE_NEEDED;
987 if (!negotiate_write_neg_token(output_buffer, &output_token))
988 status = SEC_E_INTERNAL_ERROR;
991 WinPrAsn1Encoder_Free(&enc);
995static SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(
997 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
1000 SECURITY_STATUS status = 0;
1001 SEC_WCHAR* pszTargetNameW =
nullptr;
1005 pszTargetNameW = ConvertUtf8ToWCharAlloc(pszTargetName,
nullptr);
1006 if (!pszTargetNameW)
1007 return SEC_E_INTERNAL_ERROR;
1010 status = negotiate_InitializeSecurityContextW(
1011 phCredential, phContext, pszTargetNameW, fContextReq, Reserved1, TargetDataRep, pInput,
1012 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
1013 free(pszTargetNameW);
1022 WinPrAsn1_tagId tag = 0;
1023 const char ssp[] =
"NTLMSSP";
1025 if (!input_buffer || !input_buffer->pvBuffer || (input_buffer->cbBuffer == 0))
1031 if (input_buffer->cbBuffer >= 8 && strncmp(input_buffer->pvBuffer, ssp,
sizeof(ssp)) == 0)
1034 return negotiate_GetMechByOID(&ntlm_OID);
1038 WinPrAsn1Decoder_InitMem(&decoder, WINPR_ASN1_DER, input_buffer->pvBuffer,
1039 input_buffer->cbBuffer);
1041 if (!WinPrAsn1DecReadApp(&decoder, &tag, &appDecoder) || tag != 0)
1044 if (!WinPrAsn1DecReadOID(&appDecoder, oid, FALSE))
1047 if (sspi_gss_oid_compare(oid, &spnego_OID))
1053 return negotiate_GetMechByOID(oid);
1056static SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(
1063 MechCred* creds =
nullptr;
1065 NegToken input_token = empty_neg_token;
1066 NegToken output_token = empty_neg_token;
1069 SecBufferDesc mech_input = { SECBUFFER_VERSION, 1, &input_token.mechToken };
1070 SecBufferDesc mech_output = { SECBUFFER_VERSION, 1, &output_token.mechToken };
1071 SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
1074 WinPrAsn1_tagId tag = 0;
1076 const Mech* first_mech =
nullptr;
1078 if (!phCredential || !SecIsValidHandle(phCredential))
1079 return SEC_E_NO_CREDENTIALS;
1081 creds = sspi_SecureHandleGetLowerPointer(phCredential);
1084 return SEC_E_INVALID_TOKEN;
1087 if (phContext && !phContext->dwLower && !phContext->dwUpper)
1088 return SEC_E_INVALID_HANDLE;
1090 context = sspi_SecureHandleGetLowerPointer(phContext);
1092 input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
1094 output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
1098 init_context.mech = guessMech(input_buffer, &init_context.spnego, &oid);
1099 if (!init_context.mech && !init_context.spnego)
1100 return SEC_E_INVALID_TOKEN;
1102 WLog_DBG(TAG,
"Mechanism: %s", negotiate_mech_name(&oid));
1104 if (init_context.spnego)
1107 if (!negotiate_read_neg_token(input_buffer, &input_token))
1108 return SEC_E_INVALID_TOKEN;
1111 if (!input_token.init || input_token.mechTypes.cbBuffer == 0)
1112 return SEC_E_INVALID_TOKEN;
1114 init_context.mechTypes.BufferType = SECBUFFER_DATA;
1115 init_context.mechTypes.cbBuffer = input_token.mechTypes.cbBuffer;
1118 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, input_token.mechTypes.pvBuffer,
1119 input_token.mechTypes.cbBuffer);
1121 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1122 return SEC_E_INVALID_TOKEN;
1126 if (input_token.mechToken.cbBuffer)
1128 if (!WinPrAsn1DecReadOID(&dec, &oid, FALSE))
1129 return SEC_E_INVALID_TOKEN;
1131 init_context.mech = negotiate_GetMechByOID(&oid);
1133 if (init_context.mech)
1136 output_token.mechToken = *output_buffer;
1137 WLog_DBG(TAG,
"Requested mechanism: %s",
1138 negotiate_mech_name(init_context.mech->oid));
1143 if (init_context.mech)
1145 sub_cred = negotiate_FindCredential(creds, init_context.mech);
1149 status = init_context.mech->pkg->table->AcceptSecurityContext(
1150 sub_cred,
nullptr, init_context.spnego ? &mech_input : pInput, fContextReq,
1151 TargetDataRep, &init_context.sub_context,
1152 init_context.spnego ? &mech_output : pOutput, pfContextAttr, ptsTimeStamp);
1156 if (IsSecurityStatusError(status))
1158 if (!init_context.spnego)
1164 if (init_context.mech)
1165 init_context.mech->pkg->table->DeleteSecurityContext(&init_context.sub_context);
1167 init_context.mic = TRUE;
1168 first_mech = init_context.mech;
1169 init_context.mech =
nullptr;
1170 output_token.mechToken.cbBuffer = 0;
1173 while (!init_context.mech && WinPrAsn1DecPeekTag(&dec, &tag))
1176 if (!WinPrAsn1DecReadOID(&dec, &oid, FALSE))
1177 return SEC_E_INVALID_TOKEN;
1179 init_context.mech = negotiate_GetMechByOID(&oid);
1180 WLog_DBG(TAG,
"Requested mechanism: %s", negotiate_mech_name(&oid));
1183 if (init_context.mech == first_mech)
1184 init_context.mech =
nullptr;
1186 if (init_context.mech && !negotiate_FindCredential(creds, init_context.mech))
1187 init_context.mech =
nullptr;
1190 if (!init_context.mech)
1191 return SEC_E_INTERNAL_ERROR;
1193 context = negotiate_ContextNew(&init_context);
1196 if (!IsSecurityStatusError(status))
1197 init_context.mech->pkg->table->DeleteSecurityContext(&init_context.sub_context);
1198 return SEC_E_INSUFFICIENT_MEMORY;
1201 sspi_SecureHandleSetPackageId(phNewContext, SSPI_PACKAGE_NEGOTIATE);
1202 sspi_SecureHandleSetLowerPointer(phNewContext, context);
1204 if (!init_context.spnego)
1207 CopyMemory(init_context.mechTypes.pvBuffer, input_token.mechTypes.pvBuffer,
1208 input_token.mechTypes.cbBuffer);
1210 if (!context->mech->preferred)
1212 output_token.negState = REQUEST_MIC;
1213 context->mic = TRUE;
1217 output_token.negState = ACCEPT_INCOMPLETE;
1220 if (status == SEC_E_OK)
1221 context->state = NEGOTIATE_STATE_FINAL;
1223 context->state = NEGOTIATE_STATE_NEGORESP;
1225 output_token.supportedMech = oid;
1226 WLog_DBG(TAG,
"Accepted mechanism: %s", negotiate_mech_name(&output_token.supportedMech));
1230 sub_cred = negotiate_FindCredential(creds, context->mech);
1232 return SEC_E_NO_CREDENTIALS;
1234 if (!context->spnego)
1236 return context->mech->pkg->table->AcceptSecurityContext(
1237 sub_cred, &context->sub_context, pInput, fContextReq, TargetDataRep,
1238 &context->sub_context, pOutput, pfContextAttr, ptsTimeStamp);
1241 if (!negotiate_read_neg_token(input_buffer, &input_token))
1242 return SEC_E_INVALID_TOKEN;
1245 if (input_token.mechToken.cbBuffer > 0)
1247 if (context->state != NEGOTIATE_STATE_NEGORESP)
1248 return SEC_E_INVALID_TOKEN;
1252 CopyMemory(&output_token.mechToken, output_buffer,
sizeof(
SecBuffer));
1258 PCtxtHandle sub_context = sspi_SecureHandleGetLowerPointer(&context->sub_context)
1259 ? &context->sub_context
1261 status = context->mech->pkg->table->AcceptSecurityContext(
1262 sub_cred, sub_context, &mech_input, fContextReq | context->mech->flags,
1263 TargetDataRep, &context->sub_context, &mech_output, pfContextAttr, ptsTimeStamp);
1265 if (IsSecurityStatusError(status))
1268 if (status == SEC_E_OK)
1269 context->state = NEGOTIATE_STATE_FINAL;
1271 else if (context->state == NEGOTIATE_STATE_NEGORESP)
1272 return SEC_E_INVALID_TOKEN;
1275 if (context->state == NEGOTIATE_STATE_FINAL)
1278 if (context->mic && output_token.mechToken.cbBuffer == 0 && input_token.mic.cbBuffer == 0)
1279 return SEC_E_INVALID_TOKEN;
1281 if (context->mic || input_token.mic.cbBuffer > 0)
1283 status = negotiate_mic_exchange(context, &input_token, &output_token, output_buffer);
1284 if (status != SEC_E_OK)
1288 output_token.negState = ACCEPT_COMPLETED;
1291 if (input_token.negState == ACCEPT_COMPLETED)
1294 output_buffer->cbBuffer = 0;
1298 if (output_token.negState == ACCEPT_COMPLETED)
1301 status = SEC_I_CONTINUE_NEEDED;
1303 if (!negotiate_write_neg_token(output_buffer, &output_token))
1304 return SEC_E_INTERNAL_ERROR;
1309static SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(
PCtxtHandle phContext,
1313 SECURITY_STATUS status = SEC_E_OK;
1317 return SEC_E_INVALID_HANDLE;
1319 WINPR_ASSERT(context->mech);
1320 WINPR_ASSERT(context->mech->pkg);
1321 WINPR_ASSERT(context->mech->pkg->table);
1322 if (context->mech->pkg->table->CompleteAuthToken)
1323 status = context->mech->pkg->table->CompleteAuthToken(&context->sub_context, pToken);
1328static SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(
PCtxtHandle phContext)
1330 SECURITY_STATUS status = SEC_E_OK;
1332 sspi_SecureHandleInvalidate(phContext);
1333 const SecPkg* pkg =
nullptr;
1336 return SEC_E_INVALID_HANDLE;
1338 WINPR_ASSERT(context->mech);
1339 WINPR_ASSERT(context->mech->pkg);
1340 WINPR_ASSERT(context->mech->pkg->table);
1341 pkg = context->mech->pkg;
1343 if (pkg->table->DeleteSecurityContext)
1344 status = pkg->table->DeleteSecurityContext(&context->sub_context);
1346 negotiate_ContextFree(context);
1350static SECURITY_STATUS SEC_ENTRY
1351negotiate_ImpersonateSecurityContext(WINPR_ATTR_UNUSED
PCtxtHandle phContext)
1356static SECURITY_STATUS SEC_ENTRY
1357negotiate_RevertSecurityContext(WINPR_ATTR_UNUSED
PCtxtHandle phContext)
1362static SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(
PCtxtHandle phContext,
1363 ULONG ulAttribute,
void* pBuffer)
1368 return SEC_E_INVALID_HANDLE;
1370 WINPR_ASSERT(context->mech);
1371 WINPR_ASSERT(context->mech->pkg);
1372 WINPR_ASSERT(context->mech->pkg->table_w);
1373 if (context->mech->pkg->table_w->QueryContextAttributesW)
1374 return context->mech->pkg->table_w->QueryContextAttributesW(&context->sub_context,
1375 ulAttribute, pBuffer);
1377 return SEC_E_UNSUPPORTED_FUNCTION;
1380static SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(
PCtxtHandle phContext,
1381 ULONG ulAttribute,
void* pBuffer)
1386 return SEC_E_INVALID_HANDLE;
1388 WINPR_ASSERT(context->mech);
1389 WINPR_ASSERT(context->mech->pkg);
1390 WINPR_ASSERT(context->mech->pkg->table);
1391 if (context->mech->pkg->table->QueryContextAttributesA)
1392 return context->mech->pkg->table->QueryContextAttributesA(&context->sub_context,
1393 ulAttribute, pBuffer);
1395 return SEC_E_UNSUPPORTED_FUNCTION;
1398static SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(
PCtxtHandle phContext,
1399 ULONG ulAttribute,
void* pBuffer,
1405 return SEC_E_INVALID_HANDLE;
1407 WINPR_ASSERT(context->mech);
1408 WINPR_ASSERT(context->mech->pkg);
1409 WINPR_ASSERT(context->mech->pkg->table_w);
1410 if (context->mech->pkg->table_w->SetContextAttributesW)
1411 return context->mech->pkg->table_w->SetContextAttributesW(&context->sub_context,
1412 ulAttribute, pBuffer, cbBuffer);
1414 return SEC_E_UNSUPPORTED_FUNCTION;
1417static SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(
PCtxtHandle phContext,
1418 ULONG ulAttribute,
void* pBuffer,
1424 return SEC_E_INVALID_HANDLE;
1426 WINPR_ASSERT(context->mech);
1427 WINPR_ASSERT(context->mech->pkg);
1428 WINPR_ASSERT(context->mech->pkg->table);
1429 if (context->mech->pkg->table->SetContextAttributesA)
1430 return context->mech->pkg->table->SetContextAttributesA(&context->sub_context, ulAttribute,
1433 return SEC_E_UNSUPPORTED_FUNCTION;
1436static SECURITY_STATUS SEC_ENTRY negotiate_SetCredentialsAttributesW(
PCredHandle phCredential,
1438 void* pBuffer, ULONG cbBuffer)
1440 BOOL success = FALSE;
1441 MechCred* creds = sspi_SecureHandleGetLowerPointer(phCredential);
1444 return SEC_E_INVALID_HANDLE;
1446 for (
size_t i = 0; i < MECH_COUNT; i++)
1448 MechCred* cred = &creds[i];
1450 WINPR_ASSERT(cred->mech);
1451 WINPR_ASSERT(cred->mech->pkg);
1452 WINPR_ASSERT(cred->mech->pkg->table);
1453 WINPR_ASSERT(cred->mech->pkg->table_w->SetCredentialsAttributesW);
1454 const SECURITY_STATUS secStatus = cred->mech->pkg->table_w->SetCredentialsAttributesW(
1455 &cred->cred, ulAttribute, pBuffer, cbBuffer);
1457 if (secStatus == SEC_E_OK)
1460 WLog_WARN(TAG,
"SetCredentialsAttributesW returned %s",
1461 GetSecurityStatusString(secStatus));
1465 return (success ? SEC_E_OK : SEC_E_UNSUPPORTED_FUNCTION);
1468static SECURITY_STATUS SEC_ENTRY negotiate_SetCredentialsAttributesA(
PCredHandle phCredential,
1470 void* pBuffer, ULONG cbBuffer)
1472 BOOL success = FALSE;
1474 MechCred* creds = sspi_SecureHandleGetLowerPointer(phCredential);
1477 return SEC_E_INVALID_HANDLE;
1479 for (
size_t i = 0; i < MECH_COUNT; i++)
1481 MechCred* cred = &creds[i];
1486 WINPR_ASSERT(cred->mech);
1487 WINPR_ASSERT(cred->mech->pkg);
1488 WINPR_ASSERT(cred->mech->pkg->table);
1489 WINPR_ASSERT(cred->mech->pkg->table->SetCredentialsAttributesA);
1490 const SECURITY_STATUS secStatus = cred->mech->pkg->table->SetCredentialsAttributesA(
1491 &cred->cred, ulAttribute, pBuffer, cbBuffer);
1493 if (secStatus == SEC_E_OK)
1498 WLog_WARN(TAG,
"SetCredentialsAttributesA returned %s",
1499 GetSecurityStatusString(secStatus));
1503 return (success ? SEC_E_OK : SEC_E_UNSUPPORTED_FUNCTION);
1507static BOOL checkMechCredValid(
void* pAuthData, MechCred* cred)
1510 WINPR_ASSERT(cred->mech);
1511 WINPR_ASSERT(cred->mech->pkg);
1513 BOOL kerberos = FALSE;
1516 if (!negotiate_get_config(pAuthData, &kerberos, &ntlm, &u2u))
1518 WLog_DBG(TAG,
"Failed to get negotiate configuration");
1522 if (!kerberos && sspi_gss_oid_compare(cred->mech->oid, &kerberos_OID))
1524 WLog_DBG(TAG,
"Kerberos disabled, skipping");
1528 if (!u2u && sspi_gss_oid_compare(cred->mech->oid, &kerberos_u2u_OID))
1530 WLog_DBG(TAG,
"Kerberos U2U disabled, skipping");
1534 if (!ntlm && _tcsncmp(cred->mech->pkg->name, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0)
1536 WLog_DBG(TAG,
"NTLM disabled, skipping");
1542static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(
1543 SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse,
void* pvLogonID,
1544 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
1547 MechCred* creds = calloc(MECH_COUNT,
sizeof(MechCred));
1550 return SEC_E_INTERNAL_ERROR;
1552 for (
size_t i = 0; i < MECH_COUNT; i++)
1554 MechCred* cred = &creds[i];
1555 const SecPkg* pkg = MechTable[i].pkg;
1556 cred->mech = &MechTable[i];
1558 if (!checkMechCredValid(pAuthData, cred))
1561 WINPR_ASSERT(pkg->table_w);
1562 WINPR_ASSERT(pkg->table_w->AcquireCredentialsHandleW);
1563 const SECURITY_STATUS rc = pkg->table_w->AcquireCredentialsHandleW(
1564 pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn,
1565 pvGetKeyArgument, &cred->cred, ptsExpiry);
1568 WLog_DBG(TAG,
"AcquireCredentialsHandleW returned %s", GetSecurityStatusString(rc));
1575 sspi_SecureHandleSetLowerPointer(phCredential, (
void*)creds);
1576 sspi_SecureHandleSetPackageId(phCredential, SSPI_PACKAGE_NEGOTIATE);
1580static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(
1581 SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse,
void* pvLogonID,
1582 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
1585 MechCred* creds = calloc(MECH_COUNT,
sizeof(MechCred));
1588 return SEC_E_INTERNAL_ERROR;
1590 for (
size_t i = 0; i < MECH_COUNT; i++)
1592 const SecPkg* pkg = MechTable[i].pkg;
1593 MechCred* cred = &creds[i];
1595 cred->mech = &MechTable[i];
1597 if (!checkMechCredValid(pAuthData, cred))
1600 WINPR_ASSERT(pkg->table);
1601 WINPR_ASSERT(pkg->table->AcquireCredentialsHandleA);
1602 const SECURITY_STATUS rc = pkg->table->AcquireCredentialsHandleA(
1603 pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn,
1604 pvGetKeyArgument, &cred->cred, ptsExpiry);
1607 WLog_DBG(TAG,
"AcquireCredentialsHandleA returned %s", GetSecurityStatusString(rc));
1614 sspi_SecureHandleSetLowerPointer(phCredential, (
void*)creds);
1615 sspi_SecureHandleSetPackageId(phCredential, SSPI_PACKAGE_NEGOTIATE);
1619static SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(
1620 WINPR_ATTR_UNUSED
PCredHandle phCredential, WINPR_ATTR_UNUSED ULONG ulAttribute,
1621 WINPR_ATTR_UNUSED
void* pBuffer)
1623 WLog_ERR(TAG,
"TODO: Implement");
1624 return SEC_E_UNSUPPORTED_FUNCTION;
1627static SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(
1628 WINPR_ATTR_UNUSED
PCredHandle phCredential, WINPR_ATTR_UNUSED ULONG ulAttribute,
1629 WINPR_ATTR_UNUSED
void* pBuffer)
1631 WLog_ERR(TAG,
"TODO: Implement");
1632 return SEC_E_UNSUPPORTED_FUNCTION;
1635static SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(
PCredHandle phCredential)
1637 MechCred* creds = sspi_SecureHandleGetLowerPointer(phCredential);
1638 sspi_SecureHandleInvalidate(phCredential);
1640 return SEC_E_INVALID_HANDLE;
1642 for (
size_t i = 0; i < MECH_COUNT; i++)
1644 MechCred* cred = &creds[i];
1646 WINPR_ASSERT(cred->mech);
1647 WINPR_ASSERT(cred->mech->pkg);
1648 WINPR_ASSERT(cred->mech->pkg->table);
1649 WINPR_ASSERT(cred->mech->pkg->table->FreeCredentialsHandle);
1650 const SECURITY_STATUS rc = cred->mech->pkg->table->FreeCredentialsHandle(&cred->cred);
1652 WLog_DBG(TAG,
"FreeCredentialsHandle returned %s", GetSecurityStatusString(rc));
1659static SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(
PCtxtHandle phContext, ULONG fQOP,
1666 return SEC_E_INVALID_HANDLE;
1671 WINPR_ASSERT(context->mech);
1672 WINPR_ASSERT(context->mech->pkg);
1673 WINPR_ASSERT(context->mech->pkg->table);
1674 if (context->mech->pkg->table->EncryptMessage)
1675 return context->mech->pkg->table->EncryptMessage(&context->sub_context, fQOP, pMessage,
1678 return SEC_E_UNSUPPORTED_FUNCTION;
1681static SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(
PCtxtHandle phContext,
1683 ULONG MessageSeqNo, ULONG* pfQOP)
1688 return SEC_E_INVALID_HANDLE;
1693 WINPR_ASSERT(context->mech);
1694 WINPR_ASSERT(context->mech->pkg);
1695 WINPR_ASSERT(context->mech->pkg->table);
1696 if (context->mech->pkg->table->DecryptMessage)
1697 return context->mech->pkg->table->DecryptMessage(&context->sub_context, pMessage,
1698 MessageSeqNo, pfQOP);
1700 return SEC_E_UNSUPPORTED_FUNCTION;
1703static SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(
PCtxtHandle phContext, ULONG fQOP,
1710 return SEC_E_INVALID_HANDLE;
1715 WINPR_ASSERT(context->mech);
1716 WINPR_ASSERT(context->mech->pkg);
1717 WINPR_ASSERT(context->mech->pkg->table);
1718 if (context->mech->pkg->table->MakeSignature)
1719 return context->mech->pkg->table->MakeSignature(&context->sub_context, fQOP, pMessage,
1722 return SEC_E_UNSUPPORTED_FUNCTION;
1725static SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(
PCtxtHandle phContext,
1727 ULONG MessageSeqNo, ULONG* pfQOP)
1732 return SEC_E_INVALID_HANDLE;
1737 WINPR_ASSERT(context->mech);
1738 WINPR_ASSERT(context->mech->pkg);
1739 WINPR_ASSERT(context->mech->pkg->table);
1740 if (context->mech->pkg->table->VerifySignature)
1741 return context->mech->pkg->table->VerifySignature(&context->sub_context, pMessage,
1742 MessageSeqNo, pfQOP);
1744 return SEC_E_UNSUPPORTED_FUNCTION;
1750 negotiate_QueryCredentialsAttributesA,
1751 negotiate_AcquireCredentialsHandleA,
1752 negotiate_FreeCredentialsHandle,
1754 negotiate_InitializeSecurityContextA,
1755 negotiate_AcceptSecurityContext,
1756 negotiate_CompleteAuthToken,
1757 negotiate_DeleteSecurityContext,
1759 negotiate_QueryContextAttributesA,
1760 negotiate_ImpersonateSecurityContext,
1761 negotiate_RevertSecurityContext,
1762 negotiate_MakeSignature,
1763 negotiate_VerifySignature,
1773 negotiate_EncryptMessage,
1774 negotiate_DecryptMessage,
1775 negotiate_SetContextAttributesA,
1776 negotiate_SetCredentialsAttributesA,
1782 negotiate_QueryCredentialsAttributesW,
1783 negotiate_AcquireCredentialsHandleW,
1784 negotiate_FreeCredentialsHandle,
1786 negotiate_InitializeSecurityContextW,
1787 negotiate_AcceptSecurityContext,
1788 negotiate_CompleteAuthToken,
1789 negotiate_DeleteSecurityContext,
1791 negotiate_QueryContextAttributesW,
1792 negotiate_ImpersonateSecurityContext,
1793 negotiate_RevertSecurityContext,
1794 negotiate_MakeSignature,
1795 negotiate_VerifySignature,
1805 negotiate_EncryptMessage,
1806 negotiate_DecryptMessage,
1807 negotiate_SetContextAttributesW,
1808 negotiate_SetCredentialsAttributesW,
1811BOOL NEGOTIATE_init(
void)
1813 InitializeConstWCharFromUtf8(NEGOTIATE_SecPkgInfoA.Name, NEGOTIATE_SecPkgInfoW_NameBuffer,
1814 ARRAYSIZE(NEGOTIATE_SecPkgInfoW_NameBuffer));
1815 InitializeConstWCharFromUtf8(NEGOTIATE_SecPkgInfoA.Comment, NEGOTIATE_SecPkgInfoW_CommentBuffer,
1816 ARRAYSIZE(NEGOTIATE_SecPkgInfoW_CommentBuffer));
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.