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