1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/slab.h>
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifs_debug.h"
28#include "cifsproto.h"
29
30
31
32
33
34
35
36
37#define ASN1_UNI 0
38#define ASN1_APL 1
39#define ASN1_CTX 2
40#define ASN1_PRV 3
41
42
43#define ASN1_EOC 0
44#define ASN1_BOL 1
45#define ASN1_INT 2
46#define ASN1_BTS 3
47#define ASN1_OTS 4
48#define ASN1_NUL 5
49#define ASN1_OJI 6
50#define ASN1_OJD 7
51#define ASN1_EXT 8
52#define ASN1_ENUM 10
53#define ASN1_SEQ 16
54#define ASN1_SET 17
55#define ASN1_NUMSTR 18
56#define ASN1_PRNSTR 19
57#define ASN1_TEXSTR 20
58#define ASN1_VIDSTR 21
59#define ASN1_IA5STR 22
60#define ASN1_UNITIM 23
61#define ASN1_GENTIM 24
62#define ASN1_GRASTR 25
63#define ASN1_VISSTR 26
64#define ASN1_GENSTR 27
65
66
67#define ASN1_PRI 0
68#define ASN1_CON 1
69
70
71
72
73#define ASN1_ERR_NOERROR 0
74#define ASN1_ERR_DEC_EMPTY 2
75#define ASN1_ERR_DEC_EOC_MISMATCH 3
76#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
77#define ASN1_ERR_DEC_BADVALUE 5
78
79#define SPNEGO_OID_LEN 7
80#define NTLMSSP_OID_LEN 10
81#define KRB5_OID_LEN 7
82#define KRB5U2U_OID_LEN 8
83#define MSKRB5_OID_LEN 7
84static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
85static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
86static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
87static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
88static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
89
90
91
92
93struct asn1_ctx {
94 int error;
95 unsigned char *pointer;
96 unsigned char *begin;
97 unsigned char *end;
98};
99
100
101
102
103struct asn1_octstr {
104 unsigned char *data;
105 unsigned int len;
106};
107
108static void
109asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
110{
111 ctx->begin = buf;
112 ctx->end = buf + len;
113 ctx->pointer = buf;
114 ctx->error = ASN1_ERR_NOERROR;
115}
116
117static unsigned char
118asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
119{
120 if (ctx->pointer >= ctx->end) {
121 ctx->error = ASN1_ERR_DEC_EMPTY;
122 return 0;
123 }
124 *ch = *(ctx->pointer)++;
125 return 1;
126}
127
128#if 0
129static unsigned char
130asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val)
131{
132 unsigned char ch;
133
134 if (ctx->pointer >= ctx->end) {
135 ctx->error = ASN1_ERR_DEC_EMPTY;
136 return 0;
137 }
138
139 ch = *(ctx->pointer)++;
140 if ((ch) == ASN1_ENUM)
141 *val = *(++(ctx->pointer));
142 else
143 return 0;
144
145 ctx->pointer++;
146 return 1;
147}
148#endif
149
150static unsigned char
151asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
152{
153 unsigned char ch;
154
155 *tag = 0;
156
157 do {
158 if (!asn1_octet_decode(ctx, &ch))
159 return 0;
160 *tag <<= 7;
161 *tag |= ch & 0x7F;
162 } while ((ch & 0x80) == 0x80);
163 return 1;
164}
165
166static unsigned char
167asn1_id_decode(struct asn1_ctx *ctx,
168 unsigned int *cls, unsigned int *con, unsigned int *tag)
169{
170 unsigned char ch;
171
172 if (!asn1_octet_decode(ctx, &ch))
173 return 0;
174
175 *cls = (ch & 0xC0) >> 6;
176 *con = (ch & 0x20) >> 5;
177 *tag = (ch & 0x1F);
178
179 if (*tag == 0x1F) {
180 if (!asn1_tag_decode(ctx, tag))
181 return 0;
182 }
183 return 1;
184}
185
186static unsigned char
187asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
188{
189 unsigned char ch, cnt;
190
191 if (!asn1_octet_decode(ctx, &ch))
192 return 0;
193
194 if (ch == 0x80)
195 *def = 0;
196 else {
197 *def = 1;
198
199 if (ch < 0x80)
200 *len = ch;
201 else {
202 cnt = (unsigned char) (ch & 0x7F);
203 *len = 0;
204
205 while (cnt > 0) {
206 if (!asn1_octet_decode(ctx, &ch))
207 return 0;
208 *len <<= 8;
209 *len |= ch;
210 cnt--;
211 }
212 }
213 }
214
215
216 if (*len > ctx->end - ctx->pointer)
217 return 0;
218
219 return 1;
220}
221
222static unsigned char
223asn1_header_decode(struct asn1_ctx *ctx,
224 unsigned char **eoc,
225 unsigned int *cls, unsigned int *con, unsigned int *tag)
226{
227 unsigned int def = 0;
228 unsigned int len = 0;
229
230 if (!asn1_id_decode(ctx, cls, con, tag))
231 return 0;
232
233 if (!asn1_length_decode(ctx, &def, &len))
234 return 0;
235
236
237 if (*con == ASN1_PRI && !def)
238 return 0;
239
240 if (def)
241 *eoc = ctx->pointer + len;
242 else
243 *eoc = NULL;
244 return 1;
245}
246
247static unsigned char
248asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
249{
250 unsigned char ch;
251
252 if (eoc == NULL) {
253 if (!asn1_octet_decode(ctx, &ch))
254 return 0;
255
256 if (ch != 0x00) {
257 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
258 return 0;
259 }
260
261 if (!asn1_octet_decode(ctx, &ch))
262 return 0;
263
264 if (ch != 0x00) {
265 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
266 return 0;
267 }
268 return 1;
269 } else {
270 if (ctx->pointer != eoc) {
271 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
272 return 0;
273 }
274 return 1;
275 }
276}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400static unsigned char
401asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
402{
403 unsigned char ch;
404
405 *subid = 0;
406
407 do {
408 if (!asn1_octet_decode(ctx, &ch))
409 return 0;
410
411 *subid <<= 7;
412 *subid |= ch & 0x7F;
413 } while ((ch & 0x80) == 0x80);
414 return 1;
415}
416
417static int
418asn1_oid_decode(struct asn1_ctx *ctx,
419 unsigned char *eoc, unsigned long **oid, unsigned int *len)
420{
421 unsigned long subid;
422 unsigned int size;
423 unsigned long *optr;
424
425 size = eoc - ctx->pointer + 1;
426
427
428 if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
429 return 0;
430
431 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
432 if (*oid == NULL)
433 return 0;
434
435 optr = *oid;
436
437 if (!asn1_subid_decode(ctx, &subid)) {
438 kfree(*oid);
439 *oid = NULL;
440 return 0;
441 }
442
443 if (subid < 40) {
444 optr[0] = 0;
445 optr[1] = subid;
446 } else if (subid < 80) {
447 optr[0] = 1;
448 optr[1] = subid - 40;
449 } else {
450 optr[0] = 2;
451 optr[1] = subid - 80;
452 }
453
454 *len = 2;
455 optr += 2;
456
457 while (ctx->pointer < eoc) {
458 if (++(*len) > size) {
459 ctx->error = ASN1_ERR_DEC_BADVALUE;
460 kfree(*oid);
461 *oid = NULL;
462 return 0;
463 }
464
465 if (!asn1_subid_decode(ctx, optr++)) {
466 kfree(*oid);
467 *oid = NULL;
468 return 0;
469 }
470 }
471 return 1;
472}
473
474static int
475compare_oid(unsigned long *oid1, unsigned int oid1len,
476 unsigned long *oid2, unsigned int oid2len)
477{
478 unsigned int i;
479
480 if (oid1len != oid2len)
481 return 0;
482 else {
483 for (i = 0; i < oid1len; i++) {
484 if (oid1[i] != oid2[i])
485 return 0;
486 }
487 return 1;
488 }
489}
490
491
492
493int
494decode_negTokenInit(unsigned char *security_blob, int length,
495 struct TCP_Server_Info *server)
496{
497 struct asn1_ctx ctx;
498 unsigned char *end;
499 unsigned char *sequence_end;
500 unsigned long *oid = NULL;
501 unsigned int cls, con, tag, oidlen, rc;
502
503
504
505 asn1_open(&ctx, security_blob, length);
506
507
508 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
509 cifs_dbg(FYI, "Error decoding negTokenInit header\n");
510 return 0;
511 } else if ((cls != ASN1_APL) || (con != ASN1_CON)
512 || (tag != ASN1_EOC)) {
513 cifs_dbg(FYI, "cls = %d con = %d tag = %d\n", cls, con, tag);
514 return 0;
515 }
516
517
518 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
519 if (rc) {
520 if ((tag == ASN1_OJI) && (con == ASN1_PRI) &&
521 (cls == ASN1_UNI)) {
522 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
523 if (rc) {
524 rc = compare_oid(oid, oidlen, SPNEGO_OID,
525 SPNEGO_OID_LEN);
526 kfree(oid);
527 }
528 } else
529 rc = 0;
530 }
531
532
533 if (!rc) {
534 cifs_dbg(FYI, "Error decoding negTokenInit header\n");
535 return 0;
536 }
537
538
539 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
540 cifs_dbg(FYI, "Error decoding negTokenInit\n");
541 return 0;
542 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
543 || (tag != ASN1_EOC)) {
544 cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
545 cls, con, tag, end, *end);
546 return 0;
547 }
548
549
550 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
551 cifs_dbg(FYI, "Error decoding negTokenInit\n");
552 return 0;
553 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
554 || (tag != ASN1_SEQ)) {
555 cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
556 cls, con, tag, end, *end);
557 return 0;
558 }
559
560
561 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
562 cifs_dbg(FYI, "Error decoding 2nd part of negTokenInit\n");
563 return 0;
564 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
565 || (tag != ASN1_EOC)) {
566 cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
567 cls, con, tag, end, *end);
568 return 0;
569 }
570
571
572 if (asn1_header_decode
573 (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
574 cifs_dbg(FYI, "Error decoding 2nd part of negTokenInit\n");
575 return 0;
576 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
577 || (tag != ASN1_SEQ)) {
578 cifs_dbg(FYI, "cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
579 cls, con, tag, end, *end);
580 return 0;
581 }
582
583
584 while (!asn1_eoc_decode(&ctx, sequence_end)) {
585 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
586 if (!rc) {
587 cifs_dbg(FYI, "Error decoding negTokenInit hdr exit2\n");
588 return 0;
589 }
590 if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
591 if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
592
593 cifs_dbg(FYI, "OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx\n",
594 oidlen, *oid, *(oid + 1), *(oid + 2),
595 *(oid + 3));
596
597 if (compare_oid(oid, oidlen, MSKRB5_OID,
598 MSKRB5_OID_LEN))
599 server->sec_mskerberos = true;
600 else if (compare_oid(oid, oidlen, KRB5U2U_OID,
601 KRB5U2U_OID_LEN))
602 server->sec_kerberosu2u = true;
603 else if (compare_oid(oid, oidlen, KRB5_OID,
604 KRB5_OID_LEN))
605 server->sec_kerberos = true;
606 else if (compare_oid(oid, oidlen, NTLMSSP_OID,
607 NTLMSSP_OID_LEN))
608 server->sec_ntlmssp = true;
609
610 kfree(oid);
611 }
612 } else {
613 cifs_dbg(FYI, "Should be an oid what is going on?\n");
614 }
615 }
616
617
618
619
620
621
622 return 1;
623}
624