Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13 618 lines 14 kB view raw
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 4 * 5 * Copyright (c) 2000 RP Internet (www.rpi.net.au). 6 * 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 18 */ 19 20#include <linux/config.h> 21#include <linux/module.h> 22#include <linux/types.h> 23#include <linux/kernel.h> 24#include <linux/mm.h> 25#include <linux/slab.h> 26#include "cifspdu.h" 27#include "cifsglob.h" 28#include "cifs_debug.h" 29#include "cifsproto.h" 30 31/***************************************************************************** 32 * 33 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) 34 * 35 *****************************************************************************/ 36 37/* Class */ 38#define ASN1_UNI 0 /* Universal */ 39#define ASN1_APL 1 /* Application */ 40#define ASN1_CTX 2 /* Context */ 41#define ASN1_PRV 3 /* Private */ 42 43/* Tag */ 44#define ASN1_EOC 0 /* End Of Contents or N/A */ 45#define ASN1_BOL 1 /* Boolean */ 46#define ASN1_INT 2 /* Integer */ 47#define ASN1_BTS 3 /* Bit String */ 48#define ASN1_OTS 4 /* Octet String */ 49#define ASN1_NUL 5 /* Null */ 50#define ASN1_OJI 6 /* Object Identifier */ 51#define ASN1_OJD 7 /* Object Description */ 52#define ASN1_EXT 8 /* External */ 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 */ 65 66/* Primitive / Constructed methods*/ 67#define ASN1_PRI 0 /* Primitive */ 68#define ASN1_CON 1 /* Constructed */ 69 70/* 71 * Error codes. 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 81static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; 82static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; 83 84/* 85 * ASN.1 context. 86 */ 87struct asn1_ctx { 88 int error; /* Error condition */ 89 unsigned char *pointer; /* Octet just to be decoded */ 90 unsigned char *begin; /* First octet */ 91 unsigned char *end; /* Octet after last octet */ 92}; 93 94/* 95 * Octet string (not null terminated) 96 */ 97struct asn1_octstr { 98 unsigned char *data; 99 unsigned int len; 100}; 101 102static void 103asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len) 104{ 105 ctx->begin = buf; 106 ctx->end = buf + len; 107 ctx->pointer = buf; 108 ctx->error = ASN1_ERR_NOERROR; 109} 110 111static unsigned char 112asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) 113{ 114 if (ctx->pointer >= ctx->end) { 115 ctx->error = ASN1_ERR_DEC_EMPTY; 116 return 0; 117 } 118 *ch = *(ctx->pointer)++; 119 return 1; 120} 121 122static unsigned char 123asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) 124{ 125 unsigned char ch; 126 127 *tag = 0; 128 129 do { 130 if (!asn1_octet_decode(ctx, &ch)) 131 return 0; 132 *tag <<= 7; 133 *tag |= ch & 0x7F; 134 } while ((ch & 0x80) == 0x80); 135 return 1; 136} 137 138static unsigned char 139asn1_id_decode(struct asn1_ctx *ctx, 140 unsigned int *cls, unsigned int *con, unsigned int *tag) 141{ 142 unsigned char ch; 143 144 if (!asn1_octet_decode(ctx, &ch)) 145 return 0; 146 147 *cls = (ch & 0xC0) >> 6; 148 *con = (ch & 0x20) >> 5; 149 *tag = (ch & 0x1F); 150 151 if (*tag == 0x1F) { 152 if (!asn1_tag_decode(ctx, tag)) 153 return 0; 154 } 155 return 1; 156} 157 158static unsigned char 159asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) 160{ 161 unsigned char ch, cnt; 162 163 if (!asn1_octet_decode(ctx, &ch)) 164 return 0; 165 166 if (ch == 0x80) 167 *def = 0; 168 else { 169 *def = 1; 170 171 if (ch < 0x80) 172 *len = ch; 173 else { 174 cnt = (unsigned char) (ch & 0x7F); 175 *len = 0; 176 177 while (cnt > 0) { 178 if (!asn1_octet_decode(ctx, &ch)) 179 return 0; 180 *len <<= 8; 181 *len |= ch; 182 cnt--; 183 } 184 } 185 } 186 return 1; 187} 188 189static unsigned char 190asn1_header_decode(struct asn1_ctx *ctx, 191 unsigned char **eoc, 192 unsigned int *cls, unsigned int *con, unsigned int *tag) 193{ 194 unsigned int def, len; 195 196 if (!asn1_id_decode(ctx, cls, con, tag)) 197 return 0; 198 199 if (!asn1_length_decode(ctx, &def, &len)) 200 return 0; 201 202 if (def) 203 *eoc = ctx->pointer + len; 204 else 205 *eoc = NULL; 206 return 1; 207} 208 209static unsigned char 210asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) 211{ 212 unsigned char ch; 213 214 if (eoc == NULL) { 215 if (!asn1_octet_decode(ctx, &ch)) 216 return 0; 217 218 if (ch != 0x00) { 219 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; 220 return 0; 221 } 222 223 if (!asn1_octet_decode(ctx, &ch)) 224 return 0; 225 226 if (ch != 0x00) { 227 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; 228 return 0; 229 } 230 return 1; 231 } else { 232 if (ctx->pointer != eoc) { 233 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH; 234 return 0; 235 } 236 return 1; 237 } 238} 239 240/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx, 241 unsigned char *eoc) 242{ 243 ctx->pointer = eoc; 244 return 1; 245} 246 247static unsigned char asn1_long_decode(struct asn1_ctx *ctx, 248 unsigned char *eoc, long *integer) 249{ 250 unsigned char ch; 251 unsigned int len; 252 253 if (!asn1_octet_decode(ctx, &ch)) 254 return 0; 255 256 *integer = (signed char) ch; 257 len = 1; 258 259 while (ctx->pointer < eoc) { 260 if (++len > sizeof(long)) { 261 ctx->error = ASN1_ERR_DEC_BADVALUE; 262 return 0; 263 } 264 265 if (!asn1_octet_decode(ctx, &ch)) 266 return 0; 267 268 *integer <<= 8; 269 *integer |= ch; 270 } 271 return 1; 272} 273 274static unsigned char asn1_uint_decode(struct asn1_ctx *ctx, 275 unsigned char *eoc, 276 unsigned int *integer) 277{ 278 unsigned char ch; 279 unsigned int len; 280 281 if (!asn1_octet_decode(ctx, &ch)) 282 return 0; 283 284 *integer = ch; 285 if (ch == 0) 286 len = 0; 287 else 288 len = 1; 289 290 while (ctx->pointer < eoc) { 291 if (++len > sizeof(unsigned int)) { 292 ctx->error = ASN1_ERR_DEC_BADVALUE; 293 return 0; 294 } 295 296 if (!asn1_octet_decode(ctx, &ch)) 297 return 0; 298 299 *integer <<= 8; 300 *integer |= ch; 301 } 302 return 1; 303} 304 305static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, 306 unsigned char *eoc, 307 unsigned long *integer) 308{ 309 unsigned char ch; 310 unsigned int len; 311 312 if (!asn1_octet_decode(ctx, &ch)) 313 return 0; 314 315 *integer = ch; 316 if (ch == 0) 317 len = 0; 318 else 319 len = 1; 320 321 while (ctx->pointer < eoc) { 322 if (++len > sizeof(unsigned long)) { 323 ctx->error = ASN1_ERR_DEC_BADVALUE; 324 return 0; 325 } 326 327 if (!asn1_octet_decode(ctx, &ch)) 328 return 0; 329 330 *integer <<= 8; 331 *integer |= ch; 332 } 333 return 1; 334} 335 336static unsigned char 337asn1_octets_decode(struct asn1_ctx *ctx, 338 unsigned char *eoc, 339 unsigned char **octets, unsigned int *len) 340{ 341 unsigned char *ptr; 342 343 *len = 0; 344 345 *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); 346 if (*octets == NULL) { 347 return 0; 348 } 349 350 ptr = *octets; 351 while (ctx->pointer < eoc) { 352 if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) { 353 kfree(*octets); 354 *octets = NULL; 355 return 0; 356 } 357 (*len)++; 358 } 359 return 1; 360} */ 361 362static unsigned char 363asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid) 364{ 365 unsigned char ch; 366 367 *subid = 0; 368 369 do { 370 if (!asn1_octet_decode(ctx, &ch)) 371 return 0; 372 373 *subid <<= 7; 374 *subid |= ch & 0x7F; 375 } while ((ch & 0x80) == 0x80); 376 return 1; 377} 378 379static int 380asn1_oid_decode(struct asn1_ctx *ctx, 381 unsigned char *eoc, unsigned long **oid, unsigned int *len) 382{ 383 unsigned long subid; 384 unsigned int size; 385 unsigned long *optr; 386 387 size = eoc - ctx->pointer + 1; 388 *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); 389 if (*oid == NULL) { 390 return 0; 391 } 392 393 optr = *oid; 394 395 if (!asn1_subid_decode(ctx, &subid)) { 396 kfree(*oid); 397 *oid = NULL; 398 return 0; 399 } 400 401 if (subid < 40) { 402 optr[0] = 0; 403 optr[1] = subid; 404 } else if (subid < 80) { 405 optr[0] = 1; 406 optr[1] = subid - 40; 407 } else { 408 optr[0] = 2; 409 optr[1] = subid - 80; 410 } 411 412 *len = 2; 413 optr += 2; 414 415 while (ctx->pointer < eoc) { 416 if (++(*len) > size) { 417 ctx->error = ASN1_ERR_DEC_BADVALUE; 418 kfree(*oid); 419 *oid = NULL; 420 return 0; 421 } 422 423 if (!asn1_subid_decode(ctx, optr++)) { 424 kfree(*oid); 425 *oid = NULL; 426 return 0; 427 } 428 } 429 return 1; 430} 431 432static int 433compare_oid(unsigned long *oid1, unsigned int oid1len, 434 unsigned long *oid2, unsigned int oid2len) 435{ 436 unsigned int i; 437 438 if (oid1len != oid2len) 439 return 0; 440 else { 441 for (i = 0; i < oid1len; i++) { 442 if (oid1[i] != oid2[i]) 443 return 0; 444 } 445 return 1; 446 } 447} 448 449 /* BB check for endian conversion issues here */ 450 451int 452decode_negTokenInit(unsigned char *security_blob, int length, 453 enum securityEnum *secType) 454{ 455 struct asn1_ctx ctx; 456 unsigned char *end; 457 unsigned char *sequence_end; 458 unsigned long *oid = NULL; 459 unsigned int cls, con, tag, oidlen, rc; 460 int use_ntlmssp = FALSE; 461 462 *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */ 463 464 /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ 465 466 asn1_open(&ctx, security_blob, length); 467 468 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 469 cFYI(1, ("Error decoding negTokenInit header ")); 470 return 0; 471 } else if ((cls != ASN1_APL) || (con != ASN1_CON) 472 || (tag != ASN1_EOC)) { 473 cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); 474 return 0; 475 } else { 476 /* remember to free obj->oid */ 477 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 478 if (rc) { 479 if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) { 480 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); 481 if (rc) { 482 rc = compare_oid(oid, oidlen, 483 SPNEGO_OID, 484 SPNEGO_OID_LEN); 485 kfree(oid); 486 } 487 } else 488 rc = 0; 489 } 490 491 if (!rc) { 492 cFYI(1, ("Error decoding negTokenInit header")); 493 return 0; 494 } 495 496 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 497 cFYI(1, ("Error decoding negTokenInit ")); 498 return 0; 499 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 500 || (tag != ASN1_EOC)) { 501 cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0", 502 cls, con, tag, end, *end)); 503 return 0; 504 } 505 506 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 507 cFYI(1, ("Error decoding negTokenInit ")); 508 return 0; 509 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 510 || (tag != ASN1_SEQ)) { 511 cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1", 512 cls, con, tag, end, *end)); 513 return 0; 514 } 515 516 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 517 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 518 return 0; 519 } else if ((cls != ASN1_CTX) || (con != ASN1_CON) 520 || (tag != ASN1_EOC)) { 521 cFYI(1, 522 ("cls = %d con = %d tag = %d end = %p (%d) exit 0", 523 cls, con, tag, end, *end)); 524 return 0; 525 } 526 527 if (asn1_header_decode 528 (&ctx, &sequence_end, &cls, &con, &tag) == 0) { 529 cFYI(1, ("Error decoding 2nd part of negTokenInit ")); 530 return 0; 531 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 532 || (tag != ASN1_SEQ)) { 533 cFYI(1, 534 ("cls = %d con = %d tag = %d end = %p (%d) exit 1", 535 cls, con, tag, end, *end)); 536 return 0; 537 } 538 539 while (!asn1_eoc_decode(&ctx, sequence_end)) { 540 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); 541 if (!rc) { 542 cFYI(1, 543 ("Error 1 decoding negTokenInit header exit 2")); 544 return 0; 545 } 546 if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { 547 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); 548 if(rc) { 549 cFYI(1, 550 ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx", 551 oidlen, *oid, *(oid + 1), *(oid + 2), 552 *(oid + 3))); 553 rc = compare_oid(oid, oidlen, NTLMSSP_OID, 554 NTLMSSP_OID_LEN); 555 if(oid) 556 kfree(oid); 557 if (rc) 558 use_ntlmssp = TRUE; 559 } 560 } else { 561 cFYI(1,("This should be an oid what is going on? ")); 562 } 563 } 564 565 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 566 cFYI(1, 567 ("Error decoding last part of negTokenInit exit 3")); 568 return 0; 569 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ 570 cFYI(1, 571 ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", 572 cls, con, tag, end, *end)); 573 return 0; 574 } 575 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 576 cFYI(1, 577 ("Error decoding last part of negTokenInit exit 5")); 578 return 0; 579 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 580 || (tag != ASN1_SEQ)) { 581 cFYI(1, 582 ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", 583 cls, con, tag, end, *end)); 584 } 585 586 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 587 cFYI(1, 588 ("Error decoding last part of negTokenInit exit 7")); 589 return 0; 590 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { 591 cFYI(1, 592 ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", 593 cls, con, tag, end, *end)); 594 return 0; 595 } 596 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 597 cFYI(1, 598 ("Error decoding last part of negTokenInit exit 9")); 599 return 0; 600 } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) 601 || (tag != ASN1_GENSTR)) { 602 cFYI(1, 603 ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)", 604 cls, con, tag, end, *end)); 605 return 0; 606 } 607 cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ 608 } 609 610 /* if (use_kerberos) 611 *secType = Kerberos 612 else */ 613 if (use_ntlmssp) { 614 *secType = NTLMSSP; 615 } 616 617 return 1; 618}