Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/child_create.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008-2019 Tobias Brunner
        !             3:  * Copyright (C) 2005-2008 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 "child_create.h"
        !            19: 
        !            20: #include <daemon.h>
        !            21: #include <sa/ikev2/keymat_v2.h>
        !            22: #include <crypto/diffie_hellman.h>
        !            23: #include <credentials/certificates/x509.h>
        !            24: #include <encoding/payloads/sa_payload.h>
        !            25: #include <encoding/payloads/ke_payload.h>
        !            26: #include <encoding/payloads/ts_payload.h>
        !            27: #include <encoding/payloads/nonce_payload.h>
        !            28: #include <encoding/payloads/notify_payload.h>
        !            29: #include <encoding/payloads/delete_payload.h>
        !            30: #include <processing/jobs/delete_ike_sa_job.h>
        !            31: #include <processing/jobs/inactivity_job.h>
        !            32: #include <processing/jobs/initiate_tasks_job.h>
        !            33: 
        !            34: typedef struct private_child_create_t private_child_create_t;
        !            35: 
        !            36: /**
        !            37:  * Private members of a child_create_t task.
        !            38:  */
        !            39: struct private_child_create_t {
        !            40: 
        !            41:        /**
        !            42:         * Public methods and task_t interface.
        !            43:         */
        !            44:        child_create_t public;
        !            45: 
        !            46:        /**
        !            47:         * Assigned IKE_SA.
        !            48:         */
        !            49:        ike_sa_t *ike_sa;
        !            50: 
        !            51:        /**
        !            52:         * Are we the initiator?
        !            53:         */
        !            54:        bool initiator;
        !            55: 
        !            56:        /**
        !            57:         * nonce chosen by us
        !            58:         */
        !            59:        chunk_t my_nonce;
        !            60: 
        !            61:        /**
        !            62:         * nonce chosen by peer
        !            63:         */
        !            64:        chunk_t other_nonce;
        !            65: 
        !            66:        /**
        !            67:         * nonce generator
        !            68:         */
        !            69:        nonce_gen_t *nonceg;
        !            70: 
        !            71:        /**
        !            72:         * config to create the CHILD_SA from
        !            73:         */
        !            74:        child_cfg_t *config;
        !            75: 
        !            76:        /**
        !            77:         * list of proposal candidates
        !            78:         */
        !            79:        linked_list_t *proposals;
        !            80: 
        !            81:        /**
        !            82:         * selected proposal to use for CHILD_SA
        !            83:         */
        !            84:        proposal_t *proposal;
        !            85: 
        !            86:        /**
        !            87:         * traffic selectors for initiators side
        !            88:         */
        !            89:        linked_list_t *tsi;
        !            90: 
        !            91:        /**
        !            92:         * traffic selectors for responders side
        !            93:         */
        !            94:        linked_list_t *tsr;
        !            95: 
        !            96:        /**
        !            97:         * source of triggering packet
        !            98:         */
        !            99:        traffic_selector_t *packet_tsi;
        !           100: 
        !           101:        /**
        !           102:         * destination of triggering packet
        !           103:         */
        !           104:        traffic_selector_t *packet_tsr;
        !           105: 
        !           106:        /**
        !           107:         * optional diffie hellman exchange
        !           108:         */
        !           109:        diffie_hellman_t *dh;
        !           110: 
        !           111:        /**
        !           112:         * Applying DH public value failed?
        !           113:         */
        !           114:        bool dh_failed;
        !           115: 
        !           116:        /**
        !           117:         * group used for DH exchange
        !           118:         */
        !           119:        diffie_hellman_group_t dh_group;
        !           120: 
        !           121:        /**
        !           122:         * IKE_SAs keymat
        !           123:         */
        !           124:        keymat_v2_t *keymat;
        !           125: 
        !           126:        /**
        !           127:         * mode the new CHILD_SA uses (transport/tunnel/beet)
        !           128:         */
        !           129:        ipsec_mode_t mode;
        !           130: 
        !           131:        /**
        !           132:         * peer accepts TFC padding for this SA
        !           133:         */
        !           134:        bool tfcv3;
        !           135: 
        !           136:        /**
        !           137:         * IPComp transform to use
        !           138:         */
        !           139:        ipcomp_transform_t ipcomp;
        !           140: 
        !           141:        /**
        !           142:         * IPComp transform proposed or accepted by the other peer
        !           143:         */
        !           144:        ipcomp_transform_t ipcomp_received;
        !           145: 
        !           146:        /**
        !           147:         * IPsec protocol
        !           148:         */
        !           149:        protocol_id_t proto;
        !           150: 
        !           151:        /**
        !           152:         * Own allocated SPI
        !           153:         */
        !           154:        uint32_t my_spi;
        !           155: 
        !           156:        /**
        !           157:         * SPI received in proposal
        !           158:         */
        !           159:        uint32_t other_spi;
        !           160: 
        !           161:        /**
        !           162:         * Own allocated Compression Parameter Index (CPI)
        !           163:         */
        !           164:        uint16_t my_cpi;
        !           165: 
        !           166:        /**
        !           167:         * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
        !           168:         */
        !           169:        uint16_t other_cpi;
        !           170: 
        !           171:        /**
        !           172:         * Data collected to create the CHILD_SA
        !           173:         */
        !           174:        child_sa_create_t child;
        !           175: 
        !           176:        /**
        !           177:         * CHILD_SA which gets established
        !           178:         */
        !           179:        child_sa_t *child_sa;
        !           180: 
        !           181:        /**
        !           182:         * successfully established the CHILD?
        !           183:         */
        !           184:        bool established;
        !           185: 
        !           186:        /**
        !           187:         * whether the CHILD_SA rekeys an existing one
        !           188:         */
        !           189:        bool rekey;
        !           190: 
        !           191:        /**
        !           192:         * whether we are retrying with another DH group
        !           193:         */
        !           194:        bool retry;
        !           195: };
        !           196: 
        !           197: /**
        !           198:  * Schedule a retry if creating the CHILD_SA temporary failed
        !           199:  */
        !           200: static void schedule_delayed_retry(private_child_create_t *this)
        !           201: {
        !           202:        child_create_t *task;
        !           203:        uint32_t retry;
        !           204: 
        !           205:        retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
        !           206: 
        !           207:        task = child_create_create(this->ike_sa,
        !           208:                                                           this->config->get_ref(this->config), FALSE,
        !           209:                                                           this->packet_tsi, this->packet_tsr);
        !           210:        task->use_reqid(task, this->child.reqid);
        !           211:        task->use_marks(task, this->child.mark_in, this->child.mark_out);
        !           212:        task->use_if_ids(task, this->child.if_id_in, this->child.if_id_out);
        !           213: 
        !           214:        DBG1(DBG_IKE, "creating CHILD_SA failed, trying again in %d seconds",
        !           215:                 retry);
        !           216:        this->ike_sa->queue_task_delayed(this->ike_sa, (task_t*)task, retry);
        !           217: }
        !           218: 
        !           219: /**
        !           220:  * get the nonce from a message
        !           221:  */
        !           222: static status_t get_nonce(message_t *message, chunk_t *nonce)
        !           223: {
        !           224:        nonce_payload_t *payload;
        !           225: 
        !           226:        payload = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
        !           227:        if (payload == NULL)
        !           228:        {
        !           229:                return FAILED;
        !           230:        }
        !           231:        *nonce = payload->get_nonce(payload);
        !           232:        return NEED_MORE;
        !           233: }
        !           234: 
        !           235: /**
        !           236:  * generate a new nonce to include in a CREATE_CHILD_SA message
        !           237:  */
        !           238: static bool generate_nonce(private_child_create_t *this)
        !           239: {
        !           240:        this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
        !           241:        if (!this->nonceg)
        !           242:        {
        !           243:                DBG1(DBG_IKE, "no nonce generator found to create nonce");
        !           244:                return FALSE;
        !           245:        }
        !           246:        if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
        !           247:                                                                          &this->my_nonce))
        !           248:        {
        !           249:                DBG1(DBG_IKE, "nonce allocation failed");
        !           250:                return FALSE;
        !           251:        }
        !           252:        return TRUE;
        !           253: }
        !           254: 
        !           255: /**
        !           256:  * Check a list of traffic selectors if any selector belongs to host
        !           257:  */
        !           258: static bool ts_list_is_host(linked_list_t *list, host_t *host)
        !           259: {
        !           260:        traffic_selector_t *ts;
        !           261:        bool is_host = TRUE;
        !           262:        enumerator_t *enumerator = list->create_enumerator(list);
        !           263: 
        !           264:        while (is_host && enumerator->enumerate(enumerator, (void**)&ts))
        !           265:        {
        !           266:                is_host = is_host && ts->is_host(ts, host);
        !           267:        }
        !           268:        enumerator->destroy(enumerator);
        !           269:        return is_host;
        !           270: }
        !           271: 
        !           272: /**
        !           273:  * Allocate local SPI
        !           274:  */
        !           275: static bool allocate_spi(private_child_create_t *this)
        !           276: {
        !           277:        proposal_t *proposal;
        !           278: 
        !           279:        if (this->initiator)
        !           280:        {
        !           281:                this->proto = PROTO_ESP;
        !           282:                /* we just get a SPI for the first protocol. TODO: If we ever support
        !           283:                 * proposal lists with mixed protocols, we'd need multiple SPIs */
        !           284:                if (this->proposals->get_first(this->proposals,
        !           285:                                                                           (void**)&proposal) == SUCCESS)
        !           286:                {
        !           287:                        this->proto = proposal->get_protocol(proposal);
        !           288:                }
        !           289:        }
        !           290:        else
        !           291:        {
        !           292:                this->proto = this->proposal->get_protocol(this->proposal);
        !           293:        }
        !           294:        this->my_spi = this->child_sa->alloc_spi(this->child_sa, this->proto);
        !           295:        return this->my_spi != 0;
        !           296: }
        !           297: 
        !           298: /**
        !           299:  * Update the proposals with the allocated SPIs as initiator and check the DH
        !           300:  * group and promote it if necessary
        !           301:  */
        !           302: static bool update_and_check_proposals(private_child_create_t *this)
        !           303: {
        !           304:        enumerator_t *enumerator;
        !           305:        proposal_t *proposal;
        !           306:        linked_list_t *other_dh_groups;
        !           307:        bool found = FALSE;
        !           308: 
        !           309:        other_dh_groups = linked_list_create();
        !           310:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           311:        while (enumerator->enumerate(enumerator, &proposal))
        !           312:        {
        !           313:                proposal->set_spi(proposal, this->my_spi);
        !           314: 
        !           315:                /* move the selected DH group to the front, if any */
        !           316:                if (this->dh_group != MODP_NONE)
        !           317:                {       /* proposals that don't contain the selected group are
        !           318:                         * moved to the back */
        !           319:                        if (!proposal->promote_dh_group(proposal, this->dh_group))
        !           320:                        {
        !           321:                                this->proposals->remove_at(this->proposals, enumerator);
        !           322:                                other_dh_groups->insert_last(other_dh_groups, proposal);
        !           323:                        }
        !           324:                        else
        !           325:                        {
        !           326:                                found = TRUE;
        !           327:                        }
        !           328:                }
        !           329:        }
        !           330:        enumerator->destroy(enumerator);
        !           331:        enumerator = other_dh_groups->create_enumerator(other_dh_groups);
        !           332:        while (enumerator->enumerate(enumerator, (void**)&proposal))
        !           333:        {       /* no need to remove from the list as we destroy it anyway*/
        !           334:                this->proposals->insert_last(this->proposals, proposal);
        !           335:        }
        !           336:        enumerator->destroy(enumerator);
        !           337:        other_dh_groups->destroy(other_dh_groups);
        !           338: 
        !           339:        return this->dh_group == MODP_NONE || found;
        !           340: }
        !           341: 
        !           342: /**
        !           343:  * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
        !           344:  */
        !           345: static void schedule_inactivity_timeout(private_child_create_t *this)
        !           346: {
        !           347:        uint32_t timeout, id;
        !           348:        bool close_ike;
        !           349: 
        !           350:        timeout = this->config->get_inactivity(this->config);
        !           351:        if (timeout)
        !           352:        {
        !           353:                close_ike = lib->settings->get_bool(lib->settings,
        !           354:                                                                        "%s.inactivity_close_ike", FALSE, lib->ns);
        !           355:                id = this->child_sa->get_unique_id(this->child_sa);
        !           356:                lib->scheduler->schedule_job(lib->scheduler, (job_t*)
        !           357:                                                inactivity_job_create(id, timeout, close_ike), timeout);
        !           358:        }
        !           359: }
        !           360: 
        !           361: /**
        !           362:  * Check if we have a an address pool configured
        !           363:  */
        !           364: static bool have_pool(ike_sa_t *ike_sa)
        !           365: {
        !           366:        enumerator_t *enumerator;
        !           367:        peer_cfg_t *peer_cfg;
        !           368:        char *pool;
        !           369:        bool found = FALSE;
        !           370: 
        !           371:        peer_cfg = ike_sa->get_peer_cfg(ike_sa);
        !           372:        if (peer_cfg)
        !           373:        {
        !           374:                enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
        !           375:                if (enumerator->enumerate(enumerator, &pool))
        !           376:                {
        !           377:                        found = TRUE;
        !           378:                }
        !           379:                enumerator->destroy(enumerator);
        !           380:        }
        !           381:        return found;
        !           382: }
        !           383: 
        !           384: /**
        !           385:  * Get hosts to use for dynamic traffic selectors
        !           386:  */
        !           387: static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
        !           388: {
        !           389:        enumerator_t *enumerator;
        !           390:        linked_list_t *list;
        !           391:        host_t *host;
        !           392: 
        !           393:        list = linked_list_create();
        !           394:        enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
        !           395:        while (enumerator->enumerate(enumerator, &host))
        !           396:        {
        !           397:                list->insert_last(list, host);
        !           398:        }
        !           399:        enumerator->destroy(enumerator);
        !           400: 
        !           401:        if (list->get_count(list) == 0)
        !           402:        {       /* no virtual IPs assigned */
        !           403:                if (local)
        !           404:                {
        !           405:                        host = ike_sa->get_my_host(ike_sa);
        !           406:                        list->insert_last(list, host);
        !           407:                }
        !           408:                else if (!have_pool(ike_sa))
        !           409:                {       /* use host only if we don't have a pool configured */
        !           410:                        host = ike_sa->get_other_host(ike_sa);
        !           411:                        list->insert_last(list, host);
        !           412:                }
        !           413:        }
        !           414:        return list;
        !           415: }
        !           416: 
        !           417: /**
        !           418:  * Substitute any host address with NATed address in traffic selector
        !           419:  */
        !           420: static linked_list_t* get_transport_nat_ts(private_child_create_t *this,
        !           421:                                                                                   bool local, linked_list_t *in)
        !           422: {
        !           423:        enumerator_t *enumerator;
        !           424:        linked_list_t *out;
        !           425:        traffic_selector_t *ts;
        !           426:        host_t *ike, *first = NULL;
        !           427:        uint8_t mask;
        !           428: 
        !           429:        if (local)
        !           430:        {
        !           431:                ike = this->ike_sa->get_my_host(this->ike_sa);
        !           432:        }
        !           433:        else
        !           434:        {
        !           435:                ike = this->ike_sa->get_other_host(this->ike_sa);
        !           436:        }
        !           437: 
        !           438:        out = linked_list_create();
        !           439: 
        !           440:        enumerator = in->create_enumerator(in);
        !           441:        while (enumerator->enumerate(enumerator, &ts))
        !           442:        {
        !           443:                /* require that all selectors match the first "host" selector */
        !           444:                if (ts->is_host(ts, first))
        !           445:                {
        !           446:                        if (!first)
        !           447:                        {
        !           448:                                ts->to_subnet(ts, &first, &mask);
        !           449:                        }
        !           450:                        ts = ts->clone(ts);
        !           451:                        ts->set_address(ts, ike);
        !           452:                        out->insert_last(out, ts);
        !           453:                }
        !           454:        }
        !           455:        enumerator->destroy(enumerator);
        !           456:        DESTROY_IF(first);
        !           457: 
        !           458:        return out;
        !           459: }
        !           460: 
        !           461: /**
        !           462:  * Narrow received traffic selectors with configuration
        !           463:  */
        !           464: static linked_list_t* narrow_ts(private_child_create_t *this, bool local,
        !           465:                                                                linked_list_t *in)
        !           466: {
        !           467:        linked_list_t *hosts, *nat, *ts;
        !           468:        ike_condition_t cond;
        !           469: 
        !           470:        cond = local ? COND_NAT_HERE : COND_NAT_THERE;
        !           471:        hosts = get_dynamic_hosts(this->ike_sa, local);
        !           472: 
        !           473:        if (this->mode == MODE_TRANSPORT &&
        !           474:                this->ike_sa->has_condition(this->ike_sa, cond))
        !           475:        {
        !           476:                nat = get_transport_nat_ts(this, local, in);
        !           477:                ts = this->config->get_traffic_selectors(this->config, local, nat,
        !           478:                                                                                                 hosts, TRUE);
        !           479:                nat->destroy_offset(nat, offsetof(traffic_selector_t, destroy));
        !           480:        }
        !           481:        else
        !           482:        {
        !           483:                ts = this->config->get_traffic_selectors(this->config, local, in,
        !           484:                                                                                                 hosts, TRUE);
        !           485:        }
        !           486: 
        !           487:        hosts->destroy(hosts);
        !           488: 
        !           489:        return ts;
        !           490: }
        !           491: 
        !           492: /**
        !           493:  * Check if requested mode is acceptable
        !           494:  */
        !           495: static bool check_mode(private_child_create_t *this, host_t *i, host_t *r)
        !           496: {
        !           497:        switch (this->mode)
        !           498:        {
        !           499:                case MODE_TRANSPORT:
        !           500:                        if (!this->config->has_option(this->config, OPT_PROXY_MODE) &&
        !           501:                                   (!ts_list_is_host(this->tsi, i) ||
        !           502:                                        !ts_list_is_host(this->tsr, r))
        !           503:                           )
        !           504:                        {
        !           505:                                DBG1(DBG_IKE, "not using transport mode, not host-to-host");
        !           506:                                return FALSE;
        !           507:                        }
        !           508:                        if (this->config->get_mode(this->config) != MODE_TRANSPORT)
        !           509:                        {
        !           510:                                return FALSE;
        !           511:                        }
        !           512:                        break;
        !           513:                case MODE_BEET:
        !           514:                        if (!ts_list_is_host(this->tsi, NULL) ||
        !           515:                                !ts_list_is_host(this->tsr, NULL))
        !           516:                        {
        !           517:                                DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
        !           518:                                return FALSE;
        !           519:                        }
        !           520:                        if (this->config->get_mode(this->config) != MODE_BEET)
        !           521:                        {
        !           522:                                return FALSE;
        !           523:                        }
        !           524:                        break;
        !           525:                default:
        !           526:                        break;
        !           527:        }
        !           528:        return TRUE;
        !           529: }
        !           530: 
        !           531: /**
        !           532:  * Install a CHILD_SA for usage, return value:
        !           533:  * - FAILED: no acceptable proposal
        !           534:  * - INVALID_ARG: diffie hellman group unacceptable
        !           535:  * - NOT_FOUND: TS unacceptable
        !           536:  */
        !           537: static status_t select_and_install(private_child_create_t *this,
        !           538:                                                                   bool no_dh, bool ike_auth)
        !           539: {
        !           540:        status_t status, status_i, status_o;
        !           541:        child_sa_outbound_state_t out_state;
        !           542:        chunk_t nonce_i, nonce_r;
        !           543:        chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
        !           544:        chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
        !           545:        linked_list_t *my_ts, *other_ts;
        !           546:        host_t *me, *other;
        !           547:        proposal_selection_flag_t flags = 0;
        !           548: 
        !           549:        if (this->proposals == NULL)
        !           550:        {
        !           551:                DBG1(DBG_IKE, "SA payload missing in message");
        !           552:                return FAILED;
        !           553:        }
        !           554:        if (this->tsi == NULL || this->tsr == NULL)
        !           555:        {
        !           556:                DBG1(DBG_IKE, "TS payloads missing in message");
        !           557:                return NOT_FOUND;
        !           558:        }
        !           559: 
        !           560:        me = this->ike_sa->get_my_host(this->ike_sa);
        !           561:        other = this->ike_sa->get_other_host(this->ike_sa);
        !           562: 
        !           563:        if (no_dh)
        !           564:        {
        !           565:                flags |= PROPOSAL_SKIP_DH;
        !           566:        }
        !           567:        if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
        !           568:                !lib->settings->get_bool(lib->settings, "%s.accept_private_algs",
        !           569:                                                                 FALSE, lib->ns))
        !           570:        {
        !           571:                flags |= PROPOSAL_SKIP_PRIVATE;
        !           572:        }
        !           573:        if (!lib->settings->get_bool(lib->settings,
        !           574:                                                        "%s.prefer_configured_proposals", TRUE, lib->ns))
        !           575:        {
        !           576:                flags |= PROPOSAL_PREFER_SUPPLIED;
        !           577:        }
        !           578:        this->proposal = this->config->select_proposal(this->config,
        !           579:                                                                                                   this->proposals, flags);
        !           580:        if (this->proposal == NULL)
        !           581:        {
        !           582:                DBG1(DBG_IKE, "no acceptable proposal found");
        !           583:                charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD,
        !           584:                                                   this->proposals);
        !           585:                return FAILED;
        !           586:        }
        !           587:        this->other_spi = this->proposal->get_spi(this->proposal);
        !           588: 
        !           589:        if (!this->initiator)
        !           590:        {
        !           591:                if (!allocate_spi(this))
        !           592:                {
        !           593:                        /* responder has no SPI allocated yet */
        !           594:                        DBG1(DBG_IKE, "allocating SPI failed");
        !           595:                        return FAILED;
        !           596:                }
        !           597:                this->proposal->set_spi(this->proposal, this->my_spi);
        !           598:        }
        !           599:        this->child_sa->set_proposal(this->child_sa, this->proposal);
        !           600: 
        !           601:        if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
        !           602:        {
        !           603:                uint16_t group;
        !           604: 
        !           605:                if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
        !           606:                                                                                  &group, NULL))
        !           607:                {
        !           608:                        DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
        !           609:                                 diffie_hellman_group_names, this->dh_group,
        !           610:                                 diffie_hellman_group_names, group);
        !           611:                        this->dh_group = group;
        !           612:                        return INVALID_ARG;
        !           613:                }
        !           614:                /* the selected proposal does not use a DH group */
        !           615:                DBG1(DBG_IKE, "ignoring KE exchange, agreed on a non-PFS proposal");
        !           616:                DESTROY_IF(this->dh);
        !           617:                this->dh = NULL;
        !           618:                this->dh_group = MODP_NONE;
        !           619:        }
        !           620: 
        !           621:        if (this->initiator)
        !           622:        {
        !           623:                nonce_i = this->my_nonce;
        !           624:                nonce_r = this->other_nonce;
        !           625:                my_ts = narrow_ts(this, TRUE, this->tsi);
        !           626:                other_ts = narrow_ts(this, FALSE, this->tsr);
        !           627:        }
        !           628:        else
        !           629:        {
        !           630:                nonce_r = this->my_nonce;
        !           631:                nonce_i = this->other_nonce;
        !           632:                my_ts = narrow_ts(this, TRUE, this->tsr);
        !           633:                other_ts = narrow_ts(this, FALSE, this->tsi);
        !           634:        }
        !           635: 
        !           636:        if (this->initiator)
        !           637:        {
        !           638:                if (ike_auth)
        !           639:                {
        !           640:                        charon->bus->narrow(charon->bus, this->child_sa,
        !           641:                                                                NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
        !           642:                }
        !           643:                else
        !           644:                {
        !           645:                        charon->bus->narrow(charon->bus, this->child_sa,
        !           646:                                                                NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
        !           647:                }
        !           648:        }
        !           649:        else
        !           650:        {
        !           651:                charon->bus->narrow(charon->bus, this->child_sa,
        !           652:                                                        NARROW_RESPONDER, my_ts, other_ts);
        !           653:        }
        !           654: 
        !           655:        if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
        !           656:        {
        !           657:                charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
        !           658:                my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
        !           659:                other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
        !           660:                DBG1(DBG_IKE, "no acceptable traffic selectors found");
        !           661:                return NOT_FOUND;
        !           662:        }
        !           663: 
        !           664:        this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
        !           665:        this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
        !           666:        if (this->initiator)
        !           667:        {
        !           668:                this->tsi = my_ts;
        !           669:                this->tsr = other_ts;
        !           670: 
        !           671:                if (!check_mode(this, me, other))
        !           672:                {
        !           673:                        DBG1(DBG_IKE, "%N mode requested by responder is unacceptable",
        !           674:                                 ipsec_mode_names, this->mode);
        !           675:                        return FAILED;
        !           676:                }
        !           677:        }
        !           678:        else
        !           679:        {
        !           680:                this->tsr = my_ts;
        !           681:                this->tsi = other_ts;
        !           682: 
        !           683:                if (!check_mode(this, other, me))
        !           684:                {
        !           685:                        this->mode = MODE_TUNNEL;
        !           686:                }
        !           687:        }
        !           688: 
        !           689:        if (!this->initiator)
        !           690:        {
        !           691:                /* use a copy of the traffic selectors, as the POST hook should not
        !           692:                 * change payloads */
        !           693:                my_ts = this->tsr->clone_offset(this->tsr,
        !           694:                                                                                offsetof(traffic_selector_t, clone));
        !           695:                other_ts = this->tsi->clone_offset(this->tsi,
        !           696:                                                                                offsetof(traffic_selector_t, clone));
        !           697:                charon->bus->narrow(charon->bus, this->child_sa,
        !           698:                                                        NARROW_RESPONDER_POST, my_ts, other_ts);
        !           699: 
        !           700:                if (my_ts->get_count(my_ts) == 0 ||     other_ts->get_count(other_ts) == 0)
        !           701:                {
        !           702:                        my_ts->destroy_offset(my_ts,
        !           703:                                                                  offsetof(traffic_selector_t, destroy));
        !           704:                        other_ts->destroy_offset(other_ts,
        !           705:                                                                  offsetof(traffic_selector_t, destroy));
        !           706:                        return NOT_FOUND;
        !           707:                }
        !           708:        }
        !           709: 
        !           710:        this->child_sa->set_policies(this->child_sa, my_ts, other_ts);
        !           711:        if (!this->initiator)
        !           712:        {
        !           713:                my_ts->destroy_offset(my_ts,
        !           714:                                                          offsetof(traffic_selector_t, destroy));
        !           715:                other_ts->destroy_offset(other_ts,
        !           716:                                                          offsetof(traffic_selector_t, destroy));
        !           717:        }
        !           718: 
        !           719:        this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
        !           720:        this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
        !           721:        this->child_sa->set_mode(this->child_sa, this->mode);
        !           722:        this->child_sa->set_protocol(this->child_sa,
        !           723:                                                                 this->proposal->get_protocol(this->proposal));
        !           724: 
        !           725:        if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
        !           726:        {
        !           727:                this->my_cpi = this->other_cpi = 0;
        !           728:                this->ipcomp = IPCOMP_NONE;
        !           729:        }
        !           730:        status_i = status_o = FAILED;
        !           731:        if (this->keymat->derive_child_keys(this->keymat, this->proposal,
        !           732:                        this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
        !           733:        {
        !           734:                if (this->initiator)
        !           735:                {
        !           736:                        status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
        !           737:                                                        this->my_spi, this->my_cpi, this->initiator,
        !           738:                                                        TRUE, this->tfcv3);
        !           739:                }
        !           740:                else
        !           741:                {
        !           742:                        status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
        !           743:                                                        this->my_spi, this->my_cpi, this->initiator,
        !           744:                                                        TRUE, this->tfcv3);
        !           745:                }
        !           746:                if (this->rekey)
        !           747:                {       /* during rekeyings we install the outbound SA and/or policies
        !           748:                         * separately: as responder when we receive the delete for the old
        !           749:                         * SA, as initiator pretty much immediately in the ike-rekey task,
        !           750:                         * unless there was a rekey collision that we lost */
        !           751:                        if (this->initiator)
        !           752:                        {
        !           753:                                status_o = this->child_sa->register_outbound(this->child_sa,
        !           754:                                                        encr_i, integ_i, this->other_spi, this->other_cpi,
        !           755:                                                        this->tfcv3);
        !           756:                        }
        !           757:                        else
        !           758:                        {
        !           759:                                status_o = this->child_sa->register_outbound(this->child_sa,
        !           760:                                                        encr_r, integ_r, this->other_spi, this->other_cpi,
        !           761:                                                        this->tfcv3);
        !           762:                        }
        !           763:                }
        !           764:                else if (this->initiator)
        !           765:                {
        !           766:                        status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
        !           767:                                                        this->other_spi, this->other_cpi, this->initiator,
        !           768:                                                        FALSE, this->tfcv3);
        !           769:                }
        !           770:                else
        !           771:                {
        !           772:                        status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
        !           773:                                                        this->other_spi, this->other_cpi, this->initiator,
        !           774:                                                        FALSE, this->tfcv3);
        !           775:                }
        !           776:        }
        !           777: 
        !           778:        if (status_i != SUCCESS || status_o != SUCCESS)
        !           779:        {
        !           780:                DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
        !           781:                        (status_i != SUCCESS) ? "inbound " : "",
        !           782:                        (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
        !           783:                        (status_o != SUCCESS) ? "outbound " : "");
        !           784:                charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
        !           785:                                                   this->child_sa);
        !           786:                status = FAILED;
        !           787:        }
        !           788:        else
        !           789:        {
        !           790:                status = this->child_sa->install_policies(this->child_sa);
        !           791: 
        !           792:                if (status != SUCCESS)
        !           793:                {
        !           794:                        DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
        !           795:                        charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
        !           796:                                                           this->child_sa);
        !           797:                        status = NOT_FOUND;
        !           798:                }
        !           799:                else
        !           800:                {
        !           801:                        charon->bus->child_derived_keys(charon->bus, this->child_sa,
        !           802:                                                                                        this->initiator, encr_i, encr_r,
        !           803:                                                                                        integ_i, integ_r);
        !           804:                }
        !           805:        }
        !           806:        chunk_clear(&integ_i);
        !           807:        chunk_clear(&integ_r);
        !           808:        chunk_clear(&encr_i);
        !           809:        chunk_clear(&encr_r);
        !           810: 
        !           811:        if (status != SUCCESS)
        !           812:        {
        !           813:                return status;
        !           814:        }
        !           815: 
        !           816:        charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
        !           817:                                                        this->dh, nonce_i, nonce_r);
        !           818: 
        !           819:        my_ts = linked_list_create_from_enumerator(
        !           820:                                this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
        !           821:        other_ts = linked_list_create_from_enumerator(
        !           822:                                this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
        !           823:        out_state = this->child_sa->get_outbound_state(this->child_sa);
        !           824: 
        !           825:        DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
        !           826:                 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
        !           827:                 (out_state == CHILD_OUTBOUND_INSTALLED) ? "" : "inbound ",
        !           828:                 this->child_sa->get_name(this->child_sa),
        !           829:                 this->child_sa->get_unique_id(this->child_sa),
        !           830:                 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
        !           831:                 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
        !           832:                 my_ts, other_ts);
        !           833: 
        !           834:        my_ts->destroy(my_ts);
        !           835:        other_ts->destroy(other_ts);
        !           836: 
        !           837:        this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
        !           838:        this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
        !           839:        this->established = TRUE;
        !           840: 
        !           841:        schedule_inactivity_timeout(this);
        !           842:        return SUCCESS;
        !           843: }
        !           844: 
        !           845: /**
        !           846:  * build the payloads for the message
        !           847:  */
        !           848: static bool build_payloads(private_child_create_t *this, message_t *message)
        !           849: {
        !           850:        sa_payload_t *sa_payload;
        !           851:        nonce_payload_t *nonce_payload;
        !           852:        ke_payload_t *ke_payload;
        !           853:        ts_payload_t *ts_payload;
        !           854:        kernel_feature_t features;
        !           855: 
        !           856:        /* add SA payload */
        !           857:        if (this->initiator)
        !           858:        {
        !           859:                sa_payload = sa_payload_create_from_proposals_v2(this->proposals);
        !           860:        }
        !           861:        else
        !           862:        {
        !           863:                sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
        !           864:        }
        !           865:        message->add_payload(message, (payload_t*)sa_payload);
        !           866: 
        !           867:        /* add nonce payload if not in IKE_AUTH */
        !           868:        if (message->get_exchange_type(message) == CREATE_CHILD_SA)
        !           869:        {
        !           870:                nonce_payload = nonce_payload_create(PLV2_NONCE);
        !           871:                nonce_payload->set_nonce(nonce_payload, this->my_nonce);
        !           872:                message->add_payload(message, (payload_t*)nonce_payload);
        !           873:        }
        !           874: 
        !           875:        /* diffie hellman exchange, if PFS enabled */
        !           876:        if (this->dh)
        !           877:        {
        !           878:                ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
        !           879:                                                                                                                   this->dh);
        !           880:                if (!ke_payload)
        !           881:                {
        !           882:                        DBG1(DBG_IKE, "creating KE payload failed");
        !           883:                        return FALSE;
        !           884:                }
        !           885:                message->add_payload(message, (payload_t*)ke_payload);
        !           886:        }
        !           887: 
        !           888:        /* add TSi/TSr payloads */
        !           889:        ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
        !           890:        message->add_payload(message, (payload_t*)ts_payload);
        !           891:        ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
        !           892:        message->add_payload(message, (payload_t*)ts_payload);
        !           893: 
        !           894:        /* add a notify if we are not in tunnel mode */
        !           895:        switch (this->mode)
        !           896:        {
        !           897:                case MODE_TRANSPORT:
        !           898:                        message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
        !           899:                        break;
        !           900:                case MODE_BEET:
        !           901:                        message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
        !           902:                        break;
        !           903:                default:
        !           904:                        break;
        !           905:        }
        !           906: 
        !           907:        features = charon->kernel->get_features(charon->kernel);
        !           908:        if (!(features & KERNEL_ESP_V3_TFC))
        !           909:        {
        !           910:                message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
        !           911:                                                        chunk_empty);
        !           912:        }
        !           913:        return TRUE;
        !           914: }
        !           915: 
        !           916: /**
        !           917:  * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
        !           918:  */
        !           919: static void add_ipcomp_notify(private_child_create_t *this,
        !           920:                                                                  message_t *message, uint8_t ipcomp)
        !           921: {
        !           922:        this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
        !           923:        if (this->my_cpi)
        !           924:        {
        !           925:                this->ipcomp = ipcomp;
        !           926:                message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
        !           927:                                                        chunk_cata("cc", chunk_from_thing(this->my_cpi),
        !           928:                                                                           chunk_from_thing(ipcomp)));
        !           929:        }
        !           930:        else
        !           931:        {
        !           932:                DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
        !           933:        }
        !           934: }
        !           935: 
        !           936: /**
        !           937:  * handle a received notify payload
        !           938:  */
        !           939: static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
        !           940: {
        !           941:        switch (notify->get_notify_type(notify))
        !           942:        {
        !           943:                case USE_TRANSPORT_MODE:
        !           944:                        this->mode = MODE_TRANSPORT;
        !           945:                        break;
        !           946:                case USE_BEET_MODE:
        !           947:                        if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
        !           948:                        {       /* handle private use notify only if we know its meaning */
        !           949:                                this->mode = MODE_BEET;
        !           950:                        }
        !           951:                        else
        !           952:                        {
        !           953:                                DBG1(DBG_IKE, "received a notify strongSwan uses for BEET "
        !           954:                                         "mode, but peer implementation unknown, skipped");
        !           955:                        }
        !           956:                        break;
        !           957:                case IPCOMP_SUPPORTED:
        !           958:                {
        !           959:                        ipcomp_transform_t ipcomp;
        !           960:                        uint16_t cpi;
        !           961:                        chunk_t data;
        !           962: 
        !           963:                        data = notify->get_notification_data(notify);
        !           964:                        cpi = *(uint16_t*)data.ptr;
        !           965:                        ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
        !           966:                        switch (ipcomp)
        !           967:                        {
        !           968:                                case IPCOMP_DEFLATE:
        !           969:                                        this->other_cpi = cpi;
        !           970:                                        this->ipcomp_received = ipcomp;
        !           971:                                        break;
        !           972:                                case IPCOMP_LZS:
        !           973:                                case IPCOMP_LZJH:
        !           974:                                default:
        !           975:                                        DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
        !           976:                                                 "transform ID we don't support %N",
        !           977:                                                 ipcomp_transform_names, ipcomp);
        !           978:                                        break;
        !           979:                        }
        !           980:                        break;
        !           981:                }
        !           982:                case ESP_TFC_PADDING_NOT_SUPPORTED:
        !           983:                        DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding",
        !           984:                                 notify_type_names, notify->get_notify_type(notify));
        !           985:                        this->tfcv3 = FALSE;
        !           986:                        break;
        !           987:                default:
        !           988:                        break;
        !           989:        }
        !           990: }
        !           991: 
        !           992: /**
        !           993:  * Read payloads from message
        !           994:  */
        !           995: static void process_payloads(private_child_create_t *this, message_t *message)
        !           996: {
        !           997:        enumerator_t *enumerator;
        !           998:        payload_t *payload;
        !           999:        sa_payload_t *sa_payload;
        !          1000:        ke_payload_t *ke_payload;
        !          1001:        ts_payload_t *ts_payload;
        !          1002: 
        !          1003:        /* defaults to TUNNEL mode */
        !          1004:        this->mode = MODE_TUNNEL;
        !          1005: 
        !          1006:        enumerator = message->create_payload_enumerator(message);
        !          1007:        while (enumerator->enumerate(enumerator, &payload))
        !          1008:        {
        !          1009:                switch (payload->get_type(payload))
        !          1010:                {
        !          1011:                        case PLV2_SECURITY_ASSOCIATION:
        !          1012:                                sa_payload = (sa_payload_t*)payload;
        !          1013:                                this->proposals = sa_payload->get_proposals(sa_payload);
        !          1014:                                break;
        !          1015:                        case PLV2_KEY_EXCHANGE:
        !          1016:                                ke_payload = (ke_payload_t*)payload;
        !          1017:                                if (!this->initiator)
        !          1018:                                {
        !          1019:                                        this->dh_group = ke_payload->get_dh_group_number(ke_payload);
        !          1020:                                        this->dh = this->keymat->keymat.create_dh(
        !          1021:                                                                                &this->keymat->keymat, this->dh_group);
        !          1022:                                }
        !          1023:                                else if (this->dh)
        !          1024:                                {
        !          1025:                                        this->dh_failed = this->dh->get_dh_group(this->dh) !=
        !          1026:                                                                        ke_payload->get_dh_group_number(ke_payload);
        !          1027:                                }
        !          1028:                                if (this->dh && !this->dh_failed)
        !          1029:                                {
        !          1030:                                        this->dh_failed = !this->dh->set_other_public_value(this->dh,
        !          1031:                                                                ke_payload->get_key_exchange_data(ke_payload));
        !          1032:                                }
        !          1033:                                break;
        !          1034:                        case PLV2_TS_INITIATOR:
        !          1035:                                ts_payload = (ts_payload_t*)payload;
        !          1036:                                this->tsi = ts_payload->get_traffic_selectors(ts_payload);
        !          1037:                                break;
        !          1038:                        case PLV2_TS_RESPONDER:
        !          1039:                                ts_payload = (ts_payload_t*)payload;
        !          1040:                                this->tsr = ts_payload->get_traffic_selectors(ts_payload);
        !          1041:                                break;
        !          1042:                        case PLV2_NOTIFY:
        !          1043:                                handle_notify(this, (notify_payload_t*)payload);
        !          1044:                                break;
        !          1045:                        default:
        !          1046:                                break;
        !          1047:                }
        !          1048:        }
        !          1049:        enumerator->destroy(enumerator);
        !          1050: }
        !          1051: 
        !          1052: /**
        !          1053:  * Check if we should defer the creation of this CHILD_SA until after the
        !          1054:  * IKE_SA has been established childless.
        !          1055:  */
        !          1056: static status_t defer_child_sa(private_child_create_t *this)
        !          1057: {
        !          1058:        ike_cfg_t *ike_cfg;
        !          1059: 
        !          1060:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
        !          1061: 
        !          1062:        if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_CHILDLESS))
        !          1063:        {
        !          1064:                if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
        !          1065:                {
        !          1066:                        return NEED_MORE;
        !          1067:                }
        !          1068:        }
        !          1069:        else if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
        !          1070:        {
        !          1071:                DBG1(DBG_IKE, "peer does not support childless IKE_SA initiation");
        !          1072:                return DESTROY_ME;
        !          1073:        }
        !          1074:        return NOT_SUPPORTED;
        !          1075: }
        !          1076: 
        !          1077: METHOD(task_t, build_i, status_t,
        !          1078:        private_child_create_t *this, message_t *message)
        !          1079: {
        !          1080:        enumerator_t *enumerator;
        !          1081:        host_t *vip;
        !          1082:        peer_cfg_t *peer_cfg;
        !          1083:        linked_list_t *list;
        !          1084: 
        !          1085:        switch (message->get_exchange_type(message))
        !          1086:        {
        !          1087:                case IKE_SA_INIT:
        !          1088:                        return get_nonce(message, &this->my_nonce);
        !          1089:                case CREATE_CHILD_SA:
        !          1090:                        if (!generate_nonce(this))
        !          1091:                        {
        !          1092:                                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
        !          1093:                                                                        chunk_empty);
        !          1094:                                return SUCCESS;
        !          1095:                        }
        !          1096:                        if (!this->retry && this->dh_group == MODP_NONE)
        !          1097:                        {       /* during a rekeying the group might already be set */
        !          1098:                                this->dh_group = this->config->get_dh_group(this->config);
        !          1099:                        }
        !          1100:                        break;
        !          1101:                case IKE_AUTH:
        !          1102:                        if (message->get_message_id(message) != 1)
        !          1103:                        {
        !          1104:                                /* send only in the first request, not in subsequent rounds */
        !          1105:                                return NEED_MORE;
        !          1106:                        }
        !          1107:                        switch (defer_child_sa(this))
        !          1108:                        {
        !          1109:                                case DESTROY_ME:
        !          1110:                                        /* config mismatch */
        !          1111:                                        return DESTROY_ME;
        !          1112:                                case NEED_MORE:
        !          1113:                                        /* defer until after IKE_SA has been established */
        !          1114:                                        chunk_free(&this->my_nonce);
        !          1115:                                        return NEED_MORE;
        !          1116:                                default:
        !          1117:                                        /* just continue to establish the CHILD_SA */
        !          1118:                                        break;
        !          1119:                        }
        !          1120:                        break;
        !          1121:                default:
        !          1122:                        break;
        !          1123:        }
        !          1124: 
        !          1125:        /* check if we want a virtual IP, but don't have one */
        !          1126:        list = linked_list_create();
        !          1127:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !          1128:        if (!this->rekey)
        !          1129:        {
        !          1130:                enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
        !          1131:                while (enumerator->enumerate(enumerator, &vip))
        !          1132:                {
        !          1133:                        /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
        !          1134:                        vip = host_create_any(vip->get_family(vip));
        !          1135:                        list->insert_last(list, vip);
        !          1136:                }
        !          1137:                enumerator->destroy(enumerator);
        !          1138:        }
        !          1139:        if (list->get_count(list))
        !          1140:        {
        !          1141:                this->tsi = this->config->get_traffic_selectors(this->config,
        !          1142:                                                                                                                TRUE, NULL, list, TRUE);
        !          1143:                list->destroy_offset(list, offsetof(host_t, destroy));
        !          1144:        }
        !          1145:        else
        !          1146:        {       /* no virtual IPs configured */
        !          1147:                list->destroy(list);
        !          1148:                list = get_dynamic_hosts(this->ike_sa, TRUE);
        !          1149:                this->tsi = this->config->get_traffic_selectors(this->config,
        !          1150:                                                                                                                TRUE, NULL, list, TRUE);
        !          1151:                list->destroy(list);
        !          1152:        }
        !          1153:        list = get_dynamic_hosts(this->ike_sa, FALSE);
        !          1154:        this->tsr = this->config->get_traffic_selectors(this->config,
        !          1155:                                                                                                        FALSE, NULL, list, TRUE);
        !          1156:        list->destroy(list);
        !          1157: 
        !          1158:        if (this->packet_tsi)
        !          1159:        {
        !          1160:                this->tsi->insert_first(this->tsi,
        !          1161:                                                                this->packet_tsi->clone(this->packet_tsi));
        !          1162:        }
        !          1163:        if (this->packet_tsr)
        !          1164:        {
        !          1165:                this->tsr->insert_first(this->tsr,
        !          1166:                                                                this->packet_tsr->clone(this->packet_tsr));
        !          1167:        }
        !          1168:        this->proposals = this->config->get_proposals(this->config,
        !          1169:                                                                                                  this->dh_group == MODP_NONE);
        !          1170:        this->mode = this->config->get_mode(this->config);
        !          1171: 
        !          1172:        this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, TRUE);
        !          1173:        this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa, FALSE);
        !          1174:        this->child.encap = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
        !          1175:        this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
        !          1176:                                                                         this->ike_sa->get_other_host(this->ike_sa),
        !          1177:                                                                         this->config, &this->child);
        !          1178: 
        !          1179:        if (this->child.reqid)
        !          1180:        {
        !          1181:                DBG0(DBG_IKE, "establishing CHILD_SA %s{%d} reqid %d",
        !          1182:                         this->child_sa->get_name(this->child_sa),
        !          1183:                         this->child_sa->get_unique_id(this->child_sa), this->child.reqid);
        !          1184:        }
        !          1185:        else
        !          1186:        {
        !          1187:                DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
        !          1188:                         this->child_sa->get_name(this->child_sa),
        !          1189:                         this->child_sa->get_unique_id(this->child_sa));
        !          1190:        }
        !          1191: 
        !          1192:        if (!allocate_spi(this))
        !          1193:        {
        !          1194:                DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
        !          1195:                return FAILED;
        !          1196:        }
        !          1197: 
        !          1198:        if (!update_and_check_proposals(this))
        !          1199:        {
        !          1200:                DBG1(DBG_IKE, "requested DH group %N not contained in any of our "
        !          1201:                         "proposals",
        !          1202:                         diffie_hellman_group_names, this->dh_group);
        !          1203:                return FAILED;
        !          1204:        }
        !          1205: 
        !          1206:        if (this->dh_group != MODP_NONE)
        !          1207:        {
        !          1208:                this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
        !          1209:                                                                                                  this->dh_group);
        !          1210:        }
        !          1211: 
        !          1212:        if (this->config->has_option(this->config, OPT_IPCOMP))
        !          1213:        {
        !          1214:                /* IPCOMP_DEFLATE is the only transform we support at the moment */
        !          1215:                add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
        !          1216:        }
        !          1217: 
        !          1218:        if (message->get_exchange_type(message) == IKE_AUTH)
        !          1219:        {
        !          1220:                charon->bus->narrow(charon->bus, this->child_sa,
        !          1221:                                                        NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
        !          1222:        }
        !          1223:        else
        !          1224:        {
        !          1225:                charon->bus->narrow(charon->bus, this->child_sa,
        !          1226:                                                        NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
        !          1227:        }
        !          1228: 
        !          1229:        if (!build_payloads(this, message))
        !          1230:        {
        !          1231:                return FAILED;
        !          1232:        }
        !          1233: 
        !          1234:        this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
        !          1235:        this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
        !          1236:        this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
        !          1237:        this->tsi = NULL;
        !          1238:        this->tsr = NULL;
        !          1239:        this->proposals = NULL;
        !          1240: 
        !          1241:        return NEED_MORE;
        !          1242: }
        !          1243: 
        !          1244: METHOD(task_t, process_r, status_t,
        !          1245:        private_child_create_t *this, message_t *message)
        !          1246: {
        !          1247:        switch (message->get_exchange_type(message))
        !          1248:        {
        !          1249:                case IKE_SA_INIT:
        !          1250:                        return get_nonce(message, &this->other_nonce);
        !          1251:                case CREATE_CHILD_SA:
        !          1252:                        get_nonce(message, &this->other_nonce);
        !          1253:                        break;
        !          1254:                case IKE_AUTH:
        !          1255:                        if (message->get_message_id(message) != 1)
        !          1256:                        {
        !          1257:                                /* only handle first AUTH payload, not additional rounds */
        !          1258:                                return NEED_MORE;
        !          1259:                        }
        !          1260:                default:
        !          1261:                        break;
        !          1262:        }
        !          1263: 
        !          1264:        process_payloads(this, message);
        !          1265: 
        !          1266:        return NEED_MORE;
        !          1267: }
        !          1268: 
        !          1269: /**
        !          1270:  * handle CHILD_SA setup failure
        !          1271:  */
        !          1272: static void handle_child_sa_failure(private_child_create_t *this,
        !          1273:                                                                        message_t *message)
        !          1274: {
        !          1275:        bool is_first;
        !          1276: 
        !          1277:        is_first = message->get_exchange_type(message) == IKE_AUTH;
        !          1278:        if (is_first &&
        !          1279:                lib->settings->get_bool(lib->settings,
        !          1280:                                                                "%s.close_ike_on_child_failure", FALSE, lib->ns))
        !          1281:        {
        !          1282:                /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
        !          1283:                 * first */
        !          1284:                DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
        !          1285:                lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
        !          1286:                        delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
        !          1287:                        100);
        !          1288:        }
        !          1289:        else
        !          1290:        {
        !          1291:                DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
        !          1292:                charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE,
        !          1293:                                                   is_first);
        !          1294:        }
        !          1295: }
        !          1296: 
        !          1297: /**
        !          1298:  * Substitute transport mode NAT selectors, if applicable
        !          1299:  */
        !          1300: static linked_list_t* get_ts_if_nat_transport(private_child_create_t *this,
        !          1301:                                                                                          bool local, linked_list_t *in)
        !          1302: {
        !          1303:        linked_list_t *out = NULL;
        !          1304:        ike_condition_t cond;
        !          1305: 
        !          1306:        if (this->mode == MODE_TRANSPORT)
        !          1307:        {
        !          1308:                cond = local ? COND_NAT_HERE : COND_NAT_THERE;
        !          1309:                if (this->ike_sa->has_condition(this->ike_sa, cond))
        !          1310:                {
        !          1311:                        out = get_transport_nat_ts(this, local, in);
        !          1312:                        if (out->get_count(out) == 0)
        !          1313:                        {
        !          1314:                                out->destroy(out);
        !          1315:                                out = NULL;
        !          1316:                        }
        !          1317:                }
        !          1318:        }
        !          1319:        return out;
        !          1320: }
        !          1321: 
        !          1322: /**
        !          1323:  * Select a matching CHILD config as responder
        !          1324:  */
        !          1325: static child_cfg_t* select_child_cfg(private_child_create_t *this)
        !          1326: {
        !          1327:        peer_cfg_t *peer_cfg;
        !          1328:        child_cfg_t *child_cfg = NULL;;
        !          1329: 
        !          1330:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !          1331:        if (peer_cfg && this->tsi && this->tsr)
        !          1332:        {
        !          1333:                linked_list_t *listr, *listi, *tsr, *tsi;
        !          1334: 
        !          1335:                tsr = get_ts_if_nat_transport(this, TRUE, this->tsr);
        !          1336:                tsi = get_ts_if_nat_transport(this, FALSE, this->tsi);
        !          1337: 
        !          1338:                listr = get_dynamic_hosts(this->ike_sa, TRUE);
        !          1339:                listi = get_dynamic_hosts(this->ike_sa, FALSE);
        !          1340:                child_cfg = peer_cfg->select_child_cfg(peer_cfg,
        !          1341:                                                                                        tsr ?: this->tsr, tsi ?: this->tsi,
        !          1342:                                                                                        listr, listi);
        !          1343:                if ((tsi || tsr) && child_cfg &&
        !          1344:                        child_cfg->get_mode(child_cfg) != MODE_TRANSPORT)
        !          1345:                {
        !          1346:                        /* found a CHILD config, but it doesn't use transport mode */
        !          1347:                        child_cfg->destroy(child_cfg);
        !          1348:                        child_cfg = NULL;
        !          1349:                }
        !          1350:                if (!child_cfg && (tsi || tsr))
        !          1351:                {
        !          1352:                        /* no match for the substituted NAT selectors, try it without */
        !          1353:                        child_cfg = peer_cfg->select_child_cfg(peer_cfg,
        !          1354:                                                                                        this->tsr, this->tsi, listr, listi);
        !          1355:                }
        !          1356:                listr->destroy(listr);
        !          1357:                listi->destroy(listi);
        !          1358:                DESTROY_OFFSET_IF(tsi, offsetof(traffic_selector_t, destroy));
        !          1359:                DESTROY_OFFSET_IF(tsr, offsetof(traffic_selector_t, destroy));
        !          1360:        }
        !          1361: 
        !          1362:        return child_cfg;
        !          1363: }
        !          1364: 
        !          1365: /**
        !          1366:  * Check how to handle a possibly childless IKE_SA
        !          1367:  */
        !          1368: static status_t handle_childless(private_child_create_t *this)
        !          1369: {
        !          1370:        ike_cfg_t *ike_cfg;
        !          1371: 
        !          1372:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
        !          1373: 
        !          1374:        if (!this->proposals && !this->tsi && !this->tsr)
        !          1375:        {
        !          1376:                /* looks like a childless IKE_SA, check if we allow it */
        !          1377:                if (ike_cfg->childless(ike_cfg) == CHILDLESS_NEVER)
        !          1378:                {
        !          1379:                        /* we don't allow childless initiation */
        !          1380:                        DBG1(DBG_IKE, "peer tried to initiate a childless IKE_SA");
        !          1381:                        return INVALID_STATE;
        !          1382:                }
        !          1383:                return SUCCESS;
        !          1384:        }
        !          1385: 
        !          1386:        /* the peer apparently wants to create a regular IKE_SA */
        !          1387:        if (ike_cfg->childless(ike_cfg) == CHILDLESS_FORCE)
        !          1388:        {
        !          1389:                /* reject it if we only allow childless initiation */
        !          1390:                DBG1(DBG_IKE, "peer did not initiate a childless IKE_SA");
        !          1391:                return INVALID_STATE;
        !          1392:        }
        !          1393:        return NOT_SUPPORTED;
        !          1394: }
        !          1395: 
        !          1396: METHOD(task_t, build_r, status_t,
        !          1397:        private_child_create_t *this, message_t *message)
        !          1398: {
        !          1399:        payload_t *payload;
        !          1400:        enumerator_t *enumerator;
        !          1401:        bool no_dh = TRUE, ike_auth = FALSE;
        !          1402: 
        !          1403:        switch (message->get_exchange_type(message))
        !          1404:        {
        !          1405:                case IKE_SA_INIT:
        !          1406:                        return get_nonce(message, &this->my_nonce);
        !          1407:                case CREATE_CHILD_SA:
        !          1408:                        if (!generate_nonce(this))
        !          1409:                        {
        !          1410:                                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
        !          1411:                                                                        chunk_empty);
        !          1412:                                return SUCCESS;
        !          1413:                        }
        !          1414:                        if (this->dh_failed)
        !          1415:                        {
        !          1416:                                DBG1(DBG_IKE, "applying DH public value failed");
        !          1417:                                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
        !          1418:                                                                        chunk_empty);
        !          1419:                                return SUCCESS;
        !          1420:                        }
        !          1421:                        no_dh = FALSE;
        !          1422:                        break;
        !          1423:                case IKE_AUTH:
        !          1424:                        if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
        !          1425:                        {       /* wait until all authentication round completed */
        !          1426:                                return NEED_MORE;
        !          1427:                        }
        !          1428:                        if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
        !          1429:                        {       /* no CHILD_SA is created for redirected SAs */
        !          1430:                                return SUCCESS;
        !          1431:                        }
        !          1432:                        switch (handle_childless(this))
        !          1433:                        {
        !          1434:                                case SUCCESS:
        !          1435:                                        /* no CHILD_SA built */
        !          1436:                                        return SUCCESS;
        !          1437:                                case INVALID_STATE:
        !          1438:                                        message->add_notify(message, FALSE, INVALID_SYNTAX,
        !          1439:                                                                                chunk_empty);
        !          1440:                                        return FAILED;
        !          1441:                                default:
        !          1442:                                        /* continue with regular initiation */
        !          1443:                                        break;
        !          1444:                        }
        !          1445:                        ike_auth = TRUE;
        !          1446:                default:
        !          1447:                        break;
        !          1448:        }
        !          1449: 
        !          1450:        if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
        !          1451:        {
        !          1452:                DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
        !          1453:                message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
        !          1454:                return SUCCESS;
        !          1455:        }
        !          1456:        if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
        !          1457:        {
        !          1458:                DBG1(DBG_IKE, "unable to create CHILD_SA while deleting IKE_SA");
        !          1459:                message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
        !          1460:                return SUCCESS;
        !          1461:        }
        !          1462: 
        !          1463:        if (this->config == NULL)
        !          1464:        {
        !          1465:                this->config = select_child_cfg(this);
        !          1466:        }
        !          1467:        if (this->config == NULL)
        !          1468:        {
        !          1469:                DBG1(DBG_IKE, "traffic selectors %#R === %#R unacceptable",
        !          1470:                         this->tsr, this->tsi);
        !          1471:                charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
        !          1472:                message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
        !          1473:                handle_child_sa_failure(this, message);
        !          1474:                return SUCCESS;
        !          1475:        }
        !          1476: 
        !          1477:        /* check if ike_config_t included non-critical error notifies */
        !          1478:        enumerator = message->create_payload_enumerator(message);
        !          1479:        while (enumerator->enumerate(enumerator, &payload))
        !          1480:        {
        !          1481:                if (payload->get_type(payload) == PLV2_NOTIFY)
        !          1482:                {
        !          1483:                        notify_payload_t *notify = (notify_payload_t*)payload;
        !          1484: 
        !          1485:                        switch (notify->get_notify_type(notify))
        !          1486:                        {
        !          1487:                                case INTERNAL_ADDRESS_FAILURE:
        !          1488:                                case FAILED_CP_REQUIRED:
        !          1489:                                {
        !          1490:                                        DBG1(DBG_IKE,"configuration payload negotiation "
        !          1491:                                                 "failed, no CHILD_SA built");
        !          1492:                                        enumerator->destroy(enumerator);
        !          1493:                                        handle_child_sa_failure(this, message);
        !          1494:                                        return SUCCESS;
        !          1495:                                }
        !          1496:                                default:
        !          1497:                                        break;
        !          1498:                        }
        !          1499:                }
        !          1500:        }
        !          1501:        enumerator->destroy(enumerator);
        !          1502: 
        !          1503:        this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, TRUE);
        !          1504:        this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa, FALSE);
        !          1505:        this->child.encap = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
        !          1506:        this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
        !          1507:                                                                         this->ike_sa->get_other_host(this->ike_sa),
        !          1508:                                                                         this->config, &this->child);
        !          1509: 
        !          1510:        if (this->ipcomp_received != IPCOMP_NONE)
        !          1511:        {
        !          1512:                if (this->config->has_option(this->config, OPT_IPCOMP))
        !          1513:                {
        !          1514:                        add_ipcomp_notify(this, message, this->ipcomp_received);
        !          1515:                }
        !          1516:                else
        !          1517:                {
        !          1518:                        DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
        !          1519:                                 notify_type_names, IPCOMP_SUPPORTED);
        !          1520:                }
        !          1521:        }
        !          1522: 
        !          1523:        switch (select_and_install(this, no_dh, ike_auth))
        !          1524:        {
        !          1525:                case SUCCESS:
        !          1526:                        break;
        !          1527:                case NOT_FOUND:
        !          1528:                        message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
        !          1529:                        handle_child_sa_failure(this, message);
        !          1530:                        return SUCCESS;
        !          1531:                case INVALID_ARG:
        !          1532:                {
        !          1533:                        uint16_t group = htons(this->dh_group);
        !          1534:                        message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
        !          1535:                                                                chunk_from_thing(group));
        !          1536:                        return SUCCESS;
        !          1537:                }
        !          1538:                case FAILED:
        !          1539:                default:
        !          1540:                        message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
        !          1541:                        handle_child_sa_failure(this, message);
        !          1542:                        return SUCCESS;
        !          1543:        }
        !          1544: 
        !          1545:        if (!build_payloads(this, message))
        !          1546:        {
        !          1547:                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
        !          1548:                handle_child_sa_failure(this, message);
        !          1549:                return SUCCESS;
        !          1550:        }
        !          1551: 
        !          1552:        if (!this->rekey)
        !          1553:        {       /* invoke the child_up() hook if we are not rekeying */
        !          1554:                charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
        !          1555:        }
        !          1556:        return SUCCESS;
        !          1557: }
        !          1558: 
        !          1559: /**
        !          1560:  * Raise alerts for received notify errors
        !          1561:  */
        !          1562: static void raise_alerts(private_child_create_t *this, notify_type_t type)
        !          1563: {
        !          1564:        linked_list_t *list;
        !          1565: 
        !          1566:        switch (type)
        !          1567:        {
        !          1568:                case NO_PROPOSAL_CHOSEN:
        !          1569:                        list = this->config->get_proposals(this->config, FALSE);
        !          1570:                        charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD, list);
        !          1571:                        list->destroy_offset(list, offsetof(proposal_t, destroy));
        !          1572:                        break;
        !          1573:                default:
        !          1574:                        break;
        !          1575:        }
        !          1576: }
        !          1577: 
        !          1578: METHOD(task_t, build_i_delete, status_t,
        !          1579:        private_child_create_t *this, message_t *message)
        !          1580: {
        !          1581:        message->set_exchange_type(message, INFORMATIONAL);
        !          1582:        if (this->my_spi && this->proto)
        !          1583:        {
        !          1584:                delete_payload_t *del;
        !          1585: 
        !          1586:                del = delete_payload_create(PLV2_DELETE, this->proto);
        !          1587:                del->add_spi(del, this->my_spi);
        !          1588:                message->add_payload(message, (payload_t*)del);
        !          1589: 
        !          1590:                DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
        !          1591:                         protocol_id_names, this->proto, ntohl(this->my_spi));
        !          1592:        }
        !          1593:        return NEED_MORE;
        !          1594: }
        !          1595: 
        !          1596: /**
        !          1597:  * Change task to delete the failed CHILD_SA as initiator
        !          1598:  */
        !          1599: static status_t delete_failed_sa(private_child_create_t *this)
        !          1600: {
        !          1601:        if (this->my_spi && this->proto)
        !          1602:        {
        !          1603:                this->public.task.build = _build_i_delete;
        !          1604:                this->public.task.process = (void*)return_success;
        !          1605:                return NEED_MORE;
        !          1606:        }
        !          1607:        return SUCCESS;
        !          1608: }
        !          1609: 
        !          1610: METHOD(task_t, process_i, status_t,
        !          1611:        private_child_create_t *this, message_t *message)
        !          1612: {
        !          1613:        enumerator_t *enumerator;
        !          1614:        payload_t *payload;
        !          1615:        bool no_dh = TRUE, ike_auth = FALSE;
        !          1616: 
        !          1617:        switch (message->get_exchange_type(message))
        !          1618:        {
        !          1619:                case IKE_SA_INIT:
        !          1620:                        return get_nonce(message, &this->other_nonce);
        !          1621:                case CREATE_CHILD_SA:
        !          1622:                        get_nonce(message, &this->other_nonce);
        !          1623:                        no_dh = FALSE;
        !          1624:                        break;
        !          1625:                case IKE_AUTH:
        !          1626:                        if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
        !          1627:                        {       /* wait until all authentication round completed */
        !          1628:                                return NEED_MORE;
        !          1629:                        }
        !          1630:                        if (defer_child_sa(this) == NEED_MORE)
        !          1631:                        {       /* defer until after IKE_SA has been established */
        !          1632:                                chunk_free(&this->other_nonce);
        !          1633:                                return NEED_MORE;
        !          1634:                        }
        !          1635:                        ike_auth = TRUE;
        !          1636:                default:
        !          1637:                        break;
        !          1638:        }
        !          1639: 
        !          1640:        /* check for erroneous notifies */
        !          1641:        enumerator = message->create_payload_enumerator(message);
        !          1642:        while (enumerator->enumerate(enumerator, &payload))
        !          1643:        {
        !          1644:                if (payload->get_type(payload) == PLV2_NOTIFY)
        !          1645:                {
        !          1646:                        notify_payload_t *notify = (notify_payload_t*)payload;
        !          1647:                        notify_type_t type = notify->get_notify_type(notify);
        !          1648: 
        !          1649:                        switch (type)
        !          1650:                        {
        !          1651:                                /* handle notify errors related to CHILD_SA only */
        !          1652:                                case NO_PROPOSAL_CHOSEN:
        !          1653:                                case SINGLE_PAIR_REQUIRED:
        !          1654:                                case NO_ADDITIONAL_SAS:
        !          1655:                                case INTERNAL_ADDRESS_FAILURE:
        !          1656:                                case FAILED_CP_REQUIRED:
        !          1657:                                case TS_UNACCEPTABLE:
        !          1658:                                case INVALID_SELECTORS:
        !          1659:                                {
        !          1660:                                        DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
        !          1661:                                                 notify_type_names, type);
        !          1662:                                        enumerator->destroy(enumerator);
        !          1663:                                        raise_alerts(this, type);
        !          1664:                                        handle_child_sa_failure(this, message);
        !          1665:                                        /* an error in CHILD_SA creation is not critical */
        !          1666:                                        return SUCCESS;
        !          1667:                                }
        !          1668:                                case TEMPORARY_FAILURE:
        !          1669:                                {
        !          1670:                                        DBG1(DBG_IKE, "received %N notify, will retry later",
        !          1671:                                                 notify_type_names, type);
        !          1672:                                        enumerator->destroy(enumerator);
        !          1673:                                        if (!this->rekey)
        !          1674:                                        {       /* the rekey task will retry itself if necessary */
        !          1675:                                                schedule_delayed_retry(this);
        !          1676:                                        }
        !          1677:                                        return SUCCESS;
        !          1678:                                }
        !          1679:                                case INVALID_KE_PAYLOAD:
        !          1680:                                {
        !          1681:                                        chunk_t data;
        !          1682:                                        uint16_t group = MODP_NONE;
        !          1683: 
        !          1684:                                        data = notify->get_notification_data(notify);
        !          1685:                                        if (data.len == sizeof(group))
        !          1686:                                        {
        !          1687:                                                memcpy(&group, data.ptr, data.len);
        !          1688:                                                group = ntohs(group);
        !          1689:                                        }
        !          1690:                                        if (this->retry)
        !          1691:                                        {
        !          1692:                                                DBG1(DBG_IKE, "already retried with DH group %N, "
        !          1693:                                                         "ignore requested %N", diffie_hellman_group_names,
        !          1694:                                                         this->dh_group, diffie_hellman_group_names, group);
        !          1695:                                                handle_child_sa_failure(this, message);
        !          1696:                                                /* an error in CHILD_SA creation is not critical */
        !          1697:                                                return SUCCESS;
        !          1698:                                        }
        !          1699:                                        DBG1(DBG_IKE, "peer didn't accept DH group %N, "
        !          1700:                                                 "it requested %N", diffie_hellman_group_names,
        !          1701:                                                 this->dh_group, diffie_hellman_group_names, group);
        !          1702:                                        this->retry = TRUE;
        !          1703:                                        this->dh_group = group;
        !          1704:                                        this->child_sa->set_state(this->child_sa, CHILD_RETRYING);
        !          1705:                                        this->public.task.migrate(&this->public.task, this->ike_sa);
        !          1706:                                        enumerator->destroy(enumerator);
        !          1707:                                        return NEED_MORE;
        !          1708:                                }
        !          1709:                                default:
        !          1710:                                {
        !          1711:                                        if (message->get_exchange_type(message) == CREATE_CHILD_SA)
        !          1712:                                        {       /* handle notifies if not handled in IKE_AUTH */
        !          1713:                                                if (type <= 16383)
        !          1714:                                                {
        !          1715:                                                        DBG1(DBG_IKE, "received %N notify error",
        !          1716:                                                                 notify_type_names, type);
        !          1717:                                                        enumerator->destroy(enumerator);
        !          1718:                                                        return SUCCESS;
        !          1719:                                                }
        !          1720:                                                DBG2(DBG_IKE, "received %N notify",
        !          1721:                                                         notify_type_names, type);
        !          1722:                                        }
        !          1723:                                        break;
        !          1724:                                }
        !          1725:                        }
        !          1726:                }
        !          1727:        }
        !          1728:        enumerator->destroy(enumerator);
        !          1729: 
        !          1730:        process_payloads(this, message);
        !          1731: 
        !          1732:        if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
        !          1733:        {
        !          1734:                DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
        !          1735:                         " one, no CHILD_SA built");
        !          1736:                handle_child_sa_failure(this, message);
        !          1737:                return delete_failed_sa(this);
        !          1738:        }
        !          1739:        else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
        !          1740:        {
        !          1741:                DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
        !          1742:                         "IPComp is disabled");
        !          1743:                this->ipcomp = IPCOMP_NONE;
        !          1744:        }
        !          1745:        else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
        !          1746:        {
        !          1747:                DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
        !          1748:                         "no CHILD_SA built");
        !          1749:                handle_child_sa_failure(this, message);
        !          1750:                return delete_failed_sa(this);
        !          1751:        }
        !          1752: 
        !          1753:        if (this->dh_failed)
        !          1754:        {
        !          1755:                DBG1(DBG_IKE, "applying DH public value failed");
        !          1756:                handle_child_sa_failure(this, message);
        !          1757:                return delete_failed_sa(this);
        !          1758:        }
        !          1759: 
        !          1760:        if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
        !          1761:        {
        !          1762:                if (!this->rekey)
        !          1763:                {       /* invoke the child_up() hook if we are not rekeying */
        !          1764:                        charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
        !          1765:                }
        !          1766:        }
        !          1767:        else
        !          1768:        {
        !          1769:                handle_child_sa_failure(this, message);
        !          1770:                return delete_failed_sa(this);
        !          1771:        }
        !          1772:        return SUCCESS;
        !          1773: }
        !          1774: 
        !          1775: METHOD(child_create_t, use_reqid, void,
        !          1776:        private_child_create_t *this, uint32_t reqid)
        !          1777: {
        !          1778:        this->child.reqid = reqid;
        !          1779: }
        !          1780: 
        !          1781: METHOD(child_create_t, use_marks, void,
        !          1782:        private_child_create_t *this, uint32_t in, uint32_t out)
        !          1783: {
        !          1784:        this->child.mark_in = in;
        !          1785:        this->child.mark_out = out;
        !          1786: }
        !          1787: 
        !          1788: METHOD(child_create_t, use_if_ids, void,
        !          1789:        private_child_create_t *this, uint32_t in, uint32_t out)
        !          1790: {
        !          1791:        this->child.if_id_in = in;
        !          1792:        this->child.if_id_out = out;
        !          1793: }
        !          1794: 
        !          1795: METHOD(child_create_t, use_dh_group, void,
        !          1796:        private_child_create_t *this, diffie_hellman_group_t dh_group)
        !          1797: {
        !          1798:        this->dh_group = dh_group;
        !          1799: }
        !          1800: 
        !          1801: METHOD(child_create_t, get_child, child_sa_t*,
        !          1802:        private_child_create_t *this)
        !          1803: {
        !          1804:        return this->child_sa;
        !          1805: }
        !          1806: 
        !          1807: METHOD(child_create_t, set_config, void,
        !          1808:        private_child_create_t *this, child_cfg_t *cfg)
        !          1809: {
        !          1810:        DESTROY_IF(this->config);
        !          1811:        this->config = cfg;
        !          1812: }
        !          1813: 
        !          1814: METHOD(child_create_t, get_lower_nonce, chunk_t,
        !          1815:        private_child_create_t *this)
        !          1816: {
        !          1817:        if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
        !          1818:                           min(this->my_nonce.len, this->other_nonce.len)) < 0)
        !          1819:        {
        !          1820:                return this->my_nonce;
        !          1821:        }
        !          1822:        else
        !          1823:        {
        !          1824:                return this->other_nonce;
        !          1825:        }
        !          1826: }
        !          1827: 
        !          1828: METHOD(task_t, get_type, task_type_t,
        !          1829:        private_child_create_t *this)
        !          1830: {
        !          1831:        return TASK_CHILD_CREATE;
        !          1832: }
        !          1833: 
        !          1834: METHOD(task_t, migrate, void,
        !          1835:        private_child_create_t *this, ike_sa_t *ike_sa)
        !          1836: {
        !          1837:        chunk_free(&this->my_nonce);
        !          1838:        chunk_free(&this->other_nonce);
        !          1839:        if (this->tsr)
        !          1840:        {
        !          1841:                this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
        !          1842:        }
        !          1843:        if (this->tsi)
        !          1844:        {
        !          1845:                this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
        !          1846:        }
        !          1847:        DESTROY_IF(this->child_sa);
        !          1848:        DESTROY_IF(this->proposal);
        !          1849:        DESTROY_IF(this->nonceg);
        !          1850:        DESTROY_IF(this->dh);
        !          1851:        this->dh_failed = FALSE;
        !          1852:        if (this->proposals)
        !          1853:        {
        !          1854:                this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
        !          1855:        }
        !          1856: 
        !          1857:        this->ike_sa = ike_sa;
        !          1858:        this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
        !          1859:        this->proposal = NULL;
        !          1860:        this->proposals = NULL;
        !          1861:        this->tsi = NULL;
        !          1862:        this->tsr = NULL;
        !          1863:        this->dh = NULL;
        !          1864:        this->nonceg = NULL;
        !          1865:        this->child_sa = NULL;
        !          1866:        this->mode = MODE_TUNNEL;
        !          1867:        this->ipcomp = IPCOMP_NONE;
        !          1868:        this->ipcomp_received = IPCOMP_NONE;
        !          1869:        this->other_cpi = 0;
        !          1870:        this->established = FALSE;
        !          1871:        this->child = (child_sa_create_t){};
        !          1872: }
        !          1873: 
        !          1874: METHOD(task_t, destroy, void,
        !          1875:        private_child_create_t *this)
        !          1876: {
        !          1877:        chunk_free(&this->my_nonce);
        !          1878:        chunk_free(&this->other_nonce);
        !          1879:        if (this->tsr)
        !          1880:        {
        !          1881:                this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
        !          1882:        }
        !          1883:        if (this->tsi)
        !          1884:        {
        !          1885:                this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
        !          1886:        }
        !          1887:        if (!this->established)
        !          1888:        {
        !          1889:                DESTROY_IF(this->child_sa);
        !          1890:        }
        !          1891:        DESTROY_IF(this->packet_tsi);
        !          1892:        DESTROY_IF(this->packet_tsr);
        !          1893:        DESTROY_IF(this->proposal);
        !          1894:        DESTROY_IF(this->dh);
        !          1895:        if (this->proposals)
        !          1896:        {
        !          1897:                this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
        !          1898:        }
        !          1899:        DESTROY_IF(this->config);
        !          1900:        DESTROY_IF(this->nonceg);
        !          1901:        free(this);
        !          1902: }
        !          1903: 
        !          1904: /*
        !          1905:  * Described in header.
        !          1906:  */
        !          1907: child_create_t *child_create_create(ike_sa_t *ike_sa,
        !          1908:                                                        child_cfg_t *config, bool rekey,
        !          1909:                                                        traffic_selector_t *tsi, traffic_selector_t *tsr)
        !          1910: {
        !          1911:        private_child_create_t *this;
        !          1912: 
        !          1913:        INIT(this,
        !          1914:                .public = {
        !          1915:                        .get_child = _get_child,
        !          1916:                        .set_config = _set_config,
        !          1917:                        .get_lower_nonce = _get_lower_nonce,
        !          1918:                        .use_reqid = _use_reqid,
        !          1919:                        .use_marks = _use_marks,
        !          1920:                        .use_if_ids = _use_if_ids,
        !          1921:                        .use_dh_group = _use_dh_group,
        !          1922:                        .task = {
        !          1923:                                .get_type = _get_type,
        !          1924:                                .migrate = _migrate,
        !          1925:                                .destroy = _destroy,
        !          1926:                        },
        !          1927:                },
        !          1928:                .ike_sa = ike_sa,
        !          1929:                .config = config,
        !          1930:                .packet_tsi = tsi ? tsi->clone(tsi) : NULL,
        !          1931:                .packet_tsr = tsr ? tsr->clone(tsr) : NULL,
        !          1932:                .dh_group = MODP_NONE,
        !          1933:                .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
        !          1934:                .mode = MODE_TUNNEL,
        !          1935:                .tfcv3 = TRUE,
        !          1936:                .ipcomp = IPCOMP_NONE,
        !          1937:                .ipcomp_received = IPCOMP_NONE,
        !          1938:                .rekey = rekey,
        !          1939:                .retry = FALSE,
        !          1940:        );
        !          1941: 
        !          1942:        if (config)
        !          1943:        {
        !          1944:                this->public.task.build = _build_i;
        !          1945:                this->public.task.process = _process_i;
        !          1946:                this->initiator = TRUE;
        !          1947:        }
        !          1948:        else
        !          1949:        {
        !          1950:                this->public.task.build = _build_r;
        !          1951:                this->public.task.process = _process_r;
        !          1952:                this->initiator = FALSE;
        !          1953:        }
        !          1954:        return &this->public;
        !          1955: }

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