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;
47wStream* rdpear_encodePayload(RdpEarPackageType packageType,
wStream* payload)
50 WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
55 if (!WinPrAsn1EncSeqContainer(enc))
62 case RDPEAR_PACKAGE_KERBEROS:
63 packageOctetString.data = (BYTE*)kerberosPackageName;
64 packageOctetString.len =
sizeof(kerberosPackageName);
66 case RDPEAR_PACKAGE_NTLM:
67 packageOctetString.data = (BYTE*)ntlmPackageName;
68 packageOctetString.len =
sizeof(ntlmPackageName);
74 if (!WinPrAsn1EncContextualOctetString(enc, 1, &packageOctetString))
79 Stream_Buffer(payload) };
80 if (!WinPrAsn1EncContextualOctetString(enc, 2, &payloadOctetString))
84 if (!WinPrAsn1EncEndContainer(enc))
87 ret = Stream_New(NULL, 100);
91 if (!WinPrAsn1EncToStream(enc, ret))
93 Stream_Free(ret, TRUE);
98 WinPrAsn1Encoder_Free(&enc);
102#define RDPEAR_SIMPLE_MESSAGE_TYPE(V) \
103 BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj) \
105 WINPR_UNUSED(hints); \
106 return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
108 BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, const V* obj) \
110 WINPR_UNUSED(hints); \
111 return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
113 void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj) \
115 WINPR_UNUSED(hints); \
116 ndr_struct_destroy(context, &V##_struct, obj); \
118 void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj) \
120 ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
123 static BOOL ndr_descr_read_##V(NdrContext* context, wStream* s, const void* hints, void* obj) \
125 WINPR_UNUSED(hints); \
126 return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
128 static BOOL ndr_descr_write_##V(NdrContext* context, wStream* s, const void* hints, \
131 WINPR_UNUSED(hints); \
132 return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
134 static void ndr_descr_destroy_##V(NdrContext* context, const void* hints, void* obj) \
136 WINPR_UNUSED(hints); \
137 ndr_struct_destroy(context, &V##_struct, obj); \
139 static void ndr_descr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const void* obj) \
141 ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
144 static NdrMessageDescr ndr_##V##_descr_s = { \
145 NDR_ARITY_SIMPLE, sizeof(V), ndr_descr_read_##V, ndr_descr_write_##V, \
146 ndr_descr_destroy_##V, ndr_descr_dump_##V, \
149 NdrMessageType ndr_##V##_descr(void) \
151 return &ndr_##V##_descr_s; \
157 &ndr_uint8Array_descr_s }
159static const NdrStructDescr KERB_RPC_OCTET_STRING_struct = {
"KERB_RPC_OCTET_STRING", 2,
160 KERB_RPC_OCTET_STRING_fields };
167 {
"Pdu", offsetof(
KERB_ASN1_DATA, Pdu), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
168 {
"Count", offsetof(
KERB_ASN1_DATA, Asn1BufferHints.count), NDR_NOT_POINTER, -1,
169 &ndr_uint32_descr_s },
170 {
"Asn1Buffer", offsetof(
KERB_ASN1_DATA, Asn1Buffer), NDR_POINTER_NON_NULL, 1,
171 &ndr_uint8Array_descr_s }
173static const NdrStructDescr KERB_ASN1_DATA_struct = {
"KERB_ASN1_DATA",
174 ARRAYSIZE(KERB_ASN1_DATA_fields),
175 KERB_ASN1_DATA_fields };
181BOOL ndr_read_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
const void* hints,
184 NdrDeferredEntry bufferDesc = { NDR_PTR_NULL,
"RPC_UNICODE_STRING.Buffer", &res->lenHints,
185 (
void*)&res->Buffer, ndr_uint16VaryingArray_descr() };
187 UINT16 MaximumLength = 0;
190 if (!ndr_read_uint16(context, s, &Length) || !ndr_read_uint16(context, s, &MaximumLength) ||
191 !ndr_read_refpointer(context, s, &bufferDesc.ptrId) || Length > MaximumLength)
194 res->lenHints.length = Length;
195 res->lenHints.maxLength = MaximumLength;
196 res->strLength = Length / 2;
198 return ndr_push_deferreds(context, &bufferDesc, 1);
201static BOOL ndr_descr_read_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
const void* hints,
204 return ndr_read_RPC_UNICODE_STRING(context, s, hints, res);
207BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
208 WINPR_ATTR_UNUSED
const void* hints,
212 if (!ndr_write_uint32(context, s, res->lenHints.length))
215 if (!ndr_write_uint32(context, s, res->lenHints.maxLength))
218 return ndr_write_data(context, s, res->Buffer, res->strLength);
221static BOOL ndr_write_RPC_UNICODE_STRING_(NdrContext* context,
wStream* s,
const void* hints,
225 return ndr_write_RPC_UNICODE_STRING(context, s, hints, res);
228void ndr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
231 WINPR_UNUSED(indentLevel);
232 WLog_Print(logger, lvl,
"\tLength=%d MaximumLength=%d", obj->lenHints.length,
233 obj->lenHints.maxLength);
234 winpr_HexLogDump(logger, lvl, obj->Buffer, obj->lenHints.length);
237static void ndr_descr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
240 ndr_dump_RPC_UNICODE_STRING(logger, lvl, indentLevel, obj);
243void ndr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
RPC_UNICODE_STRING* obj)
245 WINPR_UNUSED(context);
253static void ndr_descr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
void* obj)
255 ndr_destroy_RPC_UNICODE_STRING(context, hints, obj);
258static const NdrMessageDescr RPC_UNICODE_STRING_descr_s = { NDR_ARITY_SIMPLE,
260 ndr_descr_read_RPC_UNICODE_STRING,
261 ndr_write_RPC_UNICODE_STRING_,
262 ndr_descr_destroy_RPC_UNICODE_STRING,
263 ndr_descr_dump_RPC_UNICODE_STRING };
267 return &RPC_UNICODE_STRING_descr_s;
272static BOOL ndr_read_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* hints,
275 WINPR_ASSERT(context);
278 return ndr_read_uconformant_array(context, s, hints, ndr_RPC_UNICODE_STRING_descr(), v);
281static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* ghints,
284 WINPR_ASSERT(context);
286 WINPR_ASSERT(ghints);
290 return ndr_write_uconformant_array(context, s, hints->count, ndr_RPC_UNICODE_STRING_descr(), v);
296 ndr_read_RPC_UNICODE_STRING_Array,
297 ndr_write_RPC_UNICODE_STRING_Array,
304 return &RPC_UNICODE_STRING_Array_descr_s;
309BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
319 cnv.ppstr = &res->Names;
320 NdrDeferredEntry names = { NDR_PTR_NULL,
"KERB_RPC_INTERNAL_NAME.Names", &res->nameHints,
321 cnv.pv, ndr_RPC_UNICODE_STRING_Array_descr() };
323 UINT16 nameCount = 0;
326 if (!ndr_read_uint16(context, s, &res->NameType) || !ndr_read_uint16(context, s, &nameCount))
329 res->nameHints.count = nameCount;
331 return ndr_read_refpointer(context, s, &names.ptrId) && ndr_push_deferreds(context, &names, 1);
334static BOOL ndr_descr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
335 const void* hints,
void* res)
337 return ndr_read_KERB_RPC_INTERNAL_NAME(context, s, hints, res);
340BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
343 WINPR_UNUSED(context);
347 WLog_ERR(TAG,
"TODO: implement this");
351void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
354 WINPR_UNUSED(indentLevel);
356 WLog_Print(logger, lvl,
"TODO: implement this");
359static void ndr_descr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
362 ndr_dump_KERB_RPC_INTERNAL_NAME(logger, lvl, indentLevel, obj);
365void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
372 for (UINT32 i = 0; i < obj->nameHints.count; i++)
373 ndr_destroy_RPC_UNICODE_STRING(context, NULL, &obj->Names[i]);
379static void ndr_descr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
382 ndr_destroy_KERB_RPC_INTERNAL_NAME(context, hints, obj);
385static NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_s = { NDR_ARITY_SIMPLE,
387 ndr_descr_read_KERB_RPC_INTERNAL_NAME,
389 ndr_descr_destroy_KERB_RPC_INTERNAL_NAME,
390 ndr_descr_dump_KERB_RPC_INTERNAL_NAME };
394 return &KERB_RPC_INTERNAL_NAME_descr_s;
401 &ndr_uint32_descr_s },
403 &ndr_uint32_descr_s },
405 &ndr_KERB_RPC_OCTET_STRING_descr_s }
408 "KERB_RPC_ENCRYPTION_KEY", ARRAYSIZE(KERB_RPC_ENCRYPTION_KEY_fields),
409 KERB_RPC_ENCRYPTION_KEY_fields
418 &ndr_uint32_descr_s },
420 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
422 &ndr_KERB_ASN1_DATA_descr_s }
425 "BuildEncryptedAuthDataReq", ARRAYSIZE(BuildEncryptedAuthDataReq_fields),
426 BuildEncryptedAuthDataReq_fields
435 &ndr_KERB_ASN1_DATA_descr_s },
437 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
439 &ndr_uint32_descr_s }
442 "ComputeTgsChecksumReq", ARRAYSIZE(ComputeTgsChecksumReq_fields), ComputeTgsChecksumReq_fields
449static const NdrFieldStruct CreateApReqAuthenticatorReq_fields[] = {
451 -1, &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
453 &ndr_uint32_descr_s },
455 &KERB_RPC_INTERNAL_NAME_descr_s },
457 &RPC_UNICODE_STRING_descr_s },
459 &ndr_uint64_descr_s },
461 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
463 &ndr_KERB_ASN1_DATA_descr_s },
465 &ndr_KERB_ASN1_DATA_descr_s },
467 &ndr_uint32_descr_s },
470 "CreateApReqAuthenticatorReq", ARRAYSIZE(CreateApReqAuthenticatorReq_fields),
471 CreateApReqAuthenticatorReq_fields
478static const NdrFieldStruct CreateApReqAuthenticatorResp_fields[] = {
480 NDR_NOT_POINTER, -1, &ndr_uint64_descr_s },
482 &ndr_KERB_ASN1_DATA_descr_s },
484 NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
487static const NdrStructDescr CreateApReqAuthenticatorResp_struct = {
488 "CreateApReqAuthenticatorResp", ARRAYSIZE(CreateApReqAuthenticatorResp_fields),
489 CreateApReqAuthenticatorResp_fields
498 &ndr_KERB_ASN1_DATA_descr_s },
500 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
502 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
505 &ndr_uint32_descr_s },
509 "UnpackKdcReplyBodyReq", ARRAYSIZE(UnpackKdcReplyBodyReq_fields), UnpackKdcReplyBodyReq_fields
518 &ndr_uint32_descr_s },
520 &ndr_KERB_ASN1_DATA_descr_s }
524 "UnpackKdcReplyBodyResp", ARRAYSIZE(UnpackKdcReplyBodyResp_fields),
525 UnpackKdcReplyBodyResp_fields
533 {
"EncryptedReply", offsetof(
DecryptApReplyReq, EncryptedReply), NDR_POINTER_NON_NULL, -1,
534 &ndr_KERB_ASN1_DATA_descr_s },
536 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
539static const NdrStructDescr DecryptApReplyReq_struct = {
"DecryptApReplyReq",
540 ARRAYSIZE(DecryptApReplyReq_fields),
541 DecryptApReplyReq_fields };
548 {
"Reply", offsetof(
PackApReplyReq, Reply), NDR_POINTER_NON_NULL, -1,
549 &ndr_KERB_ASN1_DATA_descr_s },
550 {
"ReplyBody", offsetof(
PackApReplyReq, ReplyBody), NDR_POINTER_NON_NULL, -1,
551 &ndr_KERB_ASN1_DATA_descr_s },
552 {
"SessionKey", offsetof(
PackApReplyReq, SessionKey), NDR_POINTER_NON_NULL, -1,
553 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
556static const NdrStructDescr PackApReplyReq_struct = {
"PackApReplyReq",
557 ARRAYSIZE(PackApReplyReq_fields),
558 PackApReplyReq_fields };
565 {
"PackedReplySize", offsetof(
PackApReplyResp, PackedReplyHints), NDR_NOT_POINTER, -1,
566 &ndr_uint32_descr_s },
567 {
"PackedReply", offsetof(
PackApReplyResp, PackedReply), NDR_POINTER_NON_NULL, 0,
568 &ndr_uint8Array_descr_s },
571static const NdrStructDescr PackApReplyResp_struct = {
"PackApReplyResp",
572 ARRAYSIZE(PackApReplyResp_fields),
573 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