GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / fs / cifs / asn1.c
blobdf1237149ff4a9b4f71303053a215a48c7ad4209
1 /*
2 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
3 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
5 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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"
30 /*****************************************************************************
32 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
34 *****************************************************************************/
36 /* Class */
37 #define ASN1_UNI 0 /* Universal */
38 #define ASN1_APL 1 /* Application */
39 #define ASN1_CTX 2 /* Context */
40 #define ASN1_PRV 3 /* Private */
42 /* Tag */
43 #define ASN1_EOC 0 /* End Of Contents or N/A */
44 #define ASN1_BOL 1 /* Boolean */
45 #define ASN1_INT 2 /* Integer */
46 #define ASN1_BTS 3 /* Bit String */
47 #define ASN1_OTS 4 /* Octet String */
48 #define ASN1_NUL 5 /* Null */
49 #define ASN1_OJI 6 /* Object Identifier */
50 #define ASN1_OJD 7 /* Object Description */
51 #define ASN1_EXT 8 /* External */
52 #define ASN1_ENUM 10 /* Enumerated */
53 #define ASN1_SEQ 16 /* Sequence */
54 #define ASN1_SET 17 /* Set */
55 #define ASN1_NUMSTR 18 /* Numerical String */
56 #define ASN1_PRNSTR 19 /* Printable String */
57 #define ASN1_TEXSTR 20 /* Teletext String */
58 #define ASN1_VIDSTR 21 /* Video String */
59 #define ASN1_IA5STR 22 /* IA5 String */
60 #define ASN1_UNITIM 23 /* Universal Time */
61 #define ASN1_GENTIM 24 /* General Time */
62 #define ASN1_GRASTR 25 /* Graphical String */
63 #define ASN1_VISSTR 26 /* Visible String */
64 #define ASN1_GENSTR 27 /* General String */
66 /* Primitive / Constructed methods*/
67 #define ASN1_PRI 0 /* Primitive */
68 #define ASN1_CON 1 /* Constructed */
71 * Error codes.
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
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
84 static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
85 static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
86 static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
87 static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
88 static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
91 * ASN.1 context.
93 struct asn1_ctx {
94 int error; /* Error condition */
95 unsigned char *pointer; /* Octet just to be decoded */
96 unsigned char *begin; /* First octet */
97 unsigned char *end; /* Octet after last octet */
101 * Octet string (not null terminated)
103 struct asn1_octstr {
104 unsigned char *data;
105 unsigned int len;
108 static void
109 asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
111 ctx->begin = buf;
112 ctx->end = buf + len;
113 ctx->pointer = buf;
114 ctx->error = ASN1_ERR_NOERROR;
117 static unsigned char
118 asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
120 if (ctx->pointer >= ctx->end) {
121 ctx->error = ASN1_ERR_DEC_EMPTY;
122 return 0;
124 *ch = *(ctx->pointer)++;
125 return 1;
129 static unsigned char
130 asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
132 unsigned char ch;
134 *tag = 0;
136 do {
137 if (!asn1_octet_decode(ctx, &ch))
138 return 0;
139 *tag <<= 7;
140 *tag |= ch & 0x7F;
141 } while ((ch & 0x80) == 0x80);
142 return 1;
145 static unsigned char
146 asn1_id_decode(struct asn1_ctx *ctx,
147 unsigned int *cls, unsigned int *con, unsigned int *tag)
149 unsigned char ch;
151 if (!asn1_octet_decode(ctx, &ch))
152 return 0;
154 *cls = (ch & 0xC0) >> 6;
155 *con = (ch & 0x20) >> 5;
156 *tag = (ch & 0x1F);
158 if (*tag == 0x1F) {
159 if (!asn1_tag_decode(ctx, tag))
160 return 0;
162 return 1;
165 static unsigned char
166 asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
168 unsigned char ch, cnt;
170 if (!asn1_octet_decode(ctx, &ch))
171 return 0;
173 if (ch == 0x80)
174 *def = 0;
175 else {
176 *def = 1;
178 if (ch < 0x80)
179 *len = ch;
180 else {
181 cnt = (unsigned char) (ch & 0x7F);
182 *len = 0;
184 while (cnt > 0) {
185 if (!asn1_octet_decode(ctx, &ch))
186 return 0;
187 *len <<= 8;
188 *len |= ch;
189 cnt--;
194 /* don't trust len bigger than ctx buffer */
195 if (*len > ctx->end - ctx->pointer)
196 return 0;
198 return 1;
201 static unsigned char
202 asn1_header_decode(struct asn1_ctx *ctx,
203 unsigned char **eoc,
204 unsigned int *cls, unsigned int *con, unsigned int *tag)
206 unsigned int def = 0;
207 unsigned int len = 0;
209 if (!asn1_id_decode(ctx, cls, con, tag))
210 return 0;
212 if (!asn1_length_decode(ctx, &def, &len))
213 return 0;
215 /* primitive shall be definite, indefinite shall be constructed */
216 if (*con == ASN1_PRI && !def)
217 return 0;
219 if (def)
220 *eoc = ctx->pointer + len;
221 else
222 *eoc = NULL;
223 return 1;
226 static unsigned char
227 asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
229 unsigned char ch;
231 if (eoc == NULL) {
232 if (!asn1_octet_decode(ctx, &ch))
233 return 0;
235 if (ch != 0x00) {
236 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
237 return 0;
240 if (!asn1_octet_decode(ctx, &ch))
241 return 0;
243 if (ch != 0x00) {
244 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
245 return 0;
247 return 1;
248 } else {
249 if (ctx->pointer != eoc) {
250 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
251 return 0;
253 return 1;
257 /* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
258 unsigned char *eoc)
260 ctx->pointer = eoc;
261 return 1;
264 static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
265 unsigned char *eoc, long *integer)
267 unsigned char ch;
268 unsigned int len;
270 if (!asn1_octet_decode(ctx, &ch))
271 return 0;
273 *integer = (signed char) ch;
274 len = 1;
276 while (ctx->pointer < eoc) {
277 if (++len > sizeof(long)) {
278 ctx->error = ASN1_ERR_DEC_BADVALUE;
279 return 0;
282 if (!asn1_octet_decode(ctx, &ch))
283 return 0;
285 *integer <<= 8;
286 *integer |= ch;
288 return 1;
291 static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
292 unsigned char *eoc,
293 unsigned int *integer)
295 unsigned char ch;
296 unsigned int len;
298 if (!asn1_octet_decode(ctx, &ch))
299 return 0;
301 *integer = ch;
302 if (ch == 0)
303 len = 0;
304 else
305 len = 1;
307 while (ctx->pointer < eoc) {
308 if (++len > sizeof(unsigned int)) {
309 ctx->error = ASN1_ERR_DEC_BADVALUE;
310 return 0;
313 if (!asn1_octet_decode(ctx, &ch))
314 return 0;
316 *integer <<= 8;
317 *integer |= ch;
319 return 1;
322 static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
323 unsigned char *eoc,
324 unsigned long *integer)
326 unsigned char ch;
327 unsigned int len;
329 if (!asn1_octet_decode(ctx, &ch))
330 return 0;
332 *integer = ch;
333 if (ch == 0)
334 len = 0;
335 else
336 len = 1;
338 while (ctx->pointer < eoc) {
339 if (++len > sizeof(unsigned long)) {
340 ctx->error = ASN1_ERR_DEC_BADVALUE;
341 return 0;
344 if (!asn1_octet_decode(ctx, &ch))
345 return 0;
347 *integer <<= 8;
348 *integer |= ch;
350 return 1;
353 static unsigned char
354 asn1_octets_decode(struct asn1_ctx *ctx,
355 unsigned char *eoc,
356 unsigned char **octets, unsigned int *len)
358 unsigned char *ptr;
360 *len = 0;
362 *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
363 if (*octets == NULL) {
364 return 0;
367 ptr = *octets;
368 while (ctx->pointer < eoc) {
369 if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
370 kfree(*octets);
371 *octets = NULL;
372 return 0;
374 (*len)++;
376 return 1;
377 } */
379 static unsigned char
380 asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
382 unsigned char ch;
384 *subid = 0;
386 do {
387 if (!asn1_octet_decode(ctx, &ch))
388 return 0;
390 *subid <<= 7;
391 *subid |= ch & 0x7F;
392 } while ((ch & 0x80) == 0x80);
393 return 1;
396 static int
397 asn1_oid_decode(struct asn1_ctx *ctx,
398 unsigned char *eoc, unsigned long **oid, unsigned int *len)
400 unsigned long subid;
401 unsigned int size;
402 unsigned long *optr;
404 size = eoc - ctx->pointer + 1;
406 /* first subid actually encodes first two subids */
407 if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
408 return 0;
410 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
411 if (*oid == NULL)
412 return 0;
414 optr = *oid;
416 if (!asn1_subid_decode(ctx, &subid)) {
417 kfree(*oid);
418 *oid = NULL;
419 return 0;
422 if (subid < 40) {
423 optr[0] = 0;
424 optr[1] = subid;
425 } else if (subid < 80) {
426 optr[0] = 1;
427 optr[1] = subid - 40;
428 } else {
429 optr[0] = 2;
430 optr[1] = subid - 80;
433 *len = 2;
434 optr += 2;
436 while (ctx->pointer < eoc) {
437 if (++(*len) > size) {
438 ctx->error = ASN1_ERR_DEC_BADVALUE;
439 kfree(*oid);
440 *oid = NULL;
441 return 0;
444 if (!asn1_subid_decode(ctx, optr++)) {
445 kfree(*oid);
446 *oid = NULL;
447 return 0;
450 return 1;
453 static int
454 compare_oid(unsigned long *oid1, unsigned int oid1len,
455 unsigned long *oid2, unsigned int oid2len)
457 unsigned int i;
459 if (oid1len != oid2len)
460 return 0;
461 else {
462 for (i = 0; i < oid1len; i++) {
463 if (oid1[i] != oid2[i])
464 return 0;
466 return 1;
470 /* BB check for endian conversion issues here */
473 decode_negTokenInit(unsigned char *security_blob, int length,
474 struct TCP_Server_Info *server)
476 struct asn1_ctx ctx;
477 unsigned char *end;
478 unsigned char *sequence_end;
479 unsigned long *oid = NULL;
480 unsigned int cls, con, tag, oidlen, rc;
482 /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
484 asn1_open(&ctx, security_blob, length);
486 /* GSSAPI header */
487 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
488 cFYI(1, "Error decoding negTokenInit header");
489 return 0;
490 } else if ((cls != ASN1_APL) || (con != ASN1_CON)
491 || (tag != ASN1_EOC)) {
492 cFYI(1, "cls = %d con = %d tag = %d", cls, con, tag);
493 return 0;
496 /* Check for SPNEGO OID -- remember to free obj->oid */
497 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
498 if (rc) {
499 if ((tag == ASN1_OJI) && (con == ASN1_PRI) &&
500 (cls == ASN1_UNI)) {
501 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
502 if (rc) {
503 rc = compare_oid(oid, oidlen, SPNEGO_OID,
504 SPNEGO_OID_LEN);
505 kfree(oid);
507 } else
508 rc = 0;
511 /* SPNEGO OID not present or garbled -- bail out */
512 if (!rc) {
513 cFYI(1, "Error decoding negTokenInit header");
514 return 0;
517 /* SPNEGO */
518 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
519 cFYI(1, "Error decoding negTokenInit");
520 return 0;
521 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
522 || (tag != ASN1_EOC)) {
523 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
524 cls, con, tag, end, *end);
525 return 0;
528 /* negTokenInit */
529 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
530 cFYI(1, "Error decoding negTokenInit");
531 return 0;
532 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
533 || (tag != ASN1_SEQ)) {
534 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
535 cls, con, tag, end, *end);
536 return 0;
539 /* sequence */
540 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
541 cFYI(1, "Error decoding 2nd part of negTokenInit");
542 return 0;
543 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
544 || (tag != ASN1_EOC)) {
545 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
546 cls, con, tag, end, *end);
547 return 0;
550 /* sequence of */
551 if (asn1_header_decode
552 (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
553 cFYI(1, "Error decoding 2nd part of negTokenInit");
554 return 0;
555 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
556 || (tag != ASN1_SEQ)) {
557 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
558 cls, con, tag, end, *end);
559 return 0;
562 /* list of security mechanisms */
563 while (!asn1_eoc_decode(&ctx, sequence_end)) {
564 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
565 if (!rc) {
566 cFYI(1, "Error decoding negTokenInit hdr exit2");
567 return 0;
569 if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
570 if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
572 cFYI(1, "OID len = %d oid = 0x%lx 0x%lx "
573 "0x%lx 0x%lx", oidlen, *oid,
574 *(oid + 1), *(oid + 2), *(oid + 3));
576 if (compare_oid(oid, oidlen, MSKRB5_OID,
577 MSKRB5_OID_LEN))
578 server->sec_mskerberos = true;
579 else if (compare_oid(oid, oidlen, KRB5U2U_OID,
580 KRB5U2U_OID_LEN))
581 server->sec_kerberosu2u = true;
582 else if (compare_oid(oid, oidlen, KRB5_OID,
583 KRB5_OID_LEN))
584 server->sec_kerberos = true;
585 else if (compare_oid(oid, oidlen, NTLMSSP_OID,
586 NTLMSSP_OID_LEN))
587 server->sec_ntlmssp = true;
589 kfree(oid);
591 } else {
592 cFYI(1, "Should be an oid what is going on?");
596 /* mechlistMIC */
597 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
598 /* Check if we have reached the end of the blob, but with
599 no mechListMic (e.g. NTLMSSP instead of KRB5) */
600 if (ctx.error == ASN1_ERR_DEC_EMPTY)
601 goto decode_negtoken_exit;
602 cFYI(1, "Error decoding last part negTokenInit exit3");
603 return 0;
604 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
605 /* tag = 3 indicating mechListMIC */
606 cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
607 cls, con, tag, end, *end);
608 return 0;
611 /* sequence */
612 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
613 cFYI(1, "Error decoding last part negTokenInit exit5");
614 return 0;
615 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
616 || (tag != ASN1_SEQ)) {
617 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
618 cls, con, tag, end, *end);
621 /* sequence of */
622 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
623 cFYI(1, "Error decoding last part negTokenInit exit 7");
624 return 0;
625 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
626 cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
627 cls, con, tag, end, *end);
628 return 0;
631 /* general string */
632 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
633 cFYI(1, "Error decoding last part negTokenInit exit9");
634 return 0;
635 } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
636 || (tag != ASN1_GENSTR)) {
637 cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
638 cls, con, tag, end, *end);
639 return 0;
641 cFYI(1, "Need to call asn1_octets_decode() function for %s",
642 ctx.pointer); /* is this UTF-8 or ASCII? */
643 decode_negtoken_exit:
644 return 1;