FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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 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;
369out:
370 free(payload4);
371 ndr_context_destroy(&context);
372 return retCode;
373}
374
375int 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)