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=%u MaximumLength=%u", 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