Annotation of embedaddon/strongswan/src/libcharon/encoding/generator.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011 Tobias Brunner
                      3:  * Copyright (C) 2005-2009 Martin Willi
                      4:  * Copyright (C) 2005 Jan Hutter
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include <stdlib.h>
                     19: #include <string.h>
                     20: #include <stdio.h>
                     21: 
                     22: #include "generator.h"
                     23: 
                     24: #include <library.h>
                     25: #include <daemon.h>
                     26: #include <collections/linked_list.h>
                     27: #include <encoding/payloads/payload.h>
                     28: #include <encoding/payloads/proposal_substructure.h>
                     29: #include <encoding/payloads/transform_substructure.h>
                     30: #include <encoding/payloads/sa_payload.h>
                     31: #include <encoding/payloads/ke_payload.h>
                     32: #include <encoding/payloads/notify_payload.h>
                     33: #include <encoding/payloads/nonce_payload.h>
                     34: #include <encoding/payloads/id_payload.h>
                     35: #include <encoding/payloads/auth_payload.h>
                     36: #include <encoding/payloads/cert_payload.h>
                     37: #include <encoding/payloads/certreq_payload.h>
                     38: #include <encoding/payloads/ts_payload.h>
                     39: #include <encoding/payloads/delete_payload.h>
                     40: #include <encoding/payloads/vendor_id_payload.h>
                     41: #include <encoding/payloads/cp_payload.h>
                     42: #include <encoding/payloads/configuration_attribute.h>
                     43: #include <encoding/payloads/eap_payload.h>
                     44: #include <encoding/payloads/unknown_payload.h>
                     45: 
                     46: /**
                     47:  * Generating is done in a data buffer.
                     48:  * This is the start size of this buffer in bytes.
                     49:  */
                     50: #define GENERATOR_DATA_BUFFER_SIZE 500
                     51: 
                     52: /**
                     53:  * Number of bytes to increase the buffer, if it is too small.
                     54:  */
                     55: #define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
                     56: 
                     57: typedef struct private_generator_t private_generator_t;
                     58: 
                     59: /**
                     60:  * Private part of a generator_t object.
                     61:  */
                     62: struct private_generator_t {
                     63:        /**
                     64:         * Public part of a generator_t object.
                     65:         */
                     66:         generator_t public;
                     67: 
                     68:        /**
                     69:         * Buffer used to generate the data into.
                     70:         */
                     71:        uint8_t *buffer;
                     72: 
                     73:        /**
                     74:         * Current write position in buffer (one byte aligned).
                     75:         */
                     76:        uint8_t *out_position;
                     77: 
                     78:        /**
                     79:         * Position of last byte in buffer.
                     80:         */
                     81:        uint8_t *roof_position;
                     82: 
                     83:        /**
                     84:         * Current bit writing to in current byte (between 0 and 7).
                     85:         */
                     86:        uint8_t current_bit;
                     87: 
                     88:        /**
                     89:         * Associated data struct to read information from.
                     90:         */
                     91:        void *data_struct;
                     92: 
                     93:        /**
                     94:         * Offset of the header length field in the buffer.
                     95:         */
                     96:        uint32_t header_length_offset;
                     97: 
                     98:        /**
                     99:         * Attribute format of the last generated transform attribute.
                    100:         *
                    101:         * Used to check if a variable value field is used or not for
                    102:         * the transform attribute value.
                    103:         */
                    104:        bool attribute_format;
                    105: 
                    106:        /**
                    107:         * Depending on the value of attribute_format this field is used
                    108:         * to hold the length of the transform attribute in bytes.
                    109:         */
                    110:        uint16_t attribute_length;
                    111: 
                    112:        /**
                    113:         * TRUE, if debug messages should be logged during generation.
                    114:         */
                    115:        bool debug;
                    116: };
                    117: 
                    118: /**
                    119:  * Get size of current buffer in bytes.
                    120:  */
                    121: static int get_size(private_generator_t *this)
                    122: {
                    123:        return this->roof_position - this->buffer;
                    124: }
                    125: 
                    126: /**
                    127:  * Get free space of current buffer in bytes.
                    128:  */
                    129: static int get_space(private_generator_t *this)
                    130: {
                    131:        return this->roof_position - this->out_position;
                    132: }
                    133: 
                    134: /**
                    135:  * Get length of data in buffer (in bytes).
                    136:  */
                    137: static int get_length(private_generator_t *this)
                    138: {
                    139:        return this->out_position - this->buffer;
                    140: }
                    141: 
                    142: /**
                    143:  * Get current offset in buffer (in bytes).
                    144:  */
                    145: static uint32_t get_offset(private_generator_t *this)
                    146: {
                    147:        return this->out_position - this->buffer;
                    148: }
                    149: 
                    150: /**
                    151:  * Makes sure enough space is available in buffer to store amount of bits.
                    152:  */
                    153: static void make_space_available(private_generator_t *this, int bits)
                    154: {
                    155:        while ((get_space(this) * 8 - this->current_bit) < bits)
                    156:        {
                    157:                int old_buffer_size, new_buffer_size, out_position_offset;
                    158: 
                    159:                old_buffer_size = get_size(this);
                    160:                new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
                    161:                out_position_offset = this->out_position - this->buffer;
                    162: 
                    163:                if (this->debug)
                    164:                {
                    165:                        DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
                    166:                                 old_buffer_size, new_buffer_size);
                    167:                }
                    168: 
                    169:                this->buffer = realloc(this->buffer,new_buffer_size);
                    170:                this->out_position = (this->buffer + out_position_offset);
                    171:                this->roof_position = (this->buffer + new_buffer_size);
                    172:        }
                    173: }
                    174: 
                    175: /**
                    176:  * Writes a specific amount of byte into the buffer.
                    177:  */
                    178: static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
                    179:                                                                  int number_of_bytes)
                    180: {
                    181:        int i;
                    182:        uint8_t *read_position = (uint8_t *)bytes;
                    183: 
                    184:        make_space_available(this, number_of_bytes * 8);
                    185: 
                    186:        for (i = 0; i < number_of_bytes; i++)
                    187:        {
                    188:                *(this->out_position) = *(read_position);
                    189:                read_position++;
                    190:                this->out_position++;
                    191:        }
                    192: }
                    193: 
                    194: /**
                    195:  * Generates a U_INT-Field type and writes it to buffer.
                    196:  */
                    197: static void generate_u_int_type(private_generator_t *this,
                    198:                                                                encoding_type_t int_type,uint32_t offset)
                    199: {
                    200:        int number_of_bits = 0;
                    201: 
                    202:        /* find out number of bits of each U_INT type to check for enough space */
                    203:        switch (int_type)
                    204:        {
                    205:                case U_INT_4:
                    206:                        number_of_bits = 4;
                    207:                        break;
                    208:                case TS_TYPE:
                    209:                case RESERVED_BYTE:
                    210:                case SPI_SIZE:
                    211:                case U_INT_8:
                    212:                        number_of_bits = 8;
                    213:                        break;
                    214:                case U_INT_16:
                    215:                case PAYLOAD_LENGTH:
                    216:                case ATTRIBUTE_LENGTH:
                    217:                        number_of_bits = 16;
                    218:                        break;
                    219:                case U_INT_32:
                    220:                        number_of_bits = 32;
                    221:                        break;
                    222:                case ATTRIBUTE_TYPE:
                    223:                        number_of_bits = 15;
                    224:                        break;
                    225:                case IKE_SPI:
                    226:                        number_of_bits = 64;
                    227:                        break;
                    228:                default:
                    229:                        DBG1(DBG_ENC, "U_INT Type %N is not supported",
                    230:                                 encoding_type_names, int_type);
                    231:                        return;
                    232:        }
                    233:        if ((number_of_bits % 8) == 0 && this->current_bit != 0)
                    234:        {
                    235:                DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
                    236:                         encoding_type_names, int_type);
                    237:                return;
                    238:        }
                    239: 
                    240:        make_space_available(this, number_of_bits);
                    241:        switch (int_type)
                    242:        {
                    243:                case U_INT_4:
                    244:                {
                    245:                        uint8_t high, low;
                    246: 
                    247:                        if (this->current_bit == 0)
                    248:                        {
                    249:                                /* high of current byte in buffer has to be set to the new value*/
                    250:                                high = *((uint8_t *)(this->data_struct + offset)) << 4;
                    251:                                /* low in buffer is not changed */
                    252:                                low = *(this->out_position) & 0x0F;
                    253:                                /* high is set, low_val is not changed */
                    254:                                *(this->out_position) = high | low;
                    255:                                if (this->debug)
                    256:                                {
                    257:                                        DBG3(DBG_ENC, "   => %hhu", *(this->out_position) >> 4);
                    258:                                }
                    259:                                /* write position is not changed, just bit position is moved */
                    260:                                this->current_bit = 4;
                    261:                        }
                    262:                        else if (this->current_bit == 4)
                    263:                        {
                    264:                                /* high in buffer is not changed */
                    265:                                high = *(this->out_position) & 0xF0;
                    266:                                /* low of current byte in buffer has to be set to the new value*/
                    267:                                low = *((uint8_t *)(this->data_struct + offset)) & 0x0F;
                    268:                                *(this->out_position) = high | low;
                    269:                                if (this->debug)
                    270:                                {
                    271:                                        DBG3(DBG_ENC, "   => %hhu", *(this->out_position) & 0x0F);
                    272:                                }
                    273:                                this->out_position++;
                    274:                                this->current_bit = 0;
                    275:                        }
                    276:                        else
                    277:                        {
                    278:                                DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
                    279:                                /* 4 Bit integers must have a 4 bit alignment */
                    280:                                return;
                    281:                        }
                    282:                        break;
                    283:                }
                    284:                case TS_TYPE:
                    285:                case RESERVED_BYTE:
                    286:                case SPI_SIZE:
                    287:                case U_INT_8:
                    288:                {
                    289:                        /* 8 bit values are written as they are */
                    290:                        *this->out_position = *((uint8_t *)(this->data_struct + offset));
                    291:                        if (this->debug)
                    292:                        {
                    293:                                DBG3(DBG_ENC, "   => %hhu", *(this->out_position));
                    294:                        }
                    295:                        this->out_position++;
                    296:                        break;
                    297:                }
                    298:                case ATTRIBUTE_TYPE:
                    299:                {
                    300:                        uint8_t attribute_format_flag;
                    301:                        uint16_t val;
                    302: 
                    303:                        /* attribute type must not change first bit of current byte */
                    304:                        if (this->current_bit != 1)
                    305:                        {
                    306:                                DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
                    307:                                return;
                    308:                        }
                    309:                        attribute_format_flag = *(this->out_position) & 0x80;
                    310:                        /* get attribute type value as 16 bit integer*/
                    311:                        val = *((uint16_t*)(this->data_struct + offset));
                    312:                        /* unset most significant bit */
                    313:                        val &= 0x7FFF;
                    314:                        if (attribute_format_flag)
                    315:                        {
                    316:                                val |= 0x8000;
                    317:                        }
                    318:                        val = htons(val);
                    319:                        if (this->debug)
                    320:                        {
                    321:                                DBG3(DBG_ENC, "   => %hu", val);
                    322:                        }
                    323:                        /* write bytes to buffer (set bit is overwritten) */
                    324:                        write_bytes_to_buffer(this, &val, sizeof(uint16_t));
                    325:                        this->current_bit = 0;
                    326:                        break;
                    327: 
                    328:                }
                    329:                case U_INT_16:
                    330:                case PAYLOAD_LENGTH:
                    331:                case ATTRIBUTE_LENGTH:
                    332:                {
                    333:                        uint16_t val = htons(*((uint16_t*)(this->data_struct + offset)));
                    334:                        if (this->debug)
                    335:                        {
                    336:                                DBG3(DBG_ENC, "   %b", &val, sizeof(uint16_t));
                    337:                        }
                    338:                        write_bytes_to_buffer(this, &val, sizeof(uint16_t));
                    339:                        break;
                    340:                }
                    341:                case U_INT_32:
                    342:                {
                    343:                        uint32_t val = htonl(*((uint32_t*)(this->data_struct + offset)));
                    344:                        if (this->debug)
                    345:                        {
                    346:                                DBG3(DBG_ENC, "   %b", &val, sizeof(uint32_t));
                    347:                        }
                    348:                        write_bytes_to_buffer(this, &val, sizeof(uint32_t));
                    349:                        break;
                    350:                }
                    351:                case IKE_SPI:
                    352:                {
                    353:                        /* 64 bit are written as-is, no host order conversion */
                    354:                        write_bytes_to_buffer(this, this->data_struct + offset,
                    355:                                                                  sizeof(uint64_t));
                    356:                        if (this->debug)
                    357:                        {
                    358:                                DBG3(DBG_ENC, "   %b", this->data_struct + offset,
                    359:                                         sizeof(uint64_t));
                    360:                        }
                    361:                        break;
                    362:                }
                    363:                default:
                    364:                {
                    365:                        DBG1(DBG_ENC, "U_INT Type %N is not supported",
                    366:                                 encoding_type_names, int_type);
                    367:                        return;
                    368:                }
                    369:        }
                    370: }
                    371: 
                    372: /**
                    373:  * Generate a FLAG filed
                    374:  */
                    375: static void generate_flag(private_generator_t *this, uint32_t offset)
                    376: {
                    377:        uint8_t flag_value;
                    378:        uint8_t flag;
                    379: 
                    380:        flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
                    381:        /* get flag position */
                    382:        flag = (flag_value << (7 - this->current_bit));
                    383: 
                    384:        /* make sure one bit is available in buffer */
                    385:        make_space_available(this, 1);
                    386:        if (this->current_bit == 0)
                    387:        {
                    388:                /* memory must be zero */
                    389:                *(this->out_position) = 0x00;
                    390:        }
                    391: 
                    392:        *(this->out_position) = *(this->out_position) | flag;
                    393:        if (this->debug)
                    394:        {
                    395:                DBG3(DBG_ENC, "   => %hhu", *this->out_position);
                    396:        }
                    397: 
                    398:        this->current_bit++;
                    399:        if (this->current_bit >= 8)
                    400:        {
                    401:                this->current_bit = this->current_bit % 8;
                    402:                this->out_position++;
                    403:        }
                    404: }
                    405: 
                    406: /**
                    407:  * Generates a bytestream from a chunk_t.
                    408:  */
                    409: static void generate_from_chunk(private_generator_t *this, uint32_t offset)
                    410: {
                    411:        chunk_t *value;
                    412: 
                    413:        if (this->current_bit != 0)
                    414:        {
                    415:                DBG1(DBG_ENC, "can not generate a chunk at bitpos %hhu",
                    416:                         this->current_bit);
                    417:                return ;
                    418:        }
                    419: 
                    420:        value = (chunk_t *)(this->data_struct + offset);
                    421:        if (this->debug)
                    422:        {
                    423:                DBG3(DBG_ENC, "   %B", value);
                    424:        }
                    425: 
                    426:        write_bytes_to_buffer(this, value->ptr, value->len);
                    427: }
                    428: 
                    429: METHOD(generator_t, get_chunk, chunk_t,
                    430:        private_generator_t *this, uint32_t **lenpos)
                    431: {
                    432:        chunk_t data;
                    433: 
                    434:        *lenpos = (uint32_t*)(this->buffer + this->header_length_offset);
                    435:        data = chunk_create(this->buffer, get_length(this));
                    436:        if (this->debug)
                    437:        {
                    438:                DBG3(DBG_ENC, "generated data of this generator %B", &data);
                    439:        }
                    440:        return data;
                    441: }
                    442: 
                    443: METHOD(generator_t, generate_payload, void,
                    444:        private_generator_t *this, payload_t *payload)
                    445: {
                    446:        int i, offset_start, rule_count;
                    447:        encoding_rule_t *rules;
                    448:        payload_type_t payload_type;
                    449: 
                    450:        this->data_struct = payload;
                    451:        payload_type = payload->get_type(payload);
                    452: 
                    453:        offset_start = this->out_position - this->buffer;
                    454: 
                    455:        if (this->debug)
                    456:        {
                    457:                DBG2(DBG_ENC, "generating payload of type %N",
                    458:                         payload_type_names, payload_type);
                    459:        }
                    460: 
                    461:        /* each payload has its own encoding rules */
                    462:        rule_count = payload->get_encoding_rules(payload, &rules);
                    463: 
                    464:        for (i = 0; i < rule_count;i++)
                    465:        {
                    466:                if (this->debug)
                    467:                {
                    468:                        DBG2(DBG_ENC, "  generating rule %d %N",
                    469:                                 i, encoding_type_names, rules[i].type);
                    470:                }
                    471:                switch ((int)rules[i].type)
                    472:                {
                    473:                        case U_INT_4:
                    474:                        case U_INT_8:
                    475:                        case U_INT_16:
                    476:                        case U_INT_32:
                    477:                        case PAYLOAD_LENGTH:
                    478:                        case IKE_SPI:
                    479:                        case RESERVED_BYTE:
                    480:                        case SPI_SIZE:
                    481:                        case TS_TYPE:
                    482:                        case ATTRIBUTE_TYPE:
                    483:                        case ATTRIBUTE_LENGTH:
                    484:                                generate_u_int_type(this, rules[i].type, rules[i].offset);
                    485:                                break;
                    486:                        case RESERVED_BIT:
                    487:                        case FLAG:
                    488:                                generate_flag(this, rules[i].offset);
                    489:                                break;
                    490:                        case HEADER_LENGTH:
                    491:                                this->header_length_offset = get_offset(this);
                    492:                                generate_u_int_type(this, U_INT_32, rules[i].offset);
                    493:                                break;
                    494:                        case ADDRESS:
                    495:                        case SPI:
                    496:                        case CHUNK_DATA:
                    497:                        case ENCRYPTED_DATA:
                    498:                                generate_from_chunk(this, rules[i].offset);
                    499:                                break;
                    500:                        case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
                    501:                        case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
                    502:                        case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
                    503:                        case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
                    504:                        case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
                    505:                        case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
                    506:                        case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
                    507:                        case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
                    508:                        case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
                    509:                        {
                    510:                                linked_list_t *proposals;
                    511:                                enumerator_t *enumerator;
                    512:                                payload_t *proposal;
                    513: 
                    514:                                proposals = *((linked_list_t **)
                    515:                                                                                (this->data_struct + rules[i].offset));
                    516:                                enumerator = proposals->create_enumerator(proposals);
                    517:                                while (enumerator->enumerate(enumerator, &proposal))
                    518:                                {
                    519:                                        generate_payload(this, proposal);
                    520:                                }
                    521:                                enumerator->destroy(enumerator);
                    522:                                break;
                    523:                        }
                    524:                        case ATTRIBUTE_FORMAT:
                    525:                                generate_flag(this, rules[i].offset);
                    526:                                /* Attribute format is a flag which is stored in context*/
                    527:                                this->attribute_format =
                    528:                                                        *((bool *)(this->data_struct + rules[i].offset));
                    529:                                break;
                    530:                        case ATTRIBUTE_LENGTH_OR_VALUE:
                    531:                                if (this->attribute_format)
                    532:                                {
                    533:                                        generate_u_int_type(this, U_INT_16, rules[i].offset);
                    534:                                }
                    535:                                else
                    536:                                {
                    537:                                        generate_u_int_type(this, U_INT_16, rules[i].offset);
                    538:                                        /* this field hold the length of the attribute */
                    539:                                        this->attribute_length =
                    540:                                                *((uint16_t *)(this->data_struct + rules[i].offset));
                    541:                                }
                    542:                                break;
                    543:                        case ATTRIBUTE_VALUE:
                    544:                        {
                    545:                                if (!this->attribute_format)
                    546:                                {
                    547:                                        if (this->debug)
                    548:                                        {
                    549:                                                DBG2(DBG_ENC, "attribute value has not fixed size");
                    550:                                        }
                    551:                                        /* the attribute value is generated */
                    552:                                        generate_from_chunk(this, rules[i].offset);
                    553:                                }
                    554:                                break;
                    555:                        }
                    556:                        default:
                    557:                                DBG1(DBG_ENC, "field type %N is not supported",
                    558:                                         encoding_type_names, rules[i].type);
                    559:                                return;
                    560:                }
                    561:        }
                    562:        if (this->debug)
                    563:        {
                    564:                DBG2(DBG_ENC, "generating %N payload finished",
                    565:                         payload_type_names, payload_type);
                    566:                DBG3(DBG_ENC, "generated data for this payload %b",
                    567:                         this->buffer + offset_start,
                    568:                         (u_int)(this->out_position - this->buffer - offset_start));
                    569:        }
                    570: }
                    571: 
                    572: METHOD(generator_t, destroy, void,
                    573:        private_generator_t *this)
                    574: {
                    575:        free(this->buffer);
                    576:        free(this);
                    577: }
                    578: 
                    579: /*
                    580:  * Described in header
                    581:  */
                    582: generator_t *generator_create()
                    583: {
                    584:        private_generator_t *this;
                    585: 
                    586:        INIT(this,
                    587:                .public = {
                    588:                        .get_chunk = _get_chunk,
                    589:                        .generate_payload = _generate_payload,
                    590:                        .destroy = _destroy,
                    591:                },
                    592:                .buffer = malloc(GENERATOR_DATA_BUFFER_SIZE),
                    593:                .debug = TRUE,
                    594:        );
                    595: 
                    596:        this->out_position = this->buffer;
                    597:        this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
                    598: 
                    599:        return &this->public;
                    600: }
                    601: 
                    602: /*
                    603:  * Described in header
                    604:  */
                    605: generator_t *generator_create_no_dbg()
                    606: {
                    607:        private_generator_t *this = (private_generator_t*)generator_create();
                    608: 
                    609:        this->debug = FALSE;
                    610: 
                    611:        return &this->public;
                    612: }

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