FreeRDP
TestNdrEar.c
1 #include <winpr/print.h>
2 
3 #include <rdpear-common/ndr.h>
4 #include <rdpear-common/rdpear_common.h>
5 
6 #ifndef MAX
7 #define MAX(a, b) ((a) > (b)) ? (a) : (b)
8 #endif
9 #ifndef MIN
10 #define MIN(a, b) ((a) < (b)) ? (a) : (b)
11 #endif
12 
13 static BYTE nextValue(BYTE old, INT32 offset, char symbol, char startSymbol)
14 {
15  const INT32 uold = 16 * old;
16  const INT32 diff = symbol - startSymbol;
17  const INT32 res = uold + diff + offset;
18  return (BYTE)MIN(MAX(0, res), UINT8_MAX);
19 }
20 
21 static BYTE* parseHexBlock(const char* str, size_t* plen)
22 {
23  WINPR_ASSERT(str);
24  WINPR_ASSERT(plen);
25 
26  BYTE* ret = malloc(strlen(str) / 2);
27  BYTE* dest = ret;
28  const char* ptr = str;
29  BYTE tmp = 0;
30  size_t nchars = 0;
31  size_t len = 0;
32 
33  for (; *ptr; ptr++)
34  {
35  switch (*ptr)
36  {
37  case ' ':
38  case '\n':
39  case '\t':
40  if (nchars)
41  {
42  WLog_ERR("", "error parsing hex block, unpaired char");
43  free(ret);
44  return NULL;
45  }
46  break;
47  case '0':
48  case '1':
49  case '2':
50  case '3':
51  case '4':
52  case '5':
53  case '6':
54  case '7':
55  case '8':
56  case '9':
57  tmp = nextValue(tmp, 0, *ptr, '0');
58  nchars++;
59  if (nchars == 2)
60  {
61  *dest = tmp;
62  dest++;
63  len++;
64  tmp = 0;
65  nchars = 0;
66  }
67  break;
68 
69  case 'a':
70  case 'b':
71  case 'c':
72  case 'd':
73  case 'e':
74  case 'f':
75  tmp = nextValue(tmp, 10, *ptr, 'a');
76  nchars++;
77  if (nchars == 2)
78  {
79  *dest = tmp;
80  dest++;
81  len++;
82  tmp = 0;
83  nchars = 0;
84  }
85  break;
86 
87  case 'A':
88  case 'B':
89  case 'C':
90  case 'D':
91  case 'E':
92  case 'F':
93  tmp = nextValue(tmp, 10, *ptr, 'A');
94  nchars++;
95  if (nchars == 2)
96  {
97  *dest = tmp;
98  dest++;
99  len++;
100  tmp = 0;
101  nchars = 0;
102  }
103  break;
104  default:
105  WLog_ERR("", "invalid char in hex block");
106  free(ret);
107  return NULL;
108  }
109  }
110 
111  *plen = len;
112  return ret;
113 }
114 
115 static int TestNdrEarWrite(int argc, char* argv[])
116 {
117  WINPR_UNUSED(argc);
118  WINPR_UNUSED(argv);
119 
120  int rc = -1;
121  BYTE buffer[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
122  KERB_ASN1_DATA asn1 = { 7, { 16 }, buffer };
123 
124  wStream* s = Stream_New(NULL, 100);
125  if (!s)
126  return -1;
127 
128  NdrContext* context = ndr_context_new(FALSE, 1);
129  if (!context)
130  goto fail;
131 
132  if (!ndr_write_KERB_ASN1_DATA(context, s, NULL, &asn1))
133  goto fail;
134  if (!ndr_treat_deferred_write(context, s))
135  goto fail;
136 
137  // winpr_HexDump("", WLOG_DEBUG, Stream_Buffer(s), Stream_GetPosition(s));
138 
139  rc = 0;
140 fail:
141  ndr_context_destroy(&context);
142  Stream_Free(s, TRUE);
143  return rc;
144 }
145 
146 static int TestNdrEarRead(int argc, char* argv[])
147 {
148  WINPR_UNUSED(argc);
149  WINPR_UNUSED(argv);
150 
151  int retCode = -2;
152 
153  /* ====================================================================== */
154  NdrContext* context = ndr_context_new(FALSE, 1);
155  if (!context)
156  return -1;
157 
158  wStream staticS = { 0 };
159  wStream* s = NULL;
160 
161 #if 0
162  BYTE payload[] = {
163  0x00, 0x00, 0x00, 0x00, // (PduType)
164  0x02, 0x00, 0x00, 0x00, // (Length)
165  0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
166 
167  // == conformant array ==
168  0x02, 0x00, 0x00, 0x00, // (nitems)
169  0x30, 0x00, // content
170  0x00, 0x00 // (padding)
171  };
172  s = Stream_StaticInit(&staticS, payload, sizeof(payload));
173 
174  KERB_ASN1_DATA asn1 = { 0 };
175  if (!ndr_read_KERB_ASN1_DATA(context, s, NULL, &asn1) || !ndr_treat_deferred_read(context, s) ||
176  asn1.Asn1BufferHints.count != 2 || *asn1.Asn1Buffer != 0x30)
177  goto out;
178  KERB_ASN1_DATA_destroy(context, &asn1);
179  ndr_context_reset(context);
180 
181  /* ====================================================================== */
182  BYTE payload2[] = {
183  // ------------ a RPC_UNICODE_STRING: Administrateur -------------------------
184  0x1c, 0x00, // (Length)
185  0x1e, 0x00, // (MaximumLength)
186  0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
187  // == conformant array ==
188  0x0f, 0x00, 0x00, 0x00, // (maximum count)
189  0x00, 0x00, 0x00, 0x00, // (offset)
190  0x0e, 0x00, 0x00, 0x00, // (length)
191 
192  0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e,
193  0x00, 0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x00, 0x00,
194 
195  0x00, 0x00
196  };
197  retCode = -3;
198 
199  s = Stream_StaticInit(&staticS, payload2, sizeof(payload2));
200  RPC_UNICODE_STRING unicode = { 0 };
201  if (!ndr_read_RPC_UNICODE_STRING(context, s, NULL, &unicode) || !ndr_treat_deferred_read(context, s))
202  goto out;
203  RPC_UNICODE_STRING_destroy(context, &unicode);
204  ndr_context_reset(context);
205 
206  /* ====================================================================== */
207  BYTE payload3[] = {
208  // ------------ an KERB_RPC_INTERNAL_NAME: HARDENING3.COM -------------------------
209  0x01, 0x00, // (NameType)
210  0x01, 0x00, // (NameCount)
211  0x10, 0x00, 0x02, 0x00, // (Names)
212  // == conformant array ==
213  0x01, 0x00, 0x00, 0x00, // (nitems)
214 
215  // = RPC_UNICODE_STRING =
216  0x1c, 0x00, // (Length)
217  0x1e, 0x00, // (MaximumLength)
218  0x14, 0x00, 0x02, 0x00,
219  // == Uni-dimensional Conformant-varying Array ==
220  0x0f, 0x00, 0x00, 0x00, // (maximum count)
221  0x00, 0x00, 0x00, 0x00, // (offset)
222  0x0e, 0x00, 0x00, 0x00, // (length)
223  0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74,
224  0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00, 0x00, 0x00,
225 
226  0x00, 0x00
227  };
228  KERB_RPC_INTERNAL_NAME intName = { 0 };
229  retCode = -4;
230  s = Stream_StaticInit(&staticS, payload3, sizeof(payload3));
231  if (!ndr_read_KERB_RPC_INTERNAL_NAME(context, s, NULL, &intName) || !ndr_treat_deferred_read(context, s))
232  goto out;
233  KERB_RPC_INTERNAL_NAME_destroy(context, &intName);
234  ndr_context_reset(context);
235 #endif
236 
237  /* ====================================================================== */
238 #if 0
239  BYTE payload4[] = {
240  0x03, 0x01, 0x03, 0x01, // unionId / unionId
241  0x04, 0x00, 0x02, 0x00, // (EncryptionKey ptr)
242  0xf8, 0xca, 0x95, 0x11, // (SequenceNumber)
243  0x0c, 0x00, 0x02, 0x00, // (ClientName ptr)
244  0x18, 0x00, 0x02, 0x00, // (ClientRealm ptr)
245  0x20, 0x00, 0x02, 0x00, // (SkewTime ptr)
246  0x00, 0x00, 0x00, 0x00, // (SubKey ptr)
247  0x24, 0x00, 0x02, 0x00, // (AuthData ptr)
248  0x2c, 0x00, 0x02, 0x00, // (GssChecksum ptr)
249  0x07, 0x00, 0x00, 0x00, // (KeyUsage)
250 
251  // === EncryptionKey ===
252  0x40, 0xe9, 0x12, 0xdf, // reserved1
253  0x12, 0x00, 0x00, 0x00, // reserved2
254  // KERB_RPC_OCTET_STRING
255  0x4c, 0x00, 0x00, 0x00, // (length)
256  0x08, 0x00, 0x02, 0x00, // (value ptr)
257  // == conformant array ==
258  0x4c, 0x00, 0x00, 0x00, // (length)
259  0xc4, 0x41, 0xee, 0x34,
260  0x82, 0x2b, 0x29, 0x61, 0xe2, 0x96, 0xb5, 0x75, 0x61, 0x2d, 0xbf, 0x86, 0x01, 0x00, 0x00, 0x00,
261  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x08, 0x60, 0x2e,
262  0x30, 0x3e, 0xfe, 0x56, 0x11, 0xf0, 0x31, 0xf2, 0xd6, 0x2e, 0x3d, 0x33, 0xfe, 0xce, 0x56, 0x12,
263  0xbf, 0xb2, 0xe5, 0x86, 0x29, 0x8d, 0x29, 0x74, 0x1f, 0x8a, 0xf9, 0xb9, 0x8c, 0xd4, 0x86, 0x3a,
264  0x21, 0x92, 0xb2, 0x07, 0x95, 0x4b, 0xea, 0xee,
265 
266  //=== ClientName - KERB_RPC_INTERNAL_NAME ===
267  0x01, 0x00, // (NameType)
268  0x01, 0x00, // (NameCount)
269  0x10, 0x00, 0x02, 0x00, // (Names)
270 
271  0x01, 0x00, 0x00, 0x00, // (nitems)
272 
273  // = RPC_UNICODE_STRING =
274  0x1c, 0x00, // (Length)
275  0x1e, 0x00, // (MaximumLength)
276  0x14, 0x00, 0x02, 0x00, //(Buffer ptr)
277  // == Uni-dimensional Conformant-varying Array ==
278  0x0f, 0x00, 0x00, 0x00, // (maximum count)
279  0x00, 0x00, 0x00, 0x00, // (offset)
280  0x0e, 0x00, 0x00, 0x00, // (length)
281  0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00,
282  0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00,
283 
284  // === ClientRealm - RPC_UNICODE_STRING ===
285  0x1c, 0x00, // (Length)
286  0x1e, 0x00, // (MaximumLength)
287  0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
288  // == Uni-dimensional conformant varying array ==
289  0x0f, 0x00, 0x00, 0x00, // (maximum count)
290  0x00, 0x00, 0x00, 0x00, // (offset)
291  0x0e, 0x00, 0x00, 0x00, // (length)
292  0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e, 0x00,
293  0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00,
294 
295  0x00, 0x00, 0x00, 0x00, // padding
296 
297  // == SkewTime ==
298  0x00, 0x00, 0x00, 0x00,
299  0x00, 0x00, 0x00, 0x00,
300 
301  // === AuthData - KERB_ASN1_DATA ==
302  0x00, 0x00, 0x00, 0x00, // (PduType)
303  0x02, 0x00, 0x00, 0x00, // (Length)
304  0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
305  // == conformant array ==
306  0x02, 0x00, 0x00, 0x00, // (nitems)
307  0x30, 0x00,
308  0x00, 0x00, // (padding)
309 
310  // === GssChecksum - KERB_ASN1_DATA ===
311  0x08, 0x00, 0x00, 0x00, // (PduType)
312  0x1b, 0x00, 0x00, 0x00, // (Length)
313  0x30, 0x00, 0x02, 0x00, // (Asn1Buffer)
314  // == conformant array ==
315  0x1b, 0x00, 0x00, 0x00, // (length)
316  0x30, 0x19,
317  0xa0, 0x03,
318  0x02, 0x01, 0x07,
319  0xa1, 0x12,
320  0x04, 0x10, 0xb9, 0x4f, 0xcd, 0xae, 0xd9, 0xa8, 0xff, 0x49, 0x69, 0x5a, 0xd1,
321  0x1d, 0x38, 0x49, 0xb6, 0x92, 0x00
322  };
323  size_t sizeofPayload4 = sizeof(payload4);
324 #endif
325 #if 1
326  size_t sizeofPayload4 = 0;
327  BYTE* payload4 = parseHexBlock("03 01 03 01 \
328  04 00 02 00 38 9e ef 6b 0c 00 02 00 18 00 02 00 \
329  20 00 02 00 00 00 00 00 24 00 02 00 2c 00 02 00 \
330  07 00 00 00 13 8a a5 a8 12 00 00 00 20 00 00 00 \
331  08 00 02 00 20 00 00 00 c9 03 42 a8 17 8f d9 c4 \
332  9b d2 c4 6e 73 64 98 7b 90 f5 9a 28 77 8e ca de \
333  29 2e a3 8d 8a 56 36 d5 01 00 01 00 10 00 02 00 \
334  01 00 00 00 1c 00 1e 00 14 00 02 00 0f 00 00 00 \
335  00 00 00 00 0e 00 00 00 41 00 64 00 6d 00 69 00 \
336  6e 00 69 00 73 00 74 00 72 00 61 00 74 00 65 00 \
337  75 00 72 00 1c 00 1e 00 1c 00 02 00 0f 00 00 00 \
338  00 00 00 00 0e 00 00 00 48 00 41 00 52 00 44 00 \
339  45 00 4e 00 49 00 4e 00 47 00 33 00 2e 00 43 00 \
340  4f 00 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 \
341  02 00 00 00 28 00 02 00 02 00 00 00 30 00 00 00 \
342  08 00 00 00 1b 00 00 00 30 00 02 00 1b 00 00 00 \
343  30 19 a0 03 02 01 07 a1 12 04 10 e4 aa ff 2b 93 \
344  97 4c f2 5c 0b 49 85 72 92 94 54 00",
345  &sizeofPayload4);
346 
347  if (!payload4)
348  goto out;
349 #endif
350 
351  CreateApReqAuthenticatorReq createApReqAuthenticatorReq = { 0 };
352  s = Stream_StaticInit(&staticS, payload4, sizeofPayload4);
353  if (!ndr_skip_bytes(context, s, 4) || /* skip union id */
354  !ndr_read_CreateApReqAuthenticatorReq(context, s, NULL, &createApReqAuthenticatorReq) ||
355  !ndr_treat_deferred_read(context, s) || createApReqAuthenticatorReq.KeyUsage != 7 ||
356  !createApReqAuthenticatorReq.EncryptionKey || createApReqAuthenticatorReq.SubKey ||
357  !createApReqAuthenticatorReq.ClientName ||
358  createApReqAuthenticatorReq.ClientName->nameHints.count != 1 ||
359  !createApReqAuthenticatorReq.ClientRealm || !createApReqAuthenticatorReq.AuthData ||
360  createApReqAuthenticatorReq.AuthData->Asn1BufferHints.count != 2 ||
361  !createApReqAuthenticatorReq.SkewTime ||
362  createApReqAuthenticatorReq.SkewTime->QuadPart != 0)
363  goto out;
364  ndr_destroy_CreateApReqAuthenticatorReq(context, NULL, &createApReqAuthenticatorReq);
365  ndr_context_reset(context);
366 
367  /* ============ successful end of test =============== */
368  retCode = 0;
369 out:
370  free(payload4);
371  ndr_context_destroy(&context);
372  return retCode;
373 }
374 
375 int TestNdrEar(int argc, char* argv[])
376 {
377  const int rc = TestNdrEarWrite(argc, argv);
378  if (rc)
379  return rc;
380  return TestNdrEarRead(argc, argv);
381 }
2.2.2.1.4 CreateApReqAuthenticator
2.2.1.2.1 KERB_ASN1_DATA
2.2.1.2.3 KERB_RPC_INTERNAL_NAME
2.3.10 RPC_UNICODE_STRING (MS-DTYP)