FreeRDP
Loading...
Searching...
No Matches
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
13static 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
21static 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
115static 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;
140fail:
141 ndr_context_destroy(&context);
142 Stream_Free(s, TRUE);
143 return rc;
144}
145
146static BOOL run_payload(NdrContext* context, const BYTE* payload4, size_t sizeofPayload4)
147{
148 WINPR_ASSERT(context);
149
150 if (!payload4)
151 return FALSE;
152
153 CreateApReqAuthenticatorReq createApReqAuthenticatorReq = { 0 };
154
155 wStream staticS = { 0 };
156 wStream* s = Stream_StaticInit(&staticS, payload4, sizeofPayload4);
157 if (!ndr_skip_bytes(context, s, 4)) /* skip union id */
158 return FALSE;
159 if (!ndr_read_CreateApReqAuthenticatorReq(context, s, NULL, &createApReqAuthenticatorReq))
160 return FALSE;
161 if (!ndr_treat_deferred_read(context, s))
162 return FALSE;
163 if (createApReqAuthenticatorReq.KeyUsage != 7)
164 return FALSE;
165 if (!createApReqAuthenticatorReq.EncryptionKey)
166 return FALSE;
167 if (createApReqAuthenticatorReq.SubKey)
168 return FALSE;
169 if (!createApReqAuthenticatorReq.ClientName)
170 return FALSE;
171 if (createApReqAuthenticatorReq.ClientName->nameHints.count != 1)
172 return FALSE;
173 if (!createApReqAuthenticatorReq.ClientRealm)
174 return FALSE;
175 if (!createApReqAuthenticatorReq.AuthData)
176 return FALSE;
177 if (createApReqAuthenticatorReq.AuthData->Asn1BufferHints.count != 2)
178 return FALSE;
179 if (!createApReqAuthenticatorReq.SkewTime)
180 return FALSE;
181 if (createApReqAuthenticatorReq.SkewTime->QuadPart != 0)
182 return FALSE;
183
184 ndr_destroy_CreateApReqAuthenticatorReq(context, NULL, &createApReqAuthenticatorReq);
185 ndr_context_reset(context);
186 return TRUE;
187}
188
189static int TestNdrEarRead(int argc, char* argv[])
190{
191 WINPR_UNUSED(argc);
192 WINPR_UNUSED(argv);
193
194 int retCode = -1;
195
196 /* ====================================================================== */
197 NdrContext* context = ndr_context_new(FALSE, 1);
198 if (!context)
199 return -1;
200
201 {
202 retCode = -2;
203 const BYTE payload[] = {
204 0x00, 0x00, 0x00, 0x00, // (PduType)
205 0x02, 0x00, 0x00, 0x00, // (Length)
206 0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
207
208 // == conformant array ==
209 0x02, 0x00, 0x00, 0x00, // (nitems)
210 0x30, 0x00, // content
211 0x00, 0x00 // (padding)
212 };
213
214 wStream staticS = { 0 };
215 wStream* s = Stream_StaticInit(&staticS, payload, sizeof(payload));
216
217 KERB_ASN1_DATA asn1 = { 0 };
218 if (!ndr_read_KERB_ASN1_DATA(context, s, NULL, &asn1) ||
219 !ndr_treat_deferred_read(context, s) || asn1.Asn1BufferHints.count != 2 ||
220 *asn1.Asn1Buffer != 0x30)
221 goto out;
222 ndr_destroy_KERB_ASN1_DATA(context, NULL, &asn1);
223 ndr_context_reset(context);
224
225 /* ====================================================================== */
226 }
227 {
228 retCode = -3;
229 const BYTE payload2[] = {
230 // ------------ a RPC_UNICODE_STRING: Administrateur -------------------------
231 0x1c, 0x00, // (Length)
232 0x1e, 0x00, // (MaximumLength)
233 0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
234 // == conformant array ==
235 0x0f, 0x00, 0x00, 0x00, // (maximum count)
236 0x00, 0x00, 0x00, 0x00, // (offset)
237 0x0e, 0x00, 0x00, 0x00, // (length)
238
239 0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00,
240 0x4e, 0x00, 0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00,
241 0x00, 0x00,
242
243 0x00, 0x00
244 };
245
246 wStream staticS = { 0 };
247 wStream* s = Stream_StaticInit(&staticS, payload2, sizeof(payload2));
248 RPC_UNICODE_STRING unicode = { 0 };
249 if (!ndr_read_RPC_UNICODE_STRING(context, s, NULL, &unicode) ||
250 !ndr_treat_deferred_read(context, s))
251 goto out;
252 ndr_destroy_RPC_UNICODE_STRING(context, NULL, &unicode);
253 ndr_context_reset(context);
254 }
255 {
256 retCode = -4;
257 /* ====================================================================== */
258 const BYTE payload3[] = {
259 // ------------ an KERB_RPC_INTERNAL_NAME: HARDENING3.COM -------------------------
260 0x01, 0x00, // (NameType)
261 0x01, 0x00, // (NameCount)
262 0x10, 0x00, 0x02, 0x00, // (Names)
263 // == conformant array ==
264 0x01, 0x00, 0x00, 0x00, // (nitems)
265
266 // = RPC_UNICODE_STRING =
267 0x1c, 0x00, // (Length)
268 0x1e, 0x00, // (MaximumLength)
269 0x14, 0x00, 0x02, 0x00,
270 // == Uni-dimensional Conformant-varying Array ==
271 0x0f, 0x00, 0x00, 0x00, // (maximum count)
272 0x00, 0x00, 0x00, 0x00, // (offset)
273 0x0e, 0x00, 0x00, 0x00, // (length)
274 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00,
275 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00,
276 0x00, 0x00,
277
278 0x00, 0x00
279 };
280 KERB_RPC_INTERNAL_NAME intName = { 0 };
281
282 wStream staticS = { 0 };
283 wStream* s = Stream_StaticInit(&staticS, payload3, sizeof(payload3));
284 if (!ndr_read_KERB_RPC_INTERNAL_NAME(context, s, NULL, &intName) ||
285 !ndr_treat_deferred_read(context, s))
286 goto out;
287 ndr_destroy_KERB_RPC_INTERNAL_NAME(context, NULL, &intName);
288 ndr_context_reset(context);
289 }
290
291 /* ====================================================================== */
292 {
293 retCode = -5;
294 const BYTE payload4[] = {
295 0x03, 0x01, 0x03, 0x01, // unionId / unionId
296 0x04, 0x00, 0x02, 0x00, // (EncryptionKey ptr)
297 0xf8, 0xca, 0x95, 0x11, // (SequenceNumber)
298 0x0c, 0x00, 0x02, 0x00, // (ClientName ptr)
299 0x18, 0x00, 0x02, 0x00, // (ClientRealm ptr)
300 0x20, 0x00, 0x02, 0x00, // (SkewTime ptr)
301 0x00, 0x00, 0x00, 0x00, // (SubKey ptr)
302 0x24, 0x00, 0x02, 0x00, // (AuthData ptr)
303 0x2c, 0x00, 0x02, 0x00, // (GssChecksum ptr)
304 0x07, 0x00, 0x00, 0x00, // (KeyUsage)
305
306 // === EncryptionKey ===
307 0x40, 0xe9, 0x12, 0xdf, // reserved1
308 0x12, 0x00, 0x00, 0x00, // reserved2
309 // KERB_RPC_OCTET_STRING
310 0x4c, 0x00, 0x00, 0x00, // (length)
311 0x08, 0x00, 0x02, 0x00, // (value ptr)
312 // == conformant array ==
313 0x4c, 0x00, 0x00, 0x00, // (length)
314 0xc4, 0x41, 0xee, 0x34, 0x82, 0x2b, 0x29, 0x61, 0xe2, 0x96, 0xb5, 0x75, 0x61, 0x2d,
315 0xbf, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x89, 0x08, 0x60, 0x2e, 0x30, 0x3e, 0xfe, 0x56, 0x11, 0xf0,
317 0x31, 0xf2, 0xd6, 0x2e, 0x3d, 0x33, 0xfe, 0xce, 0x56, 0x12, 0xbf, 0xb2, 0xe5, 0x86,
318 0x29, 0x8d, 0x29, 0x74, 0x1f, 0x8a, 0xf9, 0xb9, 0x8c, 0xd4, 0x86, 0x3a, 0x21, 0x92,
319 0xb2, 0x07, 0x95, 0x4b, 0xea, 0xee,
320
321 //=== ClientName - KERB_RPC_INTERNAL_NAME ===
322 0x01, 0x00, // (NameType)
323 0x01, 0x00, // (NameCount)
324 0x10, 0x00, 0x02, 0x00, // (Names)
325
326 0x01, 0x00, 0x00, 0x00, // (nitems)
327
328 // = RPC_UNICODE_STRING =
329 0x1c, 0x00, // (Length)
330 0x1e, 0x00, // (MaximumLength)
331 0x14, 0x00, 0x02, 0x00, //(Buffer ptr)
332 // == Uni-dimensional Conformant-varying Array ==
333 0x0f, 0x00, 0x00, 0x00, // (maximum count)
334 0x00, 0x00, 0x00, 0x00, // (offset)
335 0x0e, 0x00, 0x00, 0x00, // (length)
336 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00,
337 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00,
338
339 // === ClientRealm - RPC_UNICODE_STRING ===
340 0x1c, 0x00, // (Length)
341 0x1e, 0x00, // (MaximumLength)
342 0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
343 // == Uni-dimensional conformant varying array ==
344 0x0f, 0x00, 0x00, 0x00, // (maximum count)
345 0x00, 0x00, 0x00, 0x00, // (offset)
346 0x0e, 0x00, 0x00, 0x00, // (length)
347 0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00,
348 0x4e, 0x00, 0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00,
349
350 0x00, 0x00, 0x00, 0x00, // padding
351
352 // == SkewTime ==
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354
355 // === AuthData - KERB_ASN1_DATA ==
356 0x00, 0x00, 0x00, 0x00, // (PduType)
357 0x02, 0x00, 0x00, 0x00, // (Length)
358 0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
359 // == conformant array ==
360 0x02, 0x00, 0x00, 0x00, // (nitems)
361 0x30, 0x00, 0x00, 0x00, // (padding)
362
363 // === GssChecksum - KERB_ASN1_DATA ===
364 0x08, 0x00, 0x00, 0x00, // (PduType)
365 0x1b, 0x00, 0x00, 0x00, // (Length)
366 0x30, 0x00, 0x02, 0x00, // (Asn1Buffer)
367 // == conformant array ==
368 0x1b, 0x00, 0x00, 0x00, // (length)
369 0x30, 0x19, 0xa0, 0x03, 0x02, 0x01, 0x07, 0xa1, 0x12, 0x04, 0x10, 0xb9, 0x4f, 0xcd,
370 0xae, 0xd9, 0xa8, 0xff, 0x49, 0x69, 0x5a, 0xd1, 0x1d, 0x38, 0x49, 0xb6, 0x92, 0x00
371 };
372 if (!run_payload(context, payload4, sizeof(payload4)))
373 goto out;
374 }
375
376 {
377 retCode = -6;
378 size_t sizeofPayload4 = 0;
379 BYTE* payload4 = parseHexBlock("03 01 03 01 \
380 04 00 02 00 38 9e ef 6b 0c 00 02 00 18 00 02 00 \
381 20 00 02 00 00 00 00 00 24 00 02 00 2c 00 02 00 \
382 07 00 00 00 13 8a a5 a8 12 00 00 00 20 00 00 00 \
383 08 00 02 00 20 00 00 00 c9 03 42 a8 17 8f d9 c4 \
384 9b d2 c4 6e 73 64 98 7b 90 f5 9a 28 77 8e ca de \
385 29 2e a3 8d 8a 56 36 d5 01 00 01 00 10 00 02 00 \
386 01 00 00 00 1c 00 1e 00 14 00 02 00 0f 00 00 00 \
387 00 00 00 00 0e 00 00 00 41 00 64 00 6d 00 69 00 \
388 6e 00 69 00 73 00 74 00 72 00 61 00 74 00 65 00 \
389 75 00 72 00 1c 00 1e 00 1c 00 02 00 0f 00 00 00 \
390 00 00 00 00 0e 00 00 00 48 00 41 00 52 00 44 00 \
391 45 00 4e 00 49 00 4e 00 47 00 33 00 2e 00 43 00 \
392 4f 00 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 \
393 02 00 00 00 28 00 02 00 02 00 00 00 30 00 00 00 \
394 08 00 00 00 1b 00 00 00 30 00 02 00 1b 00 00 00 \
395 30 19 a0 03 02 01 07 a1 12 04 10 e4 aa ff 2b 93 \
396 97 4c f2 5c 0b 49 85 72 92 94 54 00",
397 &sizeofPayload4);
398 const BOOL rc = run_payload(context, payload4, sizeofPayload4);
399 free(payload4);
400 if (!rc)
401 goto out;
402 }
403
404 /* ============ successful end of test =============== */
405 retCode = 0;
406out:
407 ndr_context_destroy(&context);
408 return retCode;
409}
410
411int TestNdrEar(int argc, char* argv[])
412{
413 const int rc = TestNdrEarWrite(argc, argv);
414 if (rc)
415 return rc;
416 return TestNdrEarRead(argc, argv);
417}
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)