Annotation of embedaddon/strongswan/src/libstrongswan/asn1/asn1_parser.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2006 Martin Will
                      3:  * Copyright (C) 2000-2017 Andreas Steffen
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include <stdio.h>
                     18: #include <string.h>
                     19: #include <time.h>
                     20: 
                     21: #include <utils/debug.h>
                     22: 
                     23: #include "asn1.h"
                     24: #include "asn1_parser.h"
                     25: 
                     26: #define ASN1_MAX_LEVEL 10
                     27: 
                     28: typedef struct private_asn1_parser_t private_asn1_parser_t;
                     29: 
                     30: /**
                     31:  * Private data of an asn1_cxt_t object.
                     32:  */
                     33: struct private_asn1_parser_t {
                     34:        /**
                     35:         * Public interface.
                     36:         */
                     37:        asn1_parser_t public;
                     38: 
                     39:        /**
                     40:         * Syntax definition of ASN.1 object
                     41:         */
                     42:        asn1Object_t const *objects;
                     43: 
                     44:        /**
                     45:         * Current syntax definition line
                     46:         */
                     47:        int line;
                     48: 
                     49:        /**
                     50:         * Current stat of the parsing operation
                     51:         */
                     52:        bool success;
                     53: 
                     54:        /**
                     55:         * Declare object data as private - use debug level 4 to log it
                     56:         */
                     57:        bool private;
                     58: 
                     59:        /**
                     60:         * Top-most type is implicit - ignore it
                     61:         */
                     62:        bool implicit;
                     63: 
                     64:        /**
                     65:         * Top-most parsing level - defaults to 0
                     66:         */
                     67:        u_int level0;
                     68: 
                     69:        /**
                     70:         * Jump back address for loops for each level
                     71:         */
                     72:        int loopAddr[ASN1_MAX_LEVEL + 1];
                     73: 
                     74:        /**
                     75:         * Current parsing pointer for each level
                     76:         */
                     77:        chunk_t blobs[ASN1_MAX_LEVEL + 2];
                     78: 
                     79:        /**
                     80:         * Parsing a CHOICE on the current level ?
                     81:         */
                     82:        bool choice[ASN1_MAX_LEVEL + 2];
                     83: 
                     84: };
                     85: 
                     86: METHOD(asn1_parser_t, iterate, bool,
                     87:        private_asn1_parser_t *this, int *objectID, chunk_t *object)
                     88: {
                     89:        chunk_t *blob, *blob1, blob_ori;
                     90:        u_char *start_ptr;
                     91:        u_int level;
                     92:        asn1Object_t obj;
                     93: 
                     94:        *object = chunk_empty;
                     95: 
                     96:        /* Advance to the next object syntax definition line */
                     97:        obj = this->objects[++(this->line)];
                     98: 
                     99:        /* Terminate if the end of the object syntax definition has been reached */
                    100:        if (obj.flags & ASN1_EXIT)
                    101:        {
                    102:                return FALSE;
                    103:        }
                    104: 
                    105:        if (obj.flags & ASN1_END)  /* end of loop or choice or option found */
                    106:        {
                    107:                if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
                    108:                {
                    109:                        this->line = this->loopAddr[obj.level]; /* another iteration */
                    110:                        obj = this->objects[this->line];
                    111:                }
                    112:                else
                    113:                {
                    114:                        this->loopAddr[obj.level] = 0;           /* exit loop */
                    115: 
                    116:                        if (obj.flags & ASN1_CHOICE) /* end of choices */
                    117:                        {
                    118:                                if (this->choice[obj.level+1])
                    119:                                {
                    120:                                        DBG1(DBG_ASN, "L%d - %s:  incorrect choice encoding",
                    121:                                                this->level0 + obj.level, obj.name);
                    122:                                        this->success = FALSE;
                    123:                                        goto end;
                    124:                                }
                    125:                        }
                    126: 
                    127:                        if (obj.flags & ASN1_CH) /* end of choice */
                    128:                        {
                    129:                                /* parsed a valid choice */
                    130:                                this->choice[obj.level] = FALSE;
                    131: 
                    132:                                /* advance to end of choices */
                    133:                                do
                    134:                                {
                    135:                                        this->line++;
                    136:                                }
                    137:                                while (!((this->objects[this->line].flags & ASN1_END) &&
                    138:                                                 (this->objects[this->line].flags & ASN1_CHOICE) &&
                    139:                                                 (this->objects[this->line].level == obj.level-1)));
                    140:                                this->line--;
                    141:                        }
                    142: 
                    143:                        goto end;
                    144:                }
                    145:        }
                    146: 
                    147:        level = this->level0 + obj.level;
                    148:        blob = this->blobs + obj.level;
                    149:        blob_ori = *blob;
                    150:        blob1 = blob + 1;
                    151:        start_ptr = blob->ptr;
                    152: 
                    153:        /* handle ASN.1 defaults values */
                    154:        if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
                    155:        {
                    156:                /* field is missing */
                    157:                DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
                    158:                if (obj.type & ASN1_CONSTRUCTED)
                    159:                {
                    160:                        this->line++ ;  /* skip context-specific tag */
                    161:                }
                    162:                goto end;
                    163:        }
                    164: 
                    165:        /* handle ASN.1 options */
                    166:        if ((obj.flags & ASN1_OPT)
                    167:                        && (blob->len == 0 || *start_ptr != obj.type))
                    168:        {
                    169:                /* advance to end of missing option field */
                    170:                do
                    171:                {
                    172:                        this->line++;
                    173:                }
                    174:                while (!((this->objects[this->line].flags & ASN1_END) &&
                    175:                                 (this->objects[this->line].level == obj.level)));
                    176:                goto end;
                    177:        }
                    178: 
                    179:        /* an ASN.1 object must possess at least a tag and length field */
                    180:        if (blob->len < 2)
                    181:        {
                    182:                DBG1(DBG_ASN, "L%d - %s:  ASN.1 object smaller than 2 octets",
                    183:                                        level, obj.name);
                    184:                this->success = FALSE;
                    185:                goto end;
                    186:        }
                    187: 
                    188:        blob1->len = asn1_length(blob);
                    189: 
                    190:        if (blob1->len == ASN1_INVALID_LENGTH)
                    191:        {
                    192:                DBG1(DBG_ASN, "L%d - %s:  length of ASN.1 object invalid or too large",
                    193:                                        level, obj.name);
                    194:                this->success = FALSE;
                    195:                goto end;
                    196:        }
                    197: 
                    198:        blob1->ptr = blob->ptr;
                    199:        blob->ptr += blob1->len;
                    200:        blob->len -= blob1->len;
                    201: 
                    202:        /* handle ASN.1 choice without explicit context encoding */
                    203:        if ((obj.flags & ASN1_CHOICE) && obj.type == ASN1_EOC)
                    204:        {
                    205:                DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
                    206:                this->choice[obj.level+1] = TRUE;
                    207:                *blob1 = blob_ori;
                    208:                goto end;
                    209:        }
                    210: 
                    211:        /* return raw ASN.1 object without prior type checking */
                    212:        if (obj.flags & ASN1_RAW)
                    213:        {
                    214:                DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
                    215:                object->ptr = start_ptr;
                    216:                object->len = (size_t)(blob->ptr - start_ptr);
                    217:                goto end;
                    218:        }
                    219: 
                    220:        if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
                    221:        {
                    222:                DBG2(DBG_ASN, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
                    223:                                        level, obj.name, obj.type, *start_ptr);
                    224:                DBG3(DBG_ASN, "%b", start_ptr, (u_int)(blob->ptr - start_ptr));
                    225:                this->success = FALSE;
                    226:                goto end;
                    227:        }
                    228: 
                    229:        DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
                    230: 
                    231:        /* In case of "SEQUENCE OF" or "SET OF" start a loop */
                    232:        if (obj.flags & ASN1_LOOP)
                    233:        {
                    234:                if (blob1->len > 0)
                    235:                {
                    236:                        /* at least one item, start the loop */
                    237:                        this->loopAddr[obj.level] = this->line + 1;
                    238:                }
                    239:                else
                    240:                {
                    241:                        /* no items, advance directly to end of loop */
                    242:                        do
                    243:                        {
                    244:                                this->line++;
                    245:                        }
                    246:                        while (!((this->objects[this->line].flags & ASN1_END) &&
                    247:                                         (this->objects[this->line].level == obj.level)));
                    248:                        goto end;
                    249:                }
                    250:        }
                    251: 
                    252:        /* In case of a "CHOICE" start to scan for exactly one valid choice */
                    253:        if (obj.flags & ASN1_CHOICE)
                    254:        {
                    255:                if (blob1->len == 0)
                    256:                {
                    257:                        DBG1(DBG_ASN, "L%d - %s:  contains no choice", level, obj.name);
                    258:                        this->success = FALSE;
                    259:                        goto end;
                    260:                }
                    261:                this->choice[obj.level+1] = TRUE;
                    262:        }
                    263: 
                    264:        if (obj.flags & ASN1_OBJ)
                    265:        {
                    266:                object->ptr = start_ptr;
                    267:                object->len = (size_t)(blob->ptr - start_ptr);
                    268:                if (this->private)
                    269:                {
                    270:                        DBG4(DBG_ASN, "%B", object);
                    271:                }
                    272:                else
                    273:                {
                    274:                        DBG3(DBG_ASN, "%B", object);
                    275:                }
                    276:        }
                    277:        else if (obj.flags & ASN1_BODY)
                    278:        {
                    279:                *object = *blob1;
                    280:                asn1_debug_simple_object(*object, obj.type, this->private);
                    281:        }
                    282: 
                    283: end:
                    284:        *objectID = this->line;
                    285:        return this->success;
                    286: }
                    287: 
                    288: METHOD(asn1_parser_t, get_level, u_int,
                    289: private_asn1_parser_t *this)
                    290: {
                    291:        return this->level0 + this->objects[this->line].level;
                    292: }
                    293: 
                    294: METHOD(asn1_parser_t, set_top_level, void,
                    295:        private_asn1_parser_t *this, u_int level0)
                    296: {
                    297:        this->level0 = level0;
                    298: }
                    299: 
                    300: METHOD(asn1_parser_t, set_flags, void,
                    301:        private_asn1_parser_t *this, bool implicit, bool private)
                    302: {
                    303:        this->implicit = implicit;
                    304:        this->private = private;
                    305: }
                    306: 
                    307: METHOD(asn1_parser_t, success, bool,
                    308:        private_asn1_parser_t *this)
                    309: {
                    310:        return this->success;
                    311: }
                    312: 
                    313: METHOD(asn1_parser_t, destroy, void,
                    314:        private_asn1_parser_t *this)
                    315: {
                    316:        free(this);
                    317: }
                    318: 
                    319: /**
                    320:  * Defined in header.
                    321:  */
                    322: asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
                    323: {
                    324:        private_asn1_parser_t *this;
                    325: 
                    326:        INIT(this,
                    327:                .public = {
                    328:                        .iterate = _iterate,
                    329:                        .get_level = _get_level,
                    330:                        .set_top_level = _set_top_level,
                    331:                        .set_flags = _set_flags,
                    332:                        .success = _success,
                    333:                        .destroy = _destroy,
                    334:                },
                    335:                .objects = objects,
                    336:                .blobs[0] = blob,
                    337:                .line = -1,
                    338:                .success = TRUE,
                    339:        );
                    340: 
                    341:        return &this->public;
                    342: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>