19#include <rdpear-common/rdpear_common.h>
20#include <rdpear-common/rdpear_asn1.h>
21#include <rdpear-common/ndr.h>
24#include <winpr/print.h>
25#include <freerdp/channels/log.h>
27#define TAG CHANNELS_TAG("rdpear")
29static char kerberosPackageName[] = {
30 'K', 0,
'e', 0,
'r', 0,
'b', 0,
'e', 0,
'r', 0,
'o', 0,
's', 0
32static char ntlmPackageName[] = {
'N', 0,
'T', 0,
'L', 0,
'M', 0 };
36 if (package->len ==
sizeof(kerberosPackageName) &&
37 memcmp(package->data, kerberosPackageName, package->len) == 0)
38 return RDPEAR_PACKAGE_KERBEROS;
40 if (package->len ==
sizeof(ntlmPackageName) &&
41 memcmp(package->data, ntlmPackageName, package->len) == 0)
42 return RDPEAR_PACKAGE_NTLM;
44 return RDPEAR_PACKAGE_UNKNOWN;
50 WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
55 if (!WinPrAsn1EncSeqContainer(enc))
62 packageOctetString.data = (BYTE*)kerberosPackageName;
63 packageOctetString.len =
sizeof(kerberosPackageName);
67 packageOctetString.data = (BYTE*)ntlmPackageName;
68 packageOctetString.len =
sizeof(ntlmPackageName);
71 if (!WinPrAsn1EncContextualOctetString(enc, 1, &packageOctetString))
76 Stream_Buffer(payload) };
77 if (!WinPrAsn1EncContextualOctetString(enc, 2, &payloadOctetString))
81 if (!WinPrAsn1EncEndContainer(enc))
84 ret = Stream_New(NULL, 100);
88 if (!WinPrAsn1EncToStream(enc, ret))
90 Stream_Free(ret, TRUE);
95 WinPrAsn1Encoder_Free(&enc);
99#define RDPEAR_SIMPLE_MESSAGE_TYPE(V) \
100 BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj) \
102 WINPR_UNUSED(hints); \
103 return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
105 BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, const V* obj) \
107 WINPR_UNUSED(hints); \
108 return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
110 void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj) \
112 WINPR_UNUSED(hints); \
113 ndr_struct_destroy(context, &V##_struct, obj); \
115 void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj) \
117 ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
120 static BOOL ndr_descr_read_##V(NdrContext* context, wStream* s, const void* hints, void* obj) \
122 WINPR_UNUSED(hints); \
123 return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
125 static BOOL ndr_descr_write_##V(NdrContext* context, wStream* s, const void* hints, \
128 WINPR_UNUSED(hints); \
129 return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
131 static void ndr_descr_destroy_##V(NdrContext* context, const void* hints, void* obj) \
133 WINPR_UNUSED(hints); \
134 ndr_struct_destroy(context, &V##_struct, obj); \
136 static void ndr_descr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const void* obj) \
138 ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
141 static NdrMessageDescr ndr_##V##_descr_s = { \
142 NDR_ARITY_SIMPLE, sizeof(V), ndr_descr_read_##V, ndr_descr_write_##V, \
143 ndr_descr_destroy_##V, ndr_descr_dump_##V, \
146 NdrMessageType ndr_##V##_descr(void) \
148 return &ndr_##V##_descr_s; \
154 &ndr_uint8Array_descr_s }
156static const NdrStructDescr KERB_RPC_OCTET_STRING_struct = {
"KERB_RPC_OCTET_STRING", 2,
157 KERB_RPC_OCTET_STRING_fields };
164 {
"Pdu", offsetof(
KERB_ASN1_DATA, Pdu), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
165 {
"Count", offsetof(
KERB_ASN1_DATA, Asn1BufferHints.count), NDR_NOT_POINTER, -1,
166 &ndr_uint32_descr_s },
167 {
"Asn1Buffer", offsetof(
KERB_ASN1_DATA, Asn1Buffer), NDR_POINTER_NON_NULL, 1,
168 &ndr_uint8Array_descr_s }
170static const NdrStructDescr KERB_ASN1_DATA_struct = {
"KERB_ASN1_DATA",
171 ARRAYSIZE(KERB_ASN1_DATA_fields),
172 KERB_ASN1_DATA_fields };
178BOOL ndr_read_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
const void* hints,
181 NdrDeferredEntry bufferDesc = { NDR_PTR_NULL,
"RPC_UNICODE_STRING.Buffer", &res->lenHints,
182 (
void*)&res->Buffer, ndr_uint16VaryingArray_descr() };
184 UINT16 MaximumLength = 0;
187 if (!ndr_read_uint16(context, s, &Length) || !ndr_read_uint16(context, s, &MaximumLength) ||
188 !ndr_read_refpointer(context, s, &bufferDesc.ptrId) || Length > MaximumLength)
191 res->lenHints.length = Length;
192 res->lenHints.maxLength = MaximumLength;
193 res->strLength = Length / 2;
195 return ndr_push_deferreds(context, &bufferDesc, 1);
198static BOOL ndr_descr_read_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
const void* hints,
201 return ndr_read_RPC_UNICODE_STRING(context, s, hints, res);
204BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
205 WINPR_ATTR_UNUSED
const void* hints,
209 if (!ndr_write_uint32(context, s, res->lenHints.length))
212 if (!ndr_write_uint32(context, s, res->lenHints.maxLength))
215 return ndr_write_data(context, s, res->Buffer, res->strLength);
218static BOOL ndr_write_RPC_UNICODE_STRING_(NdrContext* context,
wStream* s,
const void* hints,
222 return ndr_write_RPC_UNICODE_STRING(context, s, hints, res);
225void ndr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
228 WINPR_UNUSED(indentLevel);
229 WLog_Print(logger, lvl,
"\tLength=%u MaximumLength=%u", obj->lenHints.length,
230 obj->lenHints.maxLength);
231 winpr_HexLogDump(logger, lvl, obj->Buffer, obj->lenHints.length);
234static void ndr_descr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
237 ndr_dump_RPC_UNICODE_STRING(logger, lvl, indentLevel, obj);
240void ndr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
RPC_UNICODE_STRING* obj)
242 WINPR_UNUSED(context);
250static void ndr_descr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
void* obj)
252 ndr_destroy_RPC_UNICODE_STRING(context, hints, obj);
255static const NdrMessageDescr RPC_UNICODE_STRING_descr_s = { NDR_ARITY_SIMPLE,
257 ndr_descr_read_RPC_UNICODE_STRING,
258 ndr_write_RPC_UNICODE_STRING_,
259 ndr_descr_destroy_RPC_UNICODE_STRING,
260 ndr_descr_dump_RPC_UNICODE_STRING };
264 return &RPC_UNICODE_STRING_descr_s;
269static BOOL ndr_read_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* hints,
272 WINPR_ASSERT(context);
275 return ndr_read_uconformant_array(context, s, hints, ndr_RPC_UNICODE_STRING_descr(), v);
278static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* ghints,
281 WINPR_ASSERT(context);
283 WINPR_ASSERT(ghints);
287 return ndr_write_uconformant_array(context, s, hints->count, ndr_RPC_UNICODE_STRING_descr(), v);
293 ndr_read_RPC_UNICODE_STRING_Array,
294 ndr_write_RPC_UNICODE_STRING_Array,
301 return &RPC_UNICODE_STRING_Array_descr_s;
306BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
316 cnv.ppstr = &res->Names;
317 NdrDeferredEntry names = { NDR_PTR_NULL,
"KERB_RPC_INTERNAL_NAME.Names", &res->nameHints,
318 cnv.pv, ndr_RPC_UNICODE_STRING_Array_descr() };
320 UINT16 nameCount = 0;
323 if (!ndr_read_uint16(context, s, &res->NameType) || !ndr_read_uint16(context, s, &nameCount))
326 res->nameHints.count = nameCount;
328 return ndr_read_refpointer(context, s, &names.ptrId) && ndr_push_deferreds(context, &names, 1);
331static BOOL ndr_descr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
332 const void* hints,
void* res)
334 return ndr_read_KERB_RPC_INTERNAL_NAME(context, s, hints, res);
337BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
340 WINPR_UNUSED(context);
344 WLog_ERR(TAG,
"TODO: implement this");
348void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
351 WINPR_UNUSED(indentLevel);
353 WLog_Print(logger, lvl,
"TODO: implement this");
356static void ndr_descr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
359 ndr_dump_KERB_RPC_INTERNAL_NAME(logger, lvl, indentLevel, obj);
362void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
369 for (UINT32 i = 0; i < obj->nameHints.count; i++)
370 ndr_destroy_RPC_UNICODE_STRING(context, NULL, &obj->Names[i]);
376static void ndr_descr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
379 ndr_destroy_KERB_RPC_INTERNAL_NAME(context, hints, obj);
382static NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_s = { NDR_ARITY_SIMPLE,
384 ndr_descr_read_KERB_RPC_INTERNAL_NAME,
386 ndr_descr_destroy_KERB_RPC_INTERNAL_NAME,
387 ndr_descr_dump_KERB_RPC_INTERNAL_NAME };
391 return &KERB_RPC_INTERNAL_NAME_descr_s;
398 &ndr_uint32_descr_s },
400 &ndr_uint32_descr_s },
402 &ndr_KERB_RPC_OCTET_STRING_descr_s }
405 "KERB_RPC_ENCRYPTION_KEY", ARRAYSIZE(KERB_RPC_ENCRYPTION_KEY_fields),
406 KERB_RPC_ENCRYPTION_KEY_fields
415 &ndr_uint32_descr_s },
417 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
419 &ndr_KERB_ASN1_DATA_descr_s }
422 "BuildEncryptedAuthDataReq", ARRAYSIZE(BuildEncryptedAuthDataReq_fields),
423 BuildEncryptedAuthDataReq_fields
432 &ndr_KERB_ASN1_DATA_descr_s },
434 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
436 &ndr_uint32_descr_s }
439 "ComputeTgsChecksumReq", ARRAYSIZE(ComputeTgsChecksumReq_fields), ComputeTgsChecksumReq_fields
446static const NdrFieldStruct CreateApReqAuthenticatorReq_fields[] = {
448 -1, &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
450 &ndr_uint32_descr_s },
452 &KERB_RPC_INTERNAL_NAME_descr_s },
454 &RPC_UNICODE_STRING_descr_s },
456 &ndr_uint64_descr_s },
458 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
460 &ndr_KERB_ASN1_DATA_descr_s },
462 &ndr_KERB_ASN1_DATA_descr_s },
464 &ndr_uint32_descr_s },
467 "CreateApReqAuthenticatorReq", ARRAYSIZE(CreateApReqAuthenticatorReq_fields),
468 CreateApReqAuthenticatorReq_fields
475static const NdrFieldStruct CreateApReqAuthenticatorResp_fields[] = {
477 NDR_NOT_POINTER, -1, &ndr_uint64_descr_s },
479 &ndr_KERB_ASN1_DATA_descr_s },
481 NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
484static const NdrStructDescr CreateApReqAuthenticatorResp_struct = {
485 "CreateApReqAuthenticatorResp", ARRAYSIZE(CreateApReqAuthenticatorResp_fields),
486 CreateApReqAuthenticatorResp_fields
495 &ndr_KERB_ASN1_DATA_descr_s },
497 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
499 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
502 &ndr_uint32_descr_s },
506 "UnpackKdcReplyBodyReq", ARRAYSIZE(UnpackKdcReplyBodyReq_fields), UnpackKdcReplyBodyReq_fields
515 &ndr_uint32_descr_s },
517 &ndr_KERB_ASN1_DATA_descr_s }
521 "UnpackKdcReplyBodyResp", ARRAYSIZE(UnpackKdcReplyBodyResp_fields),
522 UnpackKdcReplyBodyResp_fields
530 {
"EncryptedReply", offsetof(
DecryptApReplyReq, EncryptedReply), NDR_POINTER_NON_NULL, -1,
531 &ndr_KERB_ASN1_DATA_descr_s },
533 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
536static const NdrStructDescr DecryptApReplyReq_struct = {
"DecryptApReplyReq",
537 ARRAYSIZE(DecryptApReplyReq_fields),
538 DecryptApReplyReq_fields };
545 {
"Reply", offsetof(
PackApReplyReq, Reply), NDR_POINTER_NON_NULL, -1,
546 &ndr_KERB_ASN1_DATA_descr_s },
547 {
"ReplyBody", offsetof(
PackApReplyReq, ReplyBody), NDR_POINTER_NON_NULL, -1,
548 &ndr_KERB_ASN1_DATA_descr_s },
549 {
"SessionKey", offsetof(
PackApReplyReq, SessionKey), NDR_POINTER_NON_NULL, -1,
550 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
553static const NdrStructDescr PackApReplyReq_struct = {
"PackApReplyReq",
554 ARRAYSIZE(PackApReplyReq_fields),
555 PackApReplyReq_fields };
562 {
"PackedReplySize", offsetof(
PackApReplyResp, PackedReplyHints), NDR_NOT_POINTER, -1,
563 &ndr_uint32_descr_s },
564 {
"PackedReply", offsetof(
PackApReplyResp, PackedReply), NDR_POINTER_NON_NULL, 0,
565 &ndr_uint8Array_descr_s },
568static const NdrStructDescr PackApReplyResp_struct = {
"PackApReplyResp",
569 ARRAYSIZE(PackApReplyResp_fields),
570 PackApReplyResp_fields };
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.2.1.2.3 KERB_RPC_INTERNAL_NAME
2.2.1.2.2 KERB_RPC_OCTET_STRING
hints for a conformant array
descriptor of a field in a structure
2.3.10 RPC_UNICODE_STRING (MS-DTYP)
2.2.2.1.6 UnpackKdcReplyBody
2.2.2.1.6 UnpackKdcReplyBody