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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * Copyright (C) 2005-2010 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 <stddef.h>
                     19: 
                     20: #include "eap_payload.h"
                     21: 
                     22: #include <daemon.h>
                     23: #include <eap/eap.h>
                     24: #include <bio/bio_writer.h>
                     25: 
                     26: typedef struct private_eap_payload_t private_eap_payload_t;
                     27: 
                     28: /**
                     29:  * Private data of an eap_payload_t object.
                     30:  *
                     31:  */
                     32: struct private_eap_payload_t {
                     33:        /**
                     34:         * Public eap_payload_t interface.
                     35:         */
                     36:        eap_payload_t public;
                     37: 
                     38:        /**
                     39:         * Next payload type.
                     40:         */
                     41:        uint8_t  next_payload;
                     42: 
                     43:        /**
                     44:         * Critical flag.
                     45:         */
                     46:        bool critical;
                     47: 
                     48:        /**
                     49:         * Reserved bits
                     50:         */
                     51:        bool reserved[7];
                     52: 
                     53:        /**
                     54:         * Length of this payload.
                     55:         */
                     56:        uint16_t payload_length;
                     57: 
                     58:        /**
                     59:         * EAP message data, if available
                     60:         */
                     61:        chunk_t data;
                     62: };
                     63: 
                     64: /**
                     65:  * Encoding rules to parse or generate a EAP payload.
                     66:  *
                     67:  * The defined offsets are the positions in a object of type
                     68:  * private_eap_payload_t.
                     69:  *
                     70:  */
                     71: static encoding_rule_t encodings[] = {
                     72:        /* 1 Byte next payload type, stored in the field next_payload */
                     73:        { U_INT_8,                      offsetof(private_eap_payload_t, next_payload)   },
                     74:        /* the critical bit */
                     75:        { FLAG,                         offsetof(private_eap_payload_t, critical)               },
                     76:        /* 7 Bit reserved bits, nowhere stored */
                     77:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[0])    },
                     78:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[1])    },
                     79:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[2])    },
                     80:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[3])    },
                     81:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[4])    },
                     82:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[5])    },
                     83:        { RESERVED_BIT,         offsetof(private_eap_payload_t, reserved[6])    },
                     84:        /* Length of the whole payload*/
                     85:        { PAYLOAD_LENGTH,       offsetof(private_eap_payload_t, payload_length) },
                     86:        /* chunk to data, starting at "code" */
                     87:        { CHUNK_DATA,           offsetof(private_eap_payload_t, data)                   },
                     88: };
                     89: 
                     90: /*
                     91:                             1                   2                   3
                     92:         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                     93:        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     94:        ! Next Payload  !C!  RESERVED   !         Payload Length        !
                     95:        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     96:        !     Code      ! Identifier    !           Length              !
                     97:        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     98:        !     Type      ! Type_Data...
                     99:        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
                    100: */
                    101: 
                    102: METHOD(payload_t, verify, status_t,
                    103:        private_eap_payload_t *this)
                    104: {
                    105:        uint16_t length;
                    106:        uint8_t code;
                    107: 
                    108:        if (this->data.len < 4)
                    109:        {
                    110:                DBG1(DBG_ENC, "EAP payloads EAP message too short (%d)", this->data.len);
                    111:                return FAILED;
                    112:        }
                    113:        length = untoh16(this->data.ptr + 2);
                    114:        if (this->data.len != length)
                    115:        {
                    116:                DBG1(DBG_ENC, "EAP payload length (%d) does not match contained "
                    117:                         "message length (%d)", this->data.len, length);
                    118:                return FAILED;
                    119:        }
                    120:        code = this->data.ptr[0];
                    121:        switch (code)
                    122:        {
                    123:                case EAP_REQUEST:
                    124:                case EAP_RESPONSE:
                    125:                {
                    126:                        if (this->data.len < 4)
                    127:                        {
                    128:                                DBG1(DBG_ENC, "EAP Request/Response does not have any data");
                    129:                                return FAILED;
                    130:                        }
                    131:                        break;
                    132:                }
                    133:                case EAP_SUCCESS:
                    134:                case EAP_FAILURE:
                    135:                {
                    136:                        if (this->data.len != 4)
                    137:                        {
                    138:                                DBG1(DBG_ENC, "EAP Success/Failure has data");
                    139:                                return FAILED;
                    140:                        }
                    141:                        break;
                    142:                }
                    143:                default:
                    144:                        return FAILED;
                    145:        }
                    146:        return SUCCESS;
                    147: }
                    148: 
                    149: METHOD(payload_t, get_encoding_rules, int,
                    150:        private_eap_payload_t *this, encoding_rule_t **rules)
                    151: {
                    152:        *rules = encodings;
                    153:        return countof(encodings);
                    154: }
                    155: 
                    156: METHOD(payload_t, get_header_length, int,
                    157:        private_eap_payload_t *this)
                    158: {
                    159:        return 4;
                    160: }
                    161: 
                    162: METHOD(payload_t, get_payload_type, payload_type_t,
                    163:        private_eap_payload_t *this)
                    164: {
                    165:        return PLV2_EAP;
                    166: }
                    167: 
                    168: METHOD(payload_t, get_next_type, payload_type_t,
                    169:        private_eap_payload_t *this)
                    170: {
                    171:        return (this->next_payload);
                    172: }
                    173: 
                    174: METHOD(payload_t, set_next_type, void,
                    175:        private_eap_payload_t *this, payload_type_t type)
                    176: {
                    177:        this->next_payload = type;
                    178: }
                    179: 
                    180: METHOD(payload_t, get_length, size_t,
                    181:        private_eap_payload_t *this)
                    182: {
                    183:        return this->payload_length;
                    184: }
                    185: 
                    186: METHOD(eap_payload_t, get_data, chunk_t,
                    187:        private_eap_payload_t *this)
                    188: {
                    189:        return this->data;
                    190: }
                    191: 
                    192: METHOD(eap_payload_t, set_data, void,
                    193:        private_eap_payload_t *this, chunk_t data)
                    194: {
                    195:        free(this->data.ptr);
                    196:        this->data = chunk_clone(data);
                    197:        this->payload_length = this->data.len + 4;
                    198: }
                    199: 
                    200: METHOD(eap_payload_t, get_code, eap_code_t,
                    201:        private_eap_payload_t *this)
                    202: {
                    203:        if (this->data.len > 0)
                    204:        {
                    205:                return this->data.ptr[0];
                    206:        }
                    207:        /* should not happen, as it is verified */
                    208:        return 0;
                    209: }
                    210: 
                    211: METHOD(eap_payload_t, get_identifier, uint8_t,
                    212:        private_eap_payload_t *this)
                    213: {
                    214:        if (this->data.len > 1)
                    215:        {
                    216:                return this->data.ptr[1];
                    217:        }
                    218:        /* should not happen, as it is verified */
                    219:        return 0;
                    220: }
                    221: 
                    222: /**
                    223:  * Get the current type at the given offset into this->data.
                    224:  * @return     the new offset or 0 if failed
                    225:  */
                    226: static size_t extract_type(private_eap_payload_t *this, size_t offset,
                    227:                                               eap_type_t *type, uint32_t *vendor)
                    228: {
                    229:        if (this->data.len > offset)
                    230:        {
                    231:                *vendor = 0;
                    232:                *type = this->data.ptr[offset];
                    233:                if (*type != EAP_EXPANDED)
                    234:                {
                    235:                        return offset + 1;
                    236:                }
                    237:                if (this->data.len >= offset + 8)
                    238:                {
                    239:                        *vendor = untoh32(this->data.ptr + offset) & 0x00FFFFFF;
                    240:                        *type = untoh32(this->data.ptr + offset + 4);
                    241:                        return offset + 8;
                    242:                }
                    243:        }
                    244:        return 0;
                    245: }
                    246: 
                    247: METHOD(eap_payload_t, get_type, eap_type_t,
                    248:        private_eap_payload_t *this, uint32_t *vendor)
                    249: {
                    250:        eap_type_t type;
                    251: 
                    252:        *vendor = 0;
                    253:        if (extract_type(this, 4, &type, vendor))
                    254:        {
                    255:                return type;
                    256:        }
                    257:        return 0;
                    258: }
                    259: 
                    260: /**
                    261:  * Type enumerator
                    262:  */
                    263: typedef struct {
                    264:        /** public interface */
                    265:        enumerator_t public;
                    266:        /** payload */
                    267:        private_eap_payload_t *payload;
                    268:        /** current offset in the data */
                    269:        size_t offset;
                    270: } type_enumerator_t;
                    271: 
                    272: METHOD(enumerator_t, enumerate_types, bool,
                    273:        type_enumerator_t *this, va_list args)
                    274: {
                    275:        eap_type_t *type;
                    276:        uint32_t *vendor;
                    277: 
                    278:        VA_ARGS_VGET(args, type, vendor);
                    279:        this->offset = extract_type(this->payload, this->offset, type, vendor);
                    280:        return this->offset;
                    281: }
                    282: 
                    283: METHOD(eap_payload_t, get_types, enumerator_t*,
                    284:        private_eap_payload_t *this)
                    285: {
                    286:        type_enumerator_t *enumerator;
                    287:        eap_type_t type;
                    288:        uint32_t vendor;
                    289:        size_t offset;
                    290: 
                    291:        offset = extract_type(this, 4, &type, &vendor);
                    292:        if (offset && type == EAP_NAK)
                    293:        {
                    294:                INIT(enumerator,
                    295:                        .public = {
                    296:                                .enumerate = enumerator_enumerate_default,
                    297:                                .venumerate = _enumerate_types,
                    298:                                .destroy = (void*)free,
                    299:                        },
                    300:                        .payload = this,
                    301:                        .offset = offset,
                    302:                );
                    303:                return &enumerator->public;
                    304:        }
                    305:        return enumerator_create_empty();
                    306: }
                    307: 
                    308: METHOD(eap_payload_t, is_expanded, bool,
                    309:        private_eap_payload_t *this)
                    310: {
                    311:        return this->data.len > 4 ? this->data.ptr[4] == EAP_EXPANDED : FALSE;
                    312: }
                    313: 
                    314: METHOD2(payload_t, eap_payload_t, destroy, void,
                    315:        private_eap_payload_t *this)
                    316: {
                    317:        chunk_free(&this->data);
                    318:        free(this);
                    319: }
                    320: 
                    321: /*
                    322:  * Described in header
                    323:  */
                    324: eap_payload_t *eap_payload_create()
                    325: {
                    326:        private_eap_payload_t *this;
                    327: 
                    328:        INIT(this,
                    329:                .public = {
                    330:                        .payload_interface = {
                    331:                                .verify = _verify,
                    332:                                .get_encoding_rules = _get_encoding_rules,
                    333:                                .get_header_length = _get_header_length,
                    334:                                .get_length = _get_length,
                    335:                                .get_next_type = _get_next_type,
                    336:                                .set_next_type = _set_next_type,
                    337:                                .get_type = _get_payload_type,
                    338:                                .destroy = _destroy,
                    339:                        },
                    340:                        .get_data = _get_data,
                    341:                        .set_data = _set_data,
                    342:                        .get_code = _get_code,
                    343:                        .get_identifier = _get_identifier,
                    344:                        .get_type = _get_type,
                    345:                        .get_types = _get_types,
                    346:                        .is_expanded = _is_expanded,
                    347:                        .destroy = _destroy,
                    348:                },
                    349:                .next_payload = PL_NONE,
                    350:                .payload_length = get_header_length(this),
                    351:        );
                    352:        return &this->public;
                    353: }
                    354: 
                    355: /*
                    356:  * Described in header
                    357:  */
                    358: eap_payload_t *eap_payload_create_data(chunk_t data)
                    359: {
                    360:        eap_payload_t *this = eap_payload_create();
                    361: 
                    362:        this->set_data(this, data);
                    363:        return this;
                    364: }
                    365: 
                    366: /*
                    367:  * Described in header
                    368:  */
                    369: eap_payload_t *eap_payload_create_data_own(chunk_t data)
                    370: {
                    371:        eap_payload_t *this = eap_payload_create();
                    372: 
                    373:        this->set_data(this, data);
                    374:        free(data.ptr);
                    375:        return this;
                    376: }
                    377: 
                    378: /*
                    379:  * Described in header
                    380:  */
                    381: eap_payload_t *eap_payload_create_code(eap_code_t code, uint8_t identifier)
                    382: {
                    383:        chunk_t data;
                    384: 
                    385:        data = chunk_from_chars(code, identifier, 0, 0);
                    386:        htoun16(data.ptr + 2, data.len);
                    387:        return eap_payload_create_data(data);
                    388: }
                    389: 
                    390: /**
                    391:  * Write the given type either expanded or not
                    392:  */
                    393: static void write_type(bio_writer_t *writer, eap_type_t type, uint32_t vendor,
                    394:                                           bool expanded)
                    395: {
                    396:        if (expanded)
                    397:        {
                    398:                writer->write_uint8(writer, EAP_EXPANDED);
                    399:                writer->write_uint24(writer, vendor);
                    400:                writer->write_uint32(writer, type);
                    401:        }
                    402:        else
                    403:        {
                    404:                writer->write_uint8(writer, type);
                    405:        }
                    406: }
                    407: 
                    408: /*
                    409:  * Described in header
                    410:  */
                    411: eap_payload_t *eap_payload_create_nak(uint8_t identifier, eap_type_t type,
                    412:                                                                          uint32_t vendor, bool expanded)
                    413: {
                    414:        enumerator_t *enumerator;
                    415:        eap_type_t reg_type;
                    416:        uint32_t reg_vendor;
                    417:        bio_writer_t *writer;
                    418:        chunk_t data;
                    419:        bool added_any = FALSE, found_vendor = FALSE;
                    420:        eap_payload_t *payload;
                    421: 
                    422:        writer = bio_writer_create(12);
                    423:        writer->write_uint8(writer, EAP_RESPONSE);
                    424:        writer->write_uint8(writer, identifier);
                    425:        /* write zero length, we update it once we know the length */
                    426:        writer->write_uint16(writer, 0);
                    427: 
                    428:        write_type(writer, EAP_NAK, 0, expanded);
                    429: 
                    430:        enumerator = charon->eap->create_enumerator(charon->eap, EAP_PEER);
                    431:        while (enumerator->enumerate(enumerator, &reg_type, &reg_vendor))
                    432:        {
                    433:                if ((type && type != reg_type) ||
                    434:                        (type && vendor && vendor != reg_vendor))
                    435:                {       /* the preferred type is only sent if we actually find it */
                    436:                        continue;
                    437:                }
                    438:                if (!reg_vendor || expanded)
                    439:                {
                    440:                        write_type(writer, reg_type, reg_vendor, expanded);
                    441:                        added_any = TRUE;
                    442:                }
                    443:                else if (reg_vendor)
                    444:                {       /* found vendor specific method, but this is not an expanded Nak */
                    445:                        found_vendor = TRUE;
                    446:                }
                    447:        }
                    448:        enumerator->destroy(enumerator);
                    449: 
                    450:        if (found_vendor)
                    451:        {       /* request an expanded authentication type */
                    452:                write_type(writer, EAP_EXPANDED, 0, expanded);
                    453:                added_any = TRUE;
                    454:        }
                    455:        if (!added_any)
                    456:        {       /* no methods added */
                    457:                write_type(writer, 0, 0, expanded);
                    458:        }
                    459: 
                    460:        /* set length */
                    461:        data = writer->get_buf(writer);
                    462:        htoun16(data.ptr + offsetof(eap_packet_t, length), data.len);
                    463: 
                    464:        payload = eap_payload_create_data(data);
                    465:        writer->destroy(writer);
                    466:        return payload;
                    467: }

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