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")
29 static char kerberosPackageName[] = {
30 'K', 0,
'e', 0,
'r', 0,
'b', 0,
'e', 0,
'r', 0,
'o', 0,
's', 0
32 static 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;
47 wStream* 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 }
159 static 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 }
173 static const NdrStructDescr KERB_ASN1_DATA_struct = {
"KERB_ASN1_DATA",
174 ARRAYSIZE(KERB_ASN1_DATA_fields),
175 KERB_ASN1_DATA_fields };
181 BOOL 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 &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);
201 static 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);
208 BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context,
wStream* s,
const void* hints,
211 return ndr_write_uint32(context, s, res->lenHints.length) &&
212 ndr_write_uint32(context, s, res->lenHints.maxLength)
218 void ndr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
221 WINPR_UNUSED(indentLevel);
222 WLog_Print(logger, lvl,
"\tLength=%d MaximumLength=%d", obj->lenHints.length,
223 obj->lenHints.maxLength);
224 winpr_HexLogDump(logger, lvl, obj->Buffer, obj->lenHints.length);
227 static void ndr_descr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl,
size_t indentLevel,
230 ndr_dump_RPC_UNICODE_STRING(logger, lvl, indentLevel, obj);
233 void ndr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
RPC_UNICODE_STRING* obj)
235 WINPR_UNUSED(context);
243 static void ndr_descr_destroy_RPC_UNICODE_STRING(NdrContext* context,
const void* hints,
void* obj)
245 ndr_destroy_RPC_UNICODE_STRING(context, hints, obj);
248 static const NdrMessageDescr RPC_UNICODE_STRING_descr_s = { NDR_ARITY_SIMPLE,
250 ndr_descr_read_RPC_UNICODE_STRING,
252 ndr_descr_destroy_RPC_UNICODE_STRING,
253 ndr_descr_dump_RPC_UNICODE_STRING };
257 return &RPC_UNICODE_STRING_descr_s;
262 static BOOL ndr_read_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* hints,
265 WINPR_ASSERT(context);
268 return ndr_read_uconformant_array(context, s, hints, ndr_RPC_UNICODE_STRING_descr(), v);
271 static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context,
wStream* s,
const void* ghints,
274 WINPR_ASSERT(context);
276 WINPR_ASSERT(ghints);
280 return ndr_write_uconformant_array(context, s, hints->count, ndr_RPC_UNICODE_STRING_descr(), v);
286 ndr_read_RPC_UNICODE_STRING_Array,
287 ndr_write_RPC_UNICODE_STRING_Array,
294 return &RPC_UNICODE_STRING_Array_descr_s;
299 BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
309 cnv.ppstr = &res->Names;
310 NdrDeferredEntry names = { NDR_PTR_NULL,
"KERB_RPC_INTERNAL_NAME.Names", &res->nameHints,
311 cnv.pv, ndr_RPC_UNICODE_STRING_Array_descr() };
313 UINT16 nameCount = 0;
316 if (!ndr_read_uint16(context, s, &res->NameType) || !ndr_read_uint16(context, s, &nameCount))
319 res->nameHints.count = nameCount;
321 return ndr_read_refpointer(context, s, &names.ptrId) && ndr_push_deferreds(context, &names, 1);
324 static BOOL ndr_descr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
325 const void* hints,
void* res)
327 return ndr_read_KERB_RPC_INTERNAL_NAME(context, s, hints, res);
330 BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context,
wStream* s,
const void* hints,
333 WINPR_UNUSED(context);
337 WLog_ERR(TAG,
"TODO: implement this");
341 void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
344 WINPR_UNUSED(indentLevel);
346 WLog_Print(logger, lvl,
"TODO: implement this");
349 static void ndr_descr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl,
size_t indentLevel,
352 ndr_dump_KERB_RPC_INTERNAL_NAME(logger, lvl, indentLevel, obj);
355 void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
362 for (UINT32 i = 0; i < obj->nameHints.count; i++)
363 ndr_destroy_RPC_UNICODE_STRING(context, NULL, &obj->Names[i]);
369 static void ndr_descr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context,
const void* hints,
372 ndr_destroy_KERB_RPC_INTERNAL_NAME(context, hints, obj);
375 static NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_s = { NDR_ARITY_SIMPLE,
377 ndr_descr_read_KERB_RPC_INTERNAL_NAME,
379 ndr_descr_destroy_KERB_RPC_INTERNAL_NAME,
380 ndr_descr_dump_KERB_RPC_INTERNAL_NAME };
384 return &KERB_RPC_INTERNAL_NAME_descr_s;
391 &ndr_uint32_descr_s },
393 &ndr_uint32_descr_s },
395 &ndr_KERB_RPC_OCTET_STRING_descr_s }
398 "KERB_RPC_ENCRYPTION_KEY", ARRAYSIZE(KERB_RPC_ENCRYPTION_KEY_fields),
399 KERB_RPC_ENCRYPTION_KEY_fields
406 static const NdrFieldStruct BuildEncryptedAuthDataReq_fields[] = {
408 &ndr_uint32_descr_s },
410 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
412 &ndr_KERB_ASN1_DATA_descr_s }
415 "BuildEncryptedAuthDataReq", ARRAYSIZE(BuildEncryptedAuthDataReq_fields),
416 BuildEncryptedAuthDataReq_fields
425 &ndr_KERB_ASN1_DATA_descr_s },
427 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
429 &ndr_uint32_descr_s }
432 "ComputeTgsChecksumReq", ARRAYSIZE(ComputeTgsChecksumReq_fields), ComputeTgsChecksumReq_fields
439 static const NdrFieldStruct CreateApReqAuthenticatorReq_fields[] = {
441 -1, &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
443 &ndr_uint32_descr_s },
445 &KERB_RPC_INTERNAL_NAME_descr_s },
447 &RPC_UNICODE_STRING_descr_s },
449 &ndr_uint64_descr_s },
451 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
453 &ndr_KERB_ASN1_DATA_descr_s },
455 &ndr_KERB_ASN1_DATA_descr_s },
457 &ndr_uint32_descr_s },
459 static const NdrStructDescr CreateApReqAuthenticatorReq_struct = {
460 "CreateApReqAuthenticatorReq", ARRAYSIZE(CreateApReqAuthenticatorReq_fields),
461 CreateApReqAuthenticatorReq_fields
468 static const NdrFieldStruct CreateApReqAuthenticatorResp_fields[] = {
470 NDR_NOT_POINTER, -1, &ndr_uint64_descr_s },
472 &ndr_KERB_ASN1_DATA_descr_s },
474 NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
477 static const NdrStructDescr CreateApReqAuthenticatorResp_struct = {
478 "CreateApReqAuthenticatorResp", ARRAYSIZE(CreateApReqAuthenticatorResp_fields),
479 CreateApReqAuthenticatorResp_fields
488 &ndr_KERB_ASN1_DATA_descr_s },
490 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
492 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
495 &ndr_uint32_descr_s },
499 "UnpackKdcReplyBodyReq", ARRAYSIZE(UnpackKdcReplyBodyReq_fields), UnpackKdcReplyBodyReq_fields
508 &ndr_uint32_descr_s },
510 &ndr_KERB_ASN1_DATA_descr_s }
514 "UnpackKdcReplyBodyResp", ARRAYSIZE(UnpackKdcReplyBodyResp_fields),
515 UnpackKdcReplyBodyResp_fields
523 {
"EncryptedReply", offsetof(
DecryptApReplyReq, EncryptedReply), NDR_POINTER_NON_NULL, -1,
524 &ndr_KERB_ASN1_DATA_descr_s },
526 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
529 static const NdrStructDescr DecryptApReplyReq_struct = {
"DecryptApReplyReq",
530 ARRAYSIZE(DecryptApReplyReq_fields),
531 DecryptApReplyReq_fields };
538 {
"Reply", offsetof(
PackApReplyReq, Reply), NDR_POINTER_NON_NULL, -1,
539 &ndr_KERB_ASN1_DATA_descr_s },
540 {
"ReplyBody", offsetof(
PackApReplyReq, ReplyBody), NDR_POINTER_NON_NULL, -1,
541 &ndr_KERB_ASN1_DATA_descr_s },
542 {
"SessionKey", offsetof(
PackApReplyReq, SessionKey), NDR_POINTER_NON_NULL, -1,
543 &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
546 static const NdrStructDescr PackApReplyReq_struct = {
"PackApReplyReq",
547 ARRAYSIZE(PackApReplyReq_fields),
548 PackApReplyReq_fields };
555 {
"PackedReplySize", offsetof(
PackApReplyResp, PackedReplyHints), NDR_NOT_POINTER, -1,
556 &ndr_uint32_descr_s },
557 {
"PackedReply", offsetof(
PackApReplyResp, PackedReply), NDR_POINTER_NON_NULL, 0,
558 &ndr_uint8Array_descr_s },
561 static const NdrStructDescr PackApReplyResp_struct = {
"PackApReplyResp",
562 ARRAYSIZE(PackApReplyResp_fields),
563 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