22 #include <winpr/assert.h>
23 #include <winpr/wtypes.h>
25 #include <winpr/crt.h>
26 #include <winpr/wlog.h>
27 #include <winpr/print.h>
28 #include <winpr/asn1.h>
29 #include <winpr/sspi.h>
30 #include <winpr/collections.h>
32 #include <rdpear-common/ndr.h>
33 #include <rdpear-common/rdpear_common.h>
34 #include <rdpear-common/rdpear_asn1.h>
36 #include <freerdp/config.h>
37 #include <freerdp/freerdp.h>
38 #include <freerdp/addin.h>
39 #include <freerdp/client/channels.h>
40 #include <freerdp/channels/log.h>
41 #include <freerdp/channels/rdpear.h>
43 #define TAG CHANNELS_TAG("rdpear.client")
46 krb5_error_code encode_krb5_authenticator(
const krb5_authenticator* rep, krb5_data** code_out);
47 krb5_error_code encode_krb5_ap_rep(
const krb5_ap_rep* rep, krb5_data** code_out);
53 krb5_context krbContext;
56 static const BYTE payloadHeader[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
59 static krb5_error_code RPC_ENCRYPTION_KEY_to_keyblock(krb5_context ctx,
61 krb5_keyblock** pkeyblock)
65 WINPR_ASSERT(pkeyblock);
67 if (!key->reserved3.length)
68 return KRB5KDC_ERR_NULL_KEY;
71 krb5_init_keyblock(ctx, (krb5_enctype)key->reserved2, key->reserved3.length, pkeyblock);
75 krb5_keyblock* keyblock = *pkeyblock;
76 memcpy(keyblock->contents, key->reserved3.value, key->reserved3.length);
81 krb5_keyusage kusage, krb5_cksumtype cksumtype,
89 krb5_keyblock* keyblock = NULL;
90 krb5_data data = { 0 };
92 krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
96 data.data = (
char*)plain->Asn1Buffer;
97 data.length = plain->Asn1BufferHints.count;
99 rv = krb5_c_make_checksum(ctx, cksumtype, keyblock, kusage, &data, out);
101 krb5_free_keyblock(ctx, keyblock);
114 krb5_keyblock* keyblock = NULL;
115 krb5_data data = { 0 };
116 krb5_enc_data enc = { 0 };
119 krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
123 data.data = (
char*)plain->Asn1Buffer;
124 data.length = plain->Asn1BufferHints.count;
126 rv = krb5_c_encrypt_length(ctx, keyblock->enctype, data.length, &elen);
129 if (!elen || (elen > UINT32_MAX))
131 rv = KRB5_PARSE_MALFORMED;
134 enc.ciphertext.length = (
unsigned int)elen;
135 enc.ciphertext.data = malloc(elen);
136 if (!enc.ciphertext.data)
142 rv = krb5_c_encrypt(ctx, keyblock, kusage, NULL, &data, &enc);
144 out->data = enc.ciphertext.data;
145 out->length = enc.ciphertext.length;
147 krb5_free_keyblock(ctx, keyblock);
152 krb5_keyusage kusage,
const krb5_data* cipher,
157 WINPR_ASSERT(cipher);
158 WINPR_ASSERT(cipher->length);
161 krb5_keyblock* keyblock = NULL;
162 krb5_data data = { 0 };
163 krb5_enc_data enc = { 0 };
165 krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
169 enc.kvno = KRB5_PVNO;
170 enc.enctype = (krb5_enctype)key->reserved2;
171 enc.ciphertext.length = cipher->length;
172 enc.ciphertext.data = cipher->data;
174 data.length = cipher->length;
175 data.data = (
char*)malloc(cipher->length);
182 rv = krb5_c_decrypt(ctx, keyblock, kusage, NULL, &enc, &data);
184 plain->Asn1Buffer = (BYTE*)data.data;
185 plain->Asn1BufferHints.count = data.length;
187 krb5_free_keyblock(ctx, keyblock);
191 static BOOL rdpear_send_payload(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallback* pChannelCallback,
192 RdpEarPackageType packageType,
wStream* payload)
198 wStream* unencodedContent = rdpear_encodePayload(packageType, payload);
199 if (!unencodedContent)
202 const size_t unencodedLen = Stream_GetPosition(unencodedContent);
204 #if UINT32_MAX < SIZE_MAX
205 if (unencodedLen > UINT32_MAX)
209 SecBuffer inBuffer = { (ULONG)unencodedLen, SECBUFFER_DATA, Stream_Buffer(unencodedContent) };
211 if (!freerdp_nla_encrypt(rdpear->rdp_context, &inBuffer, &cryptedBuffer))
214 finalStream = Stream_New(NULL, 200);
217 Stream_Write_UINT32(finalStream, 0x4EACC3C8);
218 Stream_Write_UINT32(finalStream, cryptedBuffer.cbBuffer);
219 Stream_Write_UINT32(finalStream, 0x00000000);
220 Stream_Write_UINT32(finalStream, 0x00000000);
221 Stream_Write_UINT64(finalStream, 0);
224 if (!Stream_EnsureRemainingCapacity(finalStream, cryptedBuffer.cbBuffer))
227 Stream_Write(finalStream, cryptedBuffer.pvBuffer, cryptedBuffer.cbBuffer);
229 const size_t pos = Stream_GetPosition(finalStream);
230 #if UINT32_MAX < SIZE_MAX
231 if (pos > UINT32_MAX)
236 callback->channel->Write(callback->channel, (ULONG)pos, Stream_Buffer(finalStream), NULL);
237 ret = (status == CHANNEL_RC_OK);
239 WLog_DBG(TAG,
"rdpear_send_payload=0x%x", status);
241 sspi_SecBufferFree(&cryptedBuffer);
242 Stream_Free(unencodedContent, TRUE);
243 Stream_Free(finalStream, TRUE);
247 static BOOL rdpear_prepare_response(NdrContext* rcontext, UINT16 callId, UINT32 status,
248 NdrContext** pwcontext,
wStream* retStream)
250 WINPR_ASSERT(rcontext);
251 WINPR_ASSERT(pwcontext);
255 NdrContext* wcontext = ndr_context_copy(rcontext);
259 if (!Stream_EnsureRemainingCapacity(retStream,
sizeof(payloadHeader)))
262 Stream_Write(retStream, payloadHeader,
sizeof(payloadHeader));
264 if (!ndr_write_header(wcontext, retStream) || !ndr_start_constructed(wcontext, retStream) ||
265 !ndr_write_pickle(wcontext, retStream) ||
266 !ndr_write_uint16(wcontext, retStream, callId) ||
267 !ndr_write_uint16(wcontext, retStream, 0x0000) ||
268 !ndr_write_uint32(wcontext, retStream, status) ||
269 !ndr_write_uint16(wcontext, retStream, callId) ||
270 !ndr_write_uint16(wcontext, retStream, 0x0000))
273 *pwcontext = wcontext;
277 ndr_context_destroy(&wcontext);
281 static BOOL rdpear_kerb_version(NdrContext* rcontext,
wStream* s, UINT32* pstatus, UINT32* pversion)
283 *pstatus = ERROR_INVALID_DATA;
285 if (!ndr_read_uint32(rcontext, s, pversion))
288 WLog_DBG(TAG,
"-> KerbNegotiateVersion(v=0x%x)", *pversion);
294 static BOOL rdpear_kerb_ComputeTgsChecksum(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s,
298 krb5_checksum checksum = { 0 };
301 *pstatus = ERROR_INVALID_DATA;
302 WLog_DBG(TAG,
"-> ComputeTgsChecksum");
304 if (!ndr_read_ComputeTgsChecksumReq(rcontext, s, NULL, &req) ||
305 !ndr_treat_deferred_read(rcontext, s))
310 kerb_do_checksum(rdpear->krbContext, req.Key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
311 (krb5_cksumtype)req.ChecksumType, req.requestBody, &checksum);
315 asn1Payload = rdpear_enc_Checksum(req.ChecksumType, &checksum);
320 resp->Asn1Buffer = Stream_Buffer(asn1Payload);
321 const size_t pos = Stream_GetPosition(asn1Payload);
322 if (pos > UINT32_MAX)
324 resp->Asn1BufferHints.count = (UINT32)pos;
328 ndr_destroy_ComputeTgsChecksumReq(rcontext, NULL, &req);
329 krb5_free_checksum_contents(rdpear->krbContext, &checksum);
330 Stream_Free(asn1Payload, FALSE);
334 static BOOL rdpear_kerb_BuildEncryptedAuthData(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
338 krb5_data encrypted = { 0 };
340 krb5_error_code rv = 0;
342 *pstatus = ERROR_INVALID_DATA;
343 WLog_DBG(TAG,
"-> BuildEncryptedAuthData");
345 if (!ndr_read_BuildEncryptedAuthDataReq(rcontext, s, NULL, &req) ||
346 !ndr_treat_deferred_read(rcontext, s))
349 rv = kerb_do_encrypt(rdpear->krbContext, req.Key, (krb5_keyusage)req.KeyUsage,
350 req.PlainAuthData, &encrypted);
355 asn1Payload = rdpear_enc_EncryptedData(req.Key->reserved2, &encrypted);
362 asn1->Asn1Buffer = Stream_Buffer(asn1Payload);
363 const size_t pos = Stream_GetPosition(asn1Payload);
364 if (pos > UINT32_MAX)
366 asn1->Asn1BufferHints.count = (UINT32)pos;
370 krb5_free_data_contents(rdpear->krbContext, &encrypted);
371 ndr_destroy_BuildEncryptedAuthDataReq(rcontext, NULL, &req);
372 Stream_Free(asn1Payload, FALSE);
379 return ConvertWCharNToUtf8Alloc(src->Buffer, src->strLength, NULL);
382 static BOOL extractAuthData(
const KERB_ASN1_DATA* src, krb5_authdata* authData, BOOL* haveData)
387 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
389 WinPrAsn1_INTEGER adType = 0;
393 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
396 wStream subStream = WinPrAsn1DecGetStream(&dec2);
397 if (!Stream_GetRemainingLength(&subStream))
400 if (!WinPrAsn1DecReadSequence(&dec2, &dec3))
403 if (!WinPrAsn1DecReadContextualInteger(&dec3, 0, &error, &adType) ||
404 !WinPrAsn1DecReadContextualOctetString(&dec3, 1, &error, &os, FALSE))
407 if (os.len > UINT32_MAX)
410 authData->ad_type = adType;
411 authData->length = (
unsigned int)os.len;
412 authData->contents = os.data;
417 static BOOL extractChecksum(
const KERB_ASN1_DATA* src, krb5_checksum* dst)
421 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
425 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
428 WinPrAsn1_INTEGER cksumtype = 0;
429 if (!WinPrAsn1DecReadContextualInteger(&dec2, 0, &error, &cksumtype) ||
430 !WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &os, FALSE))
433 if (os.len > UINT32_MAX)
435 dst->checksum_type = cksumtype;
436 dst->length = (
unsigned int)os.len;
437 dst->contents = os.data;
441 #define FILETIME_TO_UNIX_OFFSET_S 11644473600LL
443 static LONGLONG krb5_time_to_FILETIME(
const krb5_timestamp* ts, krb5_int32 usec)
446 return (((*ts + FILETIME_TO_UNIX_OFFSET_S) * (1000LL * 1000LL) + usec) * 10LL);
449 static void krb5_free_principal_contents(krb5_context ctx, krb5_principal principal)
451 WINPR_ASSERT(principal);
452 krb5_free_data_contents(ctx, &principal->realm);
453 krb5_free_data(ctx, principal->data);
456 static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
460 krb5_error_code rv = 0;
461 wStream* asn1EncodedAuth = NULL;
463 krb5_data authenticator = { 0 };
464 krb5_data* der = NULL;
465 krb5_keyblock* subkey = NULL;
466 krb5_principal_data client = { 0 };
468 *pstatus = ERROR_INVALID_DATA;
469 WLog_DBG(TAG,
"-> CreateApReqAuthenticator");
471 if (!ndr_read_CreateApReqAuthenticatorReq(rcontext, s, NULL, &req) ||
472 !ndr_treat_deferred_read(rcontext, s))
475 krb5_authdata authdata = { 0 };
476 krb5_authdata* authDataPtr[2] = { &authdata, NULL };
479 if (!extractAuthData(req.AuthData, &authdata, &haveData))
481 WLog_ERR(TAG,
"error retrieving auth data");
482 winpr_HexDump(TAG, WLOG_DEBUG, req.AuthData->Asn1Buffer,
483 req.AuthData->Asn1BufferHints.count);
487 if (req.SkewTime->QuadPart)
489 WLog_ERR(TAG,
"!!!!! should handle SkewTime !!!!!");
494 rv = RPC_ENCRYPTION_KEY_to_keyblock(rdpear->krbContext, req.SubKey, &subkey);
497 WLog_ERR(TAG,
"error importing subkey");
502 krb5_authenticator authent = { .checksum = NULL,
504 .seq_number = req.SequenceNumber,
505 .authorization_data = haveData ? authDataPtr : NULL };
507 client.type = req.ClientName->NameType;
508 if (req.ClientName->nameHints.count > INT32_MAX)
511 client.length = (krb5_int32)req.ClientName->nameHints.count;
512 client.data = calloc(req.ClientName->nameHints.count,
sizeof(krb5_data));
516 for (
int i = 0; i < client.length; i++)
518 client.data[i].data = KERB_RPC_UNICODESTR_to_charptr(&req.ClientName->Names[i]);
519 if (!client.data[i].data)
521 client.data[i].length = (
unsigned int)strnlen(client.data[i].data, UINT32_MAX);
523 client.realm.data = KERB_RPC_UNICODESTR_to_charptr(req.ClientRealm);
524 if (!client.realm.data)
526 client.realm.length = (
unsigned int)strnlen(client.realm.data, UINT32_MAX);
527 authent.client = &client;
529 krb5_checksum checksum;
530 krb5_checksum* pchecksum = NULL;
533 if (!extractChecksum(req.GssChecksum, &checksum))
535 WLog_ERR(TAG,
"Error getting the checksum");
538 pchecksum = &checksum;
540 authent.checksum = pchecksum;
542 krb5_us_timeofday(rdpear->krbContext, &authent.ctime, &authent.cusec);
544 rv = encode_krb5_authenticator(&authent, &der);
547 WLog_ERR(TAG,
"error encoding authenticator");
552 .Asn1Buffer = (BYTE*)der->data,
553 .Asn1BufferHints = { .count = der->length } };
555 rv = kerb_do_encrypt(rdpear->krbContext, req.EncryptionKey, (krb5_keyusage)req.KeyUsage,
556 &plain_authent, &authenticator);
559 WLog_ERR(TAG,
"error encrypting authenticator");
563 asn1EncodedAuth = rdpear_enc_EncryptedData(req.EncryptionKey->reserved2, &authenticator);
564 if (!asn1EncodedAuth)
566 WLog_ERR(TAG,
"error encoding to ASN1");
575 const size_t size = Stream_GetPosition(asn1EncodedAuth);
576 if (size > UINT32_MAX)
578 resp->Authenticator.Asn1BufferHints.count = (UINT32)size;
579 resp->Authenticator.Asn1Buffer = Stream_Buffer(asn1EncodedAuth);
580 resp->AuthenticatorTime.QuadPart = krb5_time_to_FILETIME(&authent.ctime, authent.cusec);
584 resp->Authenticator.Pdu = 6;
585 resp->KerbProtocolError = rv;
586 krb5_free_principal_contents(rdpear->krbContext, &client);
587 krb5_free_data(rdpear->krbContext, der);
588 krb5_free_data_contents(rdpear->krbContext, &authenticator);
590 krb5_free_keyblock(rdpear->krbContext, subkey);
591 ndr_destroy_CreateApReqAuthenticatorReq(rcontext, NULL, &req);
592 Stream_Free(asn1EncodedAuth, FALSE);
596 static BOOL rdpear_findEncryptedData(
const KERB_ASN1_DATA* src,
int* penctype, krb5_data* data)
600 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
602 WinPrAsn1_INTEGER encType = 0;
605 if (!WinPrAsn1DecReadSequence(&dec, &dec2) ||
606 !WinPrAsn1DecReadContextualInteger(&dec2, 0, &error, &encType) ||
607 !WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &os, FALSE))
610 if (os.len > UINT32_MAX)
612 data->data = (
char*)os.data;
613 data->length = (
unsigned int)os.len;
618 static BOOL rdpear_kerb_UnpackKdcReplyBody(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s,
623 *pstatus = ERROR_INVALID_DATA;
625 if (!ndr_read_UnpackKdcReplyBodyReq(rcontext, s, NULL, &req) ||
626 !ndr_treat_deferred_read(rcontext, s))
629 if (req.StrengthenKey)
631 WLog_ERR(TAG,
"StrengthenKey not supported yet");
635 WLog_DBG(TAG,
"-> UnpackKdcReplyBody: KeyUsage=0x%x PDU=0x%x", req.KeyUsage, req.Pdu);
640 krb5_data asn1Data = { 0 };
642 if (!rdpear_findEncryptedData(req.EncryptedData, &encType, &asn1Data) || !asn1Data.length)
645 resp->KerbProtocolError = kerb_do_decrypt(
646 rdpear->krbContext, req.Key, (krb5_keyusage)req.KeyUsage, &asn1Data, &resp->ReplyBody);
647 resp->ReplyBody.Pdu = req.Pdu;
652 ndr_destroy_UnpackKdcReplyBodyReq(rcontext, NULL, &req);
656 static BOOL rdpear_kerb_DecryptApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s,
661 *pstatus = ERROR_INVALID_DATA;
662 if (!ndr_read_DecryptApReplyReq(rcontext, s, NULL, &req) ||
663 !ndr_treat_deferred_read(rcontext, s))
666 WLog_DBG(TAG,
"-> DecryptApReply");
670 krb5_data asn1Data = { 0 };
672 if (!rdpear_findEncryptedData(req.EncryptedReply, &encType, &asn1Data) || !asn1Data.length)
677 kerb_do_decrypt(rdpear->krbContext, req.Key, KRB5_KEYUSAGE_AP_REP_ENCPART, &asn1Data, resp);
680 WLog_ERR(TAG,
"error decrypting");
688 ndr_destroy_DecryptApReplyReq(rcontext, NULL, &req);
692 static BOOL rdpear_kerb_PackApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s,
696 krb5_data asn1Data = { 0 };
697 krb5_data* out = NULL;
699 WLog_DBG(TAG,
"-> PackApReply");
700 *pstatus = ERROR_INVALID_DATA;
701 if (!ndr_read_PackApReplyReq(rcontext, s, NULL, &req) || !ndr_treat_deferred_read(rcontext, s))
704 krb5_error_code rv = kerb_do_encrypt(rdpear->krbContext, req.SessionKey,
705 KRB5_KEYUSAGE_AP_REP_ENCPART, req.ReplyBody, &asn1Data);
710 reply.enc_part.kvno = KRB5_PVNO;
711 reply.enc_part.enctype = (krb5_enctype)req.SessionKey->reserved2;
712 reply.enc_part.ciphertext.length = asn1Data.length;
713 reply.enc_part.ciphertext.data = asn1Data.data;
715 rv = encode_krb5_ap_rep(&reply, &out);
719 resp->PackedReply = (BYTE*)out->data;
720 resp->PackedReplyHints.count = out->length;
724 krb5_free_data_contents(rdpear->krbContext, &asn1Data);
725 ndr_destroy_PackApReplyReq(rcontext, NULL, &req);
729 static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
730 IWTSVirtualChannelCallback* pChannelCallback,
wStream* s)
732 UINT ret = ERROR_INVALID_DATA;
733 NdrContext* context = NULL;
734 NdrContext* wcontext = NULL;
737 UINT32 uint32Resp = 0;
746 wStream* respStream = Stream_New(NULL, 500);
756 context = ndr_read_header(s);
757 if (!context || !ndr_read_constructed(context, s, &commandStream) ||
758 !ndr_read_pickle(context, &commandStream) ||
759 !ndr_read_uint16(context, &commandStream, &callId) ||
760 !ndr_read_uint16(context, &commandStream, &callId2) || (callId != callId2))
763 ret = CHANNEL_RC_NOT_OPEN;
766 case RemoteCallKerbNegotiateVersion:
768 respDescr = ndr_uint32_descr();
770 if (rdpear_kerb_version(context, &commandStream, &status, &uint32Resp))
773 case RemoteCallKerbCreateApReqAuthenticator:
774 resp = &createApReqAuthenticatorResp;
775 respDescr = ndr_CreateApReqAuthenticatorResp_descr();
777 if (rdpear_kerb_CreateApReqAuthenticator(rdpear, context, &commandStream, &status,
778 &createApReqAuthenticatorResp))
781 case RemoteCallKerbDecryptApReply:
783 respDescr = ndr_KERB_ASN1_DATA_descr();
785 if (rdpear_kerb_DecryptApReply(rdpear, context, &commandStream, &status, &asn1Data))
788 case RemoteCallKerbComputeTgsChecksum:
790 respDescr = ndr_KERB_ASN1_DATA_descr();
792 if (rdpear_kerb_ComputeTgsChecksum(rdpear, context, &commandStream, &status, &asn1Data))
795 case RemoteCallKerbBuildEncryptedAuthData:
797 respDescr = ndr_KERB_ASN1_DATA_descr();
799 if (rdpear_kerb_BuildEncryptedAuthData(rdpear, context, &commandStream, &status,
803 case RemoteCallKerbUnpackKdcReplyBody:
804 resp = &unpackKdcReplyBodyResp;
805 respDescr = ndr_UnpackKdcReplyBodyResp_descr();
807 if (rdpear_kerb_UnpackKdcReplyBody(rdpear, context, &commandStream, &status,
808 &unpackKdcReplyBodyResp))
811 case RemoteCallKerbPackApReply:
812 resp = &packApReplyResp;
813 respDescr = ndr_PackApReplyResp_descr();
815 if (rdpear_kerb_PackApReply(rdpear, context, &commandStream, &status, &packApReplyResp))
819 case RemoteCallNtlmNegotiateVersion:
820 WLog_ERR(TAG,
"don't wanna support NTLM");
824 WLog_DBG(TAG,
"Unhandled callId=0x%x", callId);
825 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(&commandStream, BYTE),
826 Stream_GetRemainingLength(&commandStream));
830 if (!rdpear_prepare_response(context, callId, status, &wcontext, respStream))
833 if (resp && respDescr)
835 WINPR_ASSERT(respDescr->writeFn);
837 BOOL r = respDescr->writeFn(wcontext, respStream, NULL, resp) &&
838 ndr_treat_deferred_write(wcontext, respStream);
840 if (respDescr->destroyFn)
841 respDescr->destroyFn(wcontext, NULL, resp);
845 WLog_DBG(TAG,
"!writeFn || !ndr_treat_deferred_write");
850 if (!ndr_end_constructed(wcontext, respStream) ||
851 !rdpear_send_payload(rdpear, pChannelCallback, RDPEAR_PACKAGE_KERBEROS, respStream))
853 WLog_DBG(TAG,
"rdpear_send_payload !!!!!!!!");
858 ndr_context_destroy(&context);
861 ndr_context_destroy(&wcontext);
864 Stream_Free(respStream, TRUE);
868 static UINT rdpear_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* s)
871 WINPR_ASSERT(callback);
872 UINT ret = ERROR_INVALID_DATA;
876 if (!Stream_CheckAndLogRequiredLength(TAG, s, 24))
877 return ERROR_INVALID_DATA;
879 UINT32 protocolMagic = 0;
882 Stream_Read_UINT32(s, protocolMagic);
883 if (protocolMagic != 0x4EACC3C8)
884 return ERROR_INVALID_DATA;
886 Stream_Read_UINT32(s, Length);
888 Stream_Read_UINT32(s, Version);
889 if (Version != 0x00000000)
890 return ERROR_INVALID_DATA;
895 if (!Stream_CheckAndLogRequiredLength(TAG, s, Length))
896 return ERROR_INVALID_DATA;
898 SecBuffer inBuffer = { Length, SECBUFFER_TOKEN, Stream_PointerAs(s,
void) };
901 RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)callback->plugin;
902 WINPR_ASSERT(rdpear);
903 if (!freerdp_nla_decrypt(rdpear->rdp_context, &inBuffer, &decrypted))
909 Stream_StaticInit(&decodedStream, decrypted.pvBuffer, decrypted.cbBuffer);
910 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, &decodedStream);
912 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
918 if (!WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &packageName, FALSE))
921 if (!WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &payload, FALSE))
925 Stream_StaticInit(&payloadStream, payload.data, payload.len);
927 ret = rdpear_decode_payload(rdpear, pChannelCallback, &payloadStream);
929 sspi_SecBufferFree(&decrypted);
938 static UINT rdpear_on_open(IWTSVirtualChannelCallback* pChannelCallback)
940 WINPR_UNUSED(pChannelCallback);
941 return CHANNEL_RC_OK;
949 static UINT rdpear_on_close(IWTSVirtualChannelCallback* pChannelCallback)
951 WINPR_UNUSED(pChannelCallback);
952 return CHANNEL_RC_OK;
959 RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)base;
960 krb5_free_context(rdpear->krbContext);
963 static UINT init_plugin_cb(
GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings)
966 WINPR_UNUSED(settings);
968 RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)base;
969 rdpear->rdp_context = rcontext;
970 if (krb5_init_context(&rdpear->krbContext))
971 return CHANNEL_RC_INITIALIZATION_ERROR;
972 return CHANNEL_RC_OK;
975 static const IWTSVirtualChannelCallback rdpear_callbacks = { rdpear_on_data_received,
976 rdpear_on_open, rdpear_on_close,
984 FREERDP_ENTRY_POINT(UINT rdpear_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
986 return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, RDPEAR_DVC_CHANNEL_NAME,
988 &rdpear_callbacks, init_plugin_cb, terminate_plugin_cb);
2.2.2.1.8 BuildEncryptedAuthData
2.2.2.1.7 ComputeTgsChecksum
2.2.2.1.4 CreateApReqAuthenticator
2.2.2.1.4 CreateApReqAuthenticator
2.2.1.2.8 KERB_RPC_ENCRYPTION_KEY
2.3.10 RPC_UNICODE_STRING (MS-DTYP)
2.2.2.1.6 UnpackKdcReplyBody
2.2.2.1.6 UnpackKdcReplyBody