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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2020 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 "sa_payload.h"
                     21: 
                     22: #include <encoding/payloads/encodings.h>
                     23: #include <collections/linked_list.h>
                     24: #include <daemon.h>
                     25: 
                     26: /* IKEv1 situation */
                     27: #define SIT_IDENTITY_ONLY 1
                     28: 
                     29: typedef struct private_sa_payload_t private_sa_payload_t;
                     30: 
                     31: /**
                     32:  * Private data of an sa_payload_t object.
                     33:  */
                     34: struct private_sa_payload_t {
                     35: 
                     36:        /**
                     37:         * Public sa_payload_t interface.
                     38:         */
                     39:        sa_payload_t public;
                     40: 
                     41:        /**
                     42:         * Next payload type.
                     43:         */
                     44:        uint8_t  next_payload;
                     45: 
                     46:        /**
                     47:         * Critical flag.
                     48:         */
                     49:        bool critical;
                     50: 
                     51:        /**
                     52:         * Reserved bits
                     53:         */
                     54:        bool reserved[8];
                     55: 
                     56:        /**
                     57:         * Length of this payload.
                     58:         */
                     59:        uint16_t payload_length;
                     60: 
                     61:        /**
                     62:         * Proposals in this payload are stored in a linked_list_t.
                     63:         */
                     64:        linked_list_t *proposals;
                     65: 
                     66:        /**
                     67:         * Type of this payload, V1 or V2
                     68:         */
                     69:        payload_type_t type;
                     70: 
                     71:        /**
                     72:         * IKEv1 DOI
                     73:         */
                     74:        uint32_t doi;
                     75: 
                     76:        /**
                     77:         * IKEv1 situation
                     78:         */
                     79:        uint32_t situation;
                     80: };
                     81: 
                     82: /**
                     83:  * Encoding rules for IKEv1 SA payload
                     84:  */
                     85: static encoding_rule_t encodings_v1[] = {
                     86:        /* 1 Byte next payload type, stored in the field next_payload */
                     87:        { U_INT_8,                      offsetof(private_sa_payload_t, next_payload)    },
                     88:        /* 8 reserved bits */
                     89:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[0])                     },
                     90:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[1])                     },
                     91:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[2])                     },
                     92:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[3])                     },
                     93:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[4])                     },
                     94:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[5])                     },
                     95:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[6])                     },
                     96:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[7])                     },
                     97:        /* Length of the whole SA payload*/
                     98:        { PAYLOAD_LENGTH,       offsetof(private_sa_payload_t, payload_length)  },
                     99:        /* DOI*/
                    100:        { U_INT_32,                     offsetof(private_sa_payload_t, doi)                             },
                    101:        /* Situation*/
                    102:        { U_INT_32,                     offsetof(private_sa_payload_t, situation)               },
                    103:        /* Proposals are stored in a proposal substructure list */
                    104:        { PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE,
                    105:                                                offsetof(private_sa_payload_t, proposals)               },
                    106: };
                    107: 
                    108: /*
                    109:                            1                   2                   3
                    110:        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
                    111:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    112:       ! Next Payload  !    RESERVED   !         Payload Length        !
                    113:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    114:       !                           DOI                                 !
                    115:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    116:       !                           Situation                           !
                    117:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    118:       !                                                               !
                    119:       ~                          <Proposals>                          ~
                    120:       !                                                               !
                    121:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    122: */
                    123: 
                    124: /**
                    125:  * Encoding rules for IKEv2 SA payload
                    126:  */
                    127: static encoding_rule_t encodings_v2[] = {
                    128:        /* 1 Byte next payload type, stored in the field next_payload */
                    129:        { U_INT_8,                      offsetof(private_sa_payload_t, next_payload)            },
                    130:        /* the critical bit */
                    131:        { FLAG,                         offsetof(private_sa_payload_t, critical)                        },
                    132:        /* 7 Bit reserved bits */
                    133:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[0])                     },
                    134:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[1])                     },
                    135:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[2])                     },
                    136:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[3])                     },
                    137:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[4])                     },
                    138:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[5])                     },
                    139:        { RESERVED_BIT,         offsetof(private_sa_payload_t, reserved[6])                     },
                    140:        /* Length of the whole SA payload*/
                    141:        { PAYLOAD_LENGTH,       offsetof(private_sa_payload_t, payload_length)          },
                    142:        /* Proposals are stored in a proposal substructure list */
                    143:        { PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE,
                    144:                                                offsetof(private_sa_payload_t, proposals)                       },
                    145: };
                    146: 
                    147: /*
                    148:                            1                   2                   3
                    149:        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
                    150:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    151:       ! Next Payload  !C!  RESERVED   !         Payload Length        !
                    152:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    153:       !                                                               !
                    154:       ~                          <Proposals>                          ~
                    155:       !                                                               !
                    156:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    157: */
                    158: 
                    159: METHOD(payload_t, verify, status_t,
                    160:        private_sa_payload_t *this)
                    161: {
                    162:        int expected_number = 0, current_number;
                    163:        status_t status = SUCCESS;
                    164:        enumerator_t *enumerator;
                    165:        proposal_substructure_t *substruct;
                    166: 
                    167:        if (this->type == PLV2_SECURITY_ASSOCIATION)
                    168:        {
                    169:                expected_number = 1;
                    170:        }
                    171: 
                    172:        /* check proposal numbering */
                    173:        enumerator = this->proposals->create_enumerator(this->proposals);
                    174:        while (enumerator->enumerate(enumerator, (void**)&substruct))
                    175:        {
                    176:                current_number = substruct->get_proposal_number(substruct);
                    177:                if (current_number < expected_number)
                    178:                {
                    179:                        DBG1(DBG_ENC, "proposal number smaller than previous");
                    180:                        status = FAILED;
                    181:                        break;
                    182:                }
                    183: 
                    184:                status = substruct->payload_interface.verify(&substruct->payload_interface);
                    185:                if (status != SUCCESS)
                    186:                {
                    187:                        DBG1(DBG_ENC, "PROPOSAL_SUBSTRUCTURE verification failed");
                    188:                        break;
                    189:                }
                    190:                expected_number = current_number;
                    191:        }
                    192:        enumerator->destroy(enumerator);
                    193:        return status;
                    194: }
                    195: 
                    196: METHOD(payload_t, get_encoding_rules, int,
                    197:        private_sa_payload_t *this, encoding_rule_t **rules)
                    198: {
                    199:        if (this->type == PLV1_SECURITY_ASSOCIATION)
                    200:        {
                    201:                *rules = encodings_v1;
                    202:                return countof(encodings_v1);
                    203:        }
                    204:        *rules = encodings_v2;
                    205:        return countof(encodings_v2);
                    206: }
                    207: 
                    208: METHOD(payload_t, get_header_length, int,
                    209:        private_sa_payload_t *this)
                    210: {
                    211:        if (this->type == PLV1_SECURITY_ASSOCIATION)
                    212:        {
                    213:                return 12;
                    214:        }
                    215:        return 4;
                    216: }
                    217: 
                    218: METHOD(payload_t, get_type, payload_type_t,
                    219:        private_sa_payload_t *this)
                    220: {
                    221:        return this->type;
                    222: }
                    223: 
                    224: METHOD(payload_t, get_next_type, payload_type_t,
                    225:        private_sa_payload_t *this)
                    226: {
                    227:        return this->next_payload;
                    228: }
                    229: 
                    230: METHOD(payload_t, set_next_type, void,
                    231:        private_sa_payload_t *this,payload_type_t type)
                    232: {
                    233:        this->next_payload = type;
                    234: }
                    235: 
                    236: /**
                    237:  * recompute length of the payload.
                    238:  */
                    239: static void compute_length(private_sa_payload_t *this)
                    240: {
                    241:        enumerator_t *enumerator;
                    242:        payload_t *current;
                    243: 
                    244:        this->payload_length = get_header_length(this);
                    245: 
                    246:        enumerator = this->proposals->create_enumerator(this->proposals);
                    247:        while (enumerator->enumerate(enumerator, (void **)&current))
                    248:        {
                    249:                this->payload_length += current->get_length(current);
                    250:        }
                    251:        enumerator->destroy(enumerator);
                    252: }
                    253: 
                    254: METHOD(payload_t, get_length, size_t,
                    255:        private_sa_payload_t *this)
                    256: {
                    257:        return this->payload_length;
                    258: }
                    259: 
                    260: /**
                    261:  * Create a transform substructure from a proposal, add to payload
                    262:  */
                    263: static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
                    264: {
                    265:        proposal_substructure_t *substruct, *last;
                    266:        u_int count;
                    267: 
                    268:        substruct = proposal_substructure_create_from_proposal_v2(proposal);
                    269:        count = this->proposals->get_count(this->proposals);
                    270:        if (count > 0)
                    271:        {
                    272:                this->proposals->get_last(this->proposals, (void**)&last);
                    273:                /* last transform is now not anymore last one */
                    274:                last->set_is_last_proposal(last, FALSE);
                    275:        }
                    276:        substruct->set_is_last_proposal(substruct, TRUE);
                    277:        if (proposal->get_number(proposal))
                    278:        {       /* use the selected proposals number, if any */
                    279:                substruct->set_proposal_number(substruct, proposal->get_number(proposal));
                    280:        }
                    281:        else
                    282:        {
                    283:                substruct->set_proposal_number(substruct, count + 1);
                    284:        }
                    285:        this->proposals->insert_last(this->proposals, substruct);
                    286:        compute_length(this);
                    287: }
                    288: 
                    289: METHOD(sa_payload_t, get_proposals, linked_list_t*,
                    290:        private_sa_payload_t *this)
                    291: {
                    292:        int struct_number = 0;
                    293:        int ignore_struct_number = 0;
                    294:        enumerator_t *enumerator;
                    295:        proposal_substructure_t *substruct;
                    296:        linked_list_t *substructs, *list;
                    297: 
                    298:        if (this->type == PLV1_SECURITY_ASSOCIATION)
                    299:        {       /* IKEv1 proposals may start with 0 or 1 (or any other number really) */
                    300:                struct_number = ignore_struct_number = -1;
                    301:        }
                    302: 
                    303:        /* we do not support proposals split up to two proposal substructures, as
                    304:         * AH+ESP bundles are not supported in RFC4301 anymore.
                    305:         * To handle such structures safely, we just skip proposals with multiple
                    306:         * protocols.
                    307:         */
                    308:        substructs = linked_list_create();
                    309:        enumerator = this->proposals->create_enumerator(this->proposals);
                    310:        while (enumerator->enumerate(enumerator, &substruct))
                    311:        {
                    312:                int current_number = substruct->get_proposal_number(substruct);
                    313: 
                    314:                /* check if a proposal has a single protocol */
                    315:                if (current_number == struct_number)
                    316:                {
                    317:                        if (ignore_struct_number < struct_number)
                    318:                        {       /* remove an already added substruct, if first of series */
                    319:                                substructs->remove_last(substructs, (void**)&substruct);
                    320:                                ignore_struct_number = struct_number;
                    321:                        }
                    322:                        continue;
                    323:                }
                    324:                /* for IKEv1 the numbers don't have to be consecutive, for IKEv2 they do
                    325:                 * but since we don't really care for the actual number we accept them
                    326:                 * anyway. we already verified that they increase monotonically. */
                    327:                struct_number = current_number;
                    328:                substructs->insert_last(substructs, substruct);
                    329:        }
                    330:        enumerator->destroy(enumerator);
                    331: 
                    332:        /* generate proposals from substructs */
                    333:        list = linked_list_create();
                    334:        enumerator = substructs->create_enumerator(substructs);
                    335:        while (enumerator->enumerate(enumerator, &substruct))
                    336:        {
                    337:                substruct->get_proposals(substruct, list);
                    338:        }
                    339:        enumerator->destroy(enumerator);
                    340:        substructs->destroy(substructs);
                    341:        return list;
                    342: }
                    343: 
                    344: METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
                    345:        private_sa_payload_t *this, uint16_t *cpi)
                    346: {
                    347:        int current_proposal = -1, unsupported_proposal = -1;
                    348:        enumerator_t *enumerator;
                    349:        proposal_substructure_t *substruct, *espah = NULL, *ipcomp = NULL;
                    350:        linked_list_t *list;
                    351: 
                    352:        /* we currently only support the combination ESP|AH+IPComp, find the first */
                    353:        enumerator = this->proposals->create_enumerator(this->proposals);
                    354:        while (enumerator->enumerate(enumerator, &substruct))
                    355:        {
                    356:                uint8_t proposal_number = substruct->get_proposal_number(substruct);
                    357:                uint8_t protocol_id = substruct->get_protocol_id(substruct);
                    358: 
                    359:                if (proposal_number == unsupported_proposal)
                    360:                {
                    361:                        continue;
                    362:                }
                    363:                if (protocol_id != PROTO_ESP && protocol_id != PROTO_AH &&
                    364:                        protocol_id != PROTO_IPCOMP)
                    365:                {       /* unsupported combination */
                    366:                        espah = ipcomp = NULL;
                    367:                        unsupported_proposal = current_proposal;
                    368:                        continue;
                    369:                }
                    370:                if (proposal_number != current_proposal)
                    371:                {       /* start of a new proposal */
                    372:                        if (espah && ipcomp && ipcomp->get_cpi(ipcomp, NULL))
                    373:                        {       /* previous proposal is valid */
                    374:                                break;
                    375:                        }
                    376:                        espah = ipcomp = NULL;
                    377:                        current_proposal = proposal_number;
                    378:                }
                    379:                switch (protocol_id)
                    380:                {
                    381:                        case PROTO_ESP:
                    382:                        case PROTO_AH:
                    383:                                espah = substruct;
                    384:                                break;
                    385:                        case PROTO_IPCOMP:
                    386:                                ipcomp = substruct;
                    387:                                break;
                    388:                }
                    389:        }
                    390:        enumerator->destroy(enumerator);
                    391: 
                    392:        list = linked_list_create();
                    393:        if (espah && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
                    394:        {
                    395:                espah->get_proposals(espah, list);
                    396:        }
                    397:        return list;
                    398: }
                    399: 
                    400: METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
                    401:        private_sa_payload_t *this)
                    402: {
                    403:        return this->proposals->create_enumerator(this->proposals);
                    404: }
                    405: 
                    406: METHOD(sa_payload_t, get_lifetime, uint32_t,
                    407:        private_sa_payload_t *this, proposal_t *proposal)
                    408: {
                    409:        proposal_substructure_t *substruct;
                    410:        enumerator_t *enumerator;
                    411:        uint8_t number = proposal->get_number(proposal);
                    412:        uint32_t lifetime = 0;
                    413: 
                    414:        enumerator = this->proposals->create_enumerator(this->proposals);
                    415:        while (enumerator->enumerate(enumerator, &substruct))
                    416:        {
                    417:                if (substruct->get_proposal_number(substruct) == number)
                    418:                {
                    419:                        lifetime = substruct->get_lifetime(substruct,
                    420:                                                                        proposal->get_transform_number(proposal));
                    421:                        break;
                    422:                }
                    423:        }
                    424:        enumerator->destroy(enumerator);
                    425: 
                    426:        return lifetime;
                    427: }
                    428: 
                    429: METHOD(sa_payload_t, get_lifebytes, uint64_t,
                    430:        private_sa_payload_t *this, proposal_t *proposal)
                    431: {
                    432:        proposal_substructure_t *substruct;
                    433:        enumerator_t *enumerator;
                    434:        uint8_t number = proposal->get_number(proposal);
                    435:        uint64_t lifebytes = 0;
                    436: 
                    437:        enumerator = this->proposals->create_enumerator(this->proposals);
                    438:        while (enumerator->enumerate(enumerator, &substruct))
                    439:        {
                    440:                if (substruct->get_proposal_number(substruct) == number)
                    441:                {
                    442:                        lifebytes = substruct->get_lifebytes(substruct,
                    443:                                                                        proposal->get_transform_number(proposal));
                    444:                        break;
                    445:                }
                    446:        }
                    447:        enumerator->destroy(enumerator);
                    448: 
                    449:        return lifebytes;
                    450: }
                    451: 
                    452: METHOD(sa_payload_t, get_auth_method, auth_method_t,
                    453:        private_sa_payload_t *this)
                    454: {
                    455:        proposal_substructure_t *substruct;
                    456:        enumerator_t *enumerator;
                    457:        auth_method_t method = AUTH_NONE;
                    458: 
                    459:        enumerator = this->proposals->create_enumerator(this->proposals);
                    460:        if (enumerator->enumerate(enumerator, &substruct))
                    461:        {
                    462:                method = substruct->get_auth_method(substruct);
                    463:        }
                    464:        enumerator->destroy(enumerator);
                    465: 
                    466:        return method;
                    467: }
                    468: 
                    469: METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
                    470:        private_sa_payload_t *this, bool *udp)
                    471: {
                    472:        proposal_substructure_t *substruct;
                    473:        enumerator_t *enumerator;
                    474:        ipsec_mode_t mode = MODE_NONE;
                    475: 
                    476:        enumerator = this->proposals->create_enumerator(this->proposals);
                    477:        if (enumerator->enumerate(enumerator, &substruct))
                    478:        {
                    479:                mode = substruct->get_encap_mode(substruct, udp);
                    480:        }
                    481:        enumerator->destroy(enumerator);
                    482: 
                    483:        return mode;
                    484: }
                    485: 
                    486: METHOD2(payload_t, sa_payload_t, destroy, void,
                    487:        private_sa_payload_t *this)
                    488: {
                    489:        this->proposals->destroy_offset(this->proposals,
                    490:                                                                        offsetof(payload_t, destroy));
                    491:        free(this);
                    492: }
                    493: 
                    494: /*
                    495:  * Described in header.
                    496:  */
                    497: sa_payload_t *sa_payload_create(payload_type_t type)
                    498: {
                    499:        private_sa_payload_t *this;
                    500: 
                    501:        INIT(this,
                    502:                .public = {
                    503:                        .payload_interface = {
                    504:                                .verify = _verify,
                    505:                                .get_encoding_rules = _get_encoding_rules,
                    506:                                .get_header_length = _get_header_length,
                    507:                                .get_length = _get_length,
                    508:                                .get_next_type = _get_next_type,
                    509:                                .set_next_type = _set_next_type,
                    510:                                .get_type = _get_type,
                    511:                                .destroy = _destroy,
                    512:                        },
                    513:                        .get_proposals = _get_proposals,
                    514:                        .get_ipcomp_proposals = _get_ipcomp_proposals,
                    515:                        .create_substructure_enumerator = _create_substructure_enumerator,
                    516:                        .get_lifetime = _get_lifetime,
                    517:                        .get_lifebytes = _get_lifebytes,
                    518:                        .get_auth_method = _get_auth_method,
                    519:                        .get_encap_mode = _get_encap_mode,
                    520:                        .destroy = _destroy,
                    521:                },
                    522:                .next_payload = PL_NONE,
                    523:                .proposals = linked_list_create(),
                    524:                .type = type,
                    525:                /* for IKEv1 only */
                    526:                .doi = IKEV1_DOI_IPSEC,
                    527:                .situation = SIT_IDENTITY_ONLY,
                    528:        );
                    529: 
                    530:        compute_length(this);
                    531: 
                    532:        return &this->public;
                    533: }
                    534: 
                    535: /*
                    536:  * Described in header.
                    537:  */
                    538: sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
                    539: {
                    540:        private_sa_payload_t *this;
                    541:        enumerator_t *enumerator;
                    542:        proposal_t *proposal;
                    543: 
                    544:        this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
                    545:        enumerator = proposals->create_enumerator(proposals);
                    546:        while (enumerator->enumerate(enumerator, &proposal))
                    547:        {
                    548:                add_proposal_v2(this, proposal);
                    549:        }
                    550:        enumerator->destroy(enumerator);
                    551: 
                    552:        return &this->public;
                    553: }
                    554: 
                    555: /*
                    556:  * Described in header.
                    557:  */
                    558: sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
                    559: {
                    560:        private_sa_payload_t *this;
                    561: 
                    562:        this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
                    563:        add_proposal_v2(this, proposal);
                    564: 
                    565:        return &this->public;
                    566: 
                    567: }
                    568: 
                    569: /*
                    570:  * Described in header.
                    571:  */
                    572: sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
                    573:                                                                uint32_t lifetime, uint64_t lifebytes,
                    574:                                                                auth_method_t auth, ipsec_mode_t mode,
                    575:                                                                encap_t udp, uint16_t cpi)
                    576: {
                    577:        proposal_substructure_t *substruct;
                    578:        private_sa_payload_t *this;
                    579: 
                    580:        this = (private_sa_payload_t*)sa_payload_create(PLV1_SECURITY_ASSOCIATION);
                    581: 
                    582:        if (!proposals || !proposals->get_count(proposals))
                    583:        {
                    584:                return &this->public;
                    585:        }
                    586: 
                    587:        /* IKEv1 encodes multiple proposals in a single substructure
                    588:         * TODO-IKEv1: Encode ESP+AH proposals in two substructs with same num */
                    589:        substruct = proposal_substructure_create_from_proposals_v1(proposals,
                    590:                                                                                lifetime, lifebytes, auth, mode, udp);
                    591:        this->proposals->insert_last(this->proposals, substruct);
                    592:        substruct->set_is_last_proposal(substruct, FALSE);
                    593:        if (cpi)
                    594:        {
                    595:                uint8_t proposal_number = substruct->get_proposal_number(substruct);
                    596: 
                    597:                substruct = proposal_substructure_create_for_ipcomp_v1(lifetime,
                    598:                                        lifebytes, cpi, mode, udp, proposal_number);
                    599:                this->proposals->insert_last(this->proposals, substruct);
                    600:                substruct->set_is_last_proposal(substruct, FALSE);
                    601:                /* add the proposals again without IPComp */
                    602:                substruct = proposal_substructure_create_from_proposals_v1(proposals,
                    603:                                                                                lifetime, lifebytes, auth, mode, udp);
                    604:                substruct->set_proposal_number(substruct, proposal_number + 1);
                    605:                this->proposals->insert_last(this->proposals, substruct);
                    606:        }
                    607:        substruct->set_is_last_proposal(substruct, TRUE);
                    608:        compute_length(this);
                    609: 
                    610:        return &this->public;
                    611: }
                    612: 
                    613: /*
                    614:  * Described in header.
                    615:  */
                    616: sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
                    617:                                                                uint32_t lifetime, uint64_t lifebytes,
                    618:                                                                auth_method_t auth, ipsec_mode_t mode,
                    619:                                                                encap_t udp, uint16_t cpi)
                    620: {
                    621:        private_sa_payload_t *this;
                    622:        linked_list_t *proposals;
                    623: 
                    624:        proposals = linked_list_create();
                    625:        proposals->insert_last(proposals, proposal);
                    626:        this = (private_sa_payload_t*)sa_payload_create_from_proposals_v1(proposals,
                    627:                                                                        lifetime, lifebytes, auth, mode, udp, cpi);
                    628:        proposals->destroy(proposals);
                    629:        return &this->public;
                    630: }

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