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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2007-2008 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "ike_me.h"
        !            17: 
        !            18: #include <string.h>
        !            19: 
        !            20: #include <daemon.h>
        !            21: #include <config/peer_cfg.h>
        !            22: #include <encoding/payloads/id_payload.h>
        !            23: #include <encoding/payloads/notify_payload.h>
        !            24: #include <encoding/payloads/endpoint_notify.h>
        !            25: #include <processing/jobs/mediation_job.h>
        !            26: 
        !            27: #define ME_CONNECTID_LEN 4
        !            28: #define ME_CONNECTKEY_LEN 16
        !            29: 
        !            30: typedef struct private_ike_me_t private_ike_me_t;
        !            31: 
        !            32: /**
        !            33:  * Private members of a ike_me_t task.
        !            34:  */
        !            35: struct private_ike_me_t {
        !            36: 
        !            37:        /**
        !            38:         * Public methods and task_t interface.
        !            39:         */
        !            40:        ike_me_t public;
        !            41: 
        !            42:        /**
        !            43:         * Assigned IKE_SA.
        !            44:         */
        !            45:        ike_sa_t *ike_sa;
        !            46: 
        !            47:        /**
        !            48:         * Are we the initiator?
        !            49:         */
        !            50:        bool initiator;
        !            51: 
        !            52:        /**
        !            53:         * Is this a mediation connection?
        !            54:         */
        !            55:        bool mediation;
        !            56: 
        !            57:        /**
        !            58:         * Is this the response from another peer?
        !            59:         */
        !            60:        bool response;
        !            61: 
        !            62:        /**
        !            63:         * Gathered endpoints
        !            64:         */
        !            65:        linked_list_t *local_endpoints;
        !            66: 
        !            67:        /**
        !            68:         * Parsed endpoints
        !            69:         */
        !            70:        linked_list_t *remote_endpoints;
        !            71: 
        !            72:        /**
        !            73:         * Did the peer request a callback?
        !            74:         */
        !            75:        bool callback;
        !            76: 
        !            77:        /**
        !            78:         * Did the connect fail?
        !            79:         */
        !            80:        bool failed;
        !            81: 
        !            82:        /**
        !            83:         * Was there anything wrong with the payloads?
        !            84:         */
        !            85:        bool invalid_syntax;
        !            86: 
        !            87:        /**
        !            88:         * The requested peer
        !            89:         */
        !            90:        identification_t *peer_id;
        !            91:        /**
        !            92:         * Received ID used for connectivity checks
        !            93:         */
        !            94:        chunk_t connect_id;
        !            95: 
        !            96:        /**
        !            97:         * Received key used for connectivity checks
        !            98:         */
        !            99:        chunk_t connect_key;
        !           100: 
        !           101:        /**
        !           102:         * Peer config of the mediated connection
        !           103:         */
        !           104:        peer_cfg_t *mediated_cfg;
        !           105: 
        !           106: };
        !           107: 
        !           108: /**
        !           109:  * Adds a list of endpoints as notifies to a given message
        !           110:  */
        !           111: static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
        !           112: {
        !           113:        enumerator_t *enumerator;
        !           114:        endpoint_notify_t *endpoint;
        !           115: 
        !           116:        enumerator = endpoints->create_enumerator(endpoints);
        !           117:        while (enumerator->enumerate(enumerator, (void**)&endpoint))
        !           118:        {
        !           119:                message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
        !           120:        }
        !           121:        enumerator->destroy(enumerator);
        !           122: }
        !           123: 
        !           124: /**
        !           125:  * Gathers endpoints and adds them to the current message
        !           126:  */
        !           127: static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
        !           128: {
        !           129:        enumerator_t *enumerator;
        !           130:        host_t *addr, *host;
        !           131:        uint16_t port;
        !           132: 
        !           133:        /* get the port that is used to communicate with the ms */
        !           134:        host = this->ike_sa->get_my_host(this->ike_sa);
        !           135:        port = host->get_port(host);
        !           136: 
        !           137:        enumerator = charon->kernel->create_address_enumerator(charon->kernel,
        !           138:                                                                                                                   ADDR_TYPE_REGULAR);
        !           139:        while (enumerator->enumerate(enumerator, (void**)&addr))
        !           140:        {
        !           141:                host = addr->clone(addr);
        !           142:                host->set_port(host, port);
        !           143: 
        !           144:                this->local_endpoints->insert_last(this->local_endpoints,
        !           145:                                endpoint_notify_create_from_host(HOST, host, NULL));
        !           146: 
        !           147:                host->destroy(host);
        !           148:        }
        !           149:        enumerator->destroy(enumerator);
        !           150: 
        !           151:        host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
        !           152:        if (host)
        !           153:        {
        !           154:                this->local_endpoints->insert_last(this->local_endpoints,
        !           155:                                endpoint_notify_create_from_host(SERVER_REFLEXIVE, host,
        !           156:                                                this->ike_sa->get_my_host(this->ike_sa)));
        !           157:        }
        !           158: 
        !           159:        add_endpoints_to_message(message, this->local_endpoints);
        !           160: }
        !           161: 
        !           162: /**
        !           163:  * read notifys from message and evaluate them
        !           164:  */
        !           165: static void process_payloads(private_ike_me_t *this, message_t *message)
        !           166: {
        !           167:        enumerator_t *enumerator;
        !           168:        payload_t *payload;
        !           169: 
        !           170:        enumerator = message->create_payload_enumerator(message);
        !           171:        while (enumerator->enumerate(enumerator, &payload))
        !           172:        {
        !           173:                if (payload->get_type(payload) != PLV2_NOTIFY)
        !           174:                {
        !           175:                        continue;
        !           176:                }
        !           177: 
        !           178:                notify_payload_t *notify = (notify_payload_t*)payload;
        !           179: 
        !           180:                switch (notify->get_notify_type(notify))
        !           181:                {
        !           182:                        case ME_CONNECT_FAILED:
        !           183:                        {
        !           184:                                DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify");
        !           185:                                this->failed = TRUE;
        !           186:                                break;
        !           187:                        }
        !           188:                        case ME_MEDIATION:
        !           189:                        {
        !           190:                                DBG2(DBG_IKE, "received ME_MEDIATION notify");
        !           191:                                this->mediation = TRUE;
        !           192:                                break;
        !           193:                        }
        !           194:                        case ME_ENDPOINT:
        !           195:                        {
        !           196:                                endpoint_notify_t *endpoint;
        !           197:                                endpoint = endpoint_notify_create_from_payload(notify);
        !           198:                                if (!endpoint)
        !           199:                                {
        !           200:                                        DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify");
        !           201:                                        break;
        !           202:                                }
        !           203:                                DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H",
        !           204:                                         me_endpoint_type_names, endpoint->get_type(endpoint),
        !           205:                                         endpoint->get_host(endpoint));
        !           206: 
        !           207:                                this->remote_endpoints->insert_last(this->remote_endpoints,
        !           208:                                                                                                        endpoint);
        !           209:                                break;
        !           210:                        }
        !           211:                        case ME_CALLBACK:
        !           212:                        {
        !           213:                                DBG2(DBG_IKE, "received ME_CALLBACK notify");
        !           214:                                this->callback = TRUE;
        !           215:                                break;
        !           216:                        }
        !           217:                        case ME_CONNECTID:
        !           218:                        {
        !           219:                                chunk_free(&this->connect_id);
        !           220:                                this->connect_id = chunk_clone(notify->get_notification_data(notify));
        !           221:                                DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id);
        !           222:                                break;
        !           223:                        }
        !           224:                        case ME_CONNECTKEY:
        !           225:                        {
        !           226:                                chunk_free(&this->connect_key);
        !           227:                                this->connect_key = chunk_clone(notify->get_notification_data(notify));
        !           228:                                DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key);
        !           229:                                break;
        !           230:                        }
        !           231:                        case ME_RESPONSE:
        !           232:                        {
        !           233:                                DBG2(DBG_IKE, "received ME_RESPONSE notify");
        !           234:                                this->response = TRUE;
        !           235:                                break;
        !           236:                        }
        !           237:                        default:
        !           238:                                break;
        !           239:                }
        !           240:        }
        !           241:        enumerator->destroy(enumerator);
        !           242: }
        !           243: 
        !           244: METHOD(task_t, build_i, status_t,
        !           245:        private_ike_me_t *this, message_t *message)
        !           246: {
        !           247:        switch(message->get_exchange_type(message))
        !           248:        {
        !           249:                case IKE_SA_INIT:
        !           250:                {
        !           251:                        peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !           252:                        if (peer_cfg->is_mediation(peer_cfg))
        !           253:                        {
        !           254:                                DBG2(DBG_IKE, "adding ME_MEDIATION");
        !           255:                                message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
        !           256:                        }
        !           257:                        else
        !           258:                        {
        !           259:                                return SUCCESS;
        !           260:                        }
        !           261:                        break;
        !           262:                }
        !           263:                case IKE_AUTH:
        !           264:                {
        !           265:                        if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
        !           266:                        {
        !           267:                                endpoint_notify_t *endpoint;
        !           268:                                endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
        !           269:                                                                                                                        NULL, NULL);
        !           270:                                message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
        !           271:                                endpoint->destroy(endpoint);
        !           272:                        }
        !           273:                        break;
        !           274:                }
        !           275:                case ME_CONNECT:
        !           276:                {
        !           277:                        rng_t *rng;
        !           278:                        id_payload_t *id_payload;
        !           279:                        id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
        !           280:                                                                                                                           this->peer_id);
        !           281:                        message->add_payload(message, (payload_t*)id_payload);
        !           282: 
        !           283:                        rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
        !           284:                        if (!rng)
        !           285:                        {
        !           286:                                DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT");
        !           287:                                return FAILED;
        !           288:                        }
        !           289:                        if (!this->response)
        !           290:                        {
        !           291:                                /* only the initiator creates a connect ID. the responder
        !           292:                                 * returns the connect ID that it received from the initiator */
        !           293:                                if (!rng->allocate_bytes(rng, ME_CONNECTID_LEN,
        !           294:                                                                                 &this->connect_id))
        !           295:                                {
        !           296:                                        DBG1(DBG_IKE, "unable to generate ID for ME_CONNECT");
        !           297:                                        rng->destroy(rng);
        !           298:                                        return FAILED;
        !           299:                                }
        !           300:                        }
        !           301:                        if (!rng->allocate_bytes(rng, ME_CONNECTKEY_LEN,
        !           302:                                                                         &this->connect_key))
        !           303:                        {
        !           304:                                DBG1(DBG_IKE, "unable to generate connect key for ME_CONNECT");
        !           305:                                rng->destroy(rng);
        !           306:                                return FAILED;
        !           307:                        }
        !           308:                        rng->destroy(rng);
        !           309: 
        !           310:                        message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
        !           311:                        message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
        !           312: 
        !           313:                        if (this->response)
        !           314:                        {
        !           315:                                message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
        !           316:                        }
        !           317:                        else
        !           318:                        {
        !           319:                                /* FIXME: should we make this configurable? */
        !           320:                                message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
        !           321:                        }
        !           322: 
        !           323:                        gather_and_add_endpoints(this, message);
        !           324: 
        !           325:                        break;
        !           326:                }
        !           327:                default:
        !           328:                        break;
        !           329:        }
        !           330:        return NEED_MORE;
        !           331: }
        !           332: 
        !           333: METHOD(task_t, process_r, status_t,
        !           334:        private_ike_me_t *this, message_t *message)
        !           335: {
        !           336:        switch(message->get_exchange_type(message))
        !           337:        {
        !           338:                case ME_CONNECT:
        !           339:                {
        !           340:                        id_payload_t *id_payload;
        !           341:                        id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
        !           342:                        if (!id_payload)
        !           343:                        {
        !           344:                                DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
        !           345:                                         ", aborting");
        !           346:                                break;
        !           347:                        }
        !           348:                        this->peer_id = id_payload->get_identification(id_payload);
        !           349: 
        !           350:                        process_payloads(this, message);
        !           351: 
        !           352:                        if (this->callback)
        !           353:                        {
        !           354:                                DBG1(DBG_IKE, "received ME_CALLBACK for '%Y'", this->peer_id);
        !           355:                                break;
        !           356:                        }
        !           357: 
        !           358:                        if (!this->connect_id.ptr)
        !           359:                        {
        !           360:                                DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
        !           361:                                         ", aborting");
        !           362:                                this->invalid_syntax = TRUE;
        !           363:                                break;
        !           364:                        }
        !           365: 
        !           366:                        if (!this->connect_key.ptr)
        !           367:                        {
        !           368:                                DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY "
        !           369:                                         "notify, aborting");
        !           370:                                this->invalid_syntax = TRUE;
        !           371:                                break;
        !           372:                        }
        !           373: 
        !           374:                        if (!this->remote_endpoints->get_count(this->remote_endpoints))
        !           375:                        {
        !           376:                                DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
        !           377:                                         "payloads, aborting");
        !           378:                                this->invalid_syntax = TRUE;
        !           379:                                break;
        !           380:                        }
        !           381: 
        !           382:                        DBG1(DBG_IKE, "received ME_CONNECT");
        !           383:                        break;
        !           384:                }
        !           385:                default:
        !           386:                        break;
        !           387:        }
        !           388:        return NEED_MORE;
        !           389: }
        !           390: 
        !           391: METHOD(task_t, build_r, status_t,
        !           392:        private_ike_me_t *this, message_t *message)
        !           393: {
        !           394:        switch(message->get_exchange_type(message))
        !           395:        {
        !           396:                case ME_CONNECT:
        !           397:                {
        !           398:                        if (this->invalid_syntax)
        !           399:                        {
        !           400:                                message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
        !           401:                                break;
        !           402:                        }
        !           403: 
        !           404:                        if (this->callback)
        !           405:                        {
        !           406:                                /* we got a callback from the mediation server, initiate the
        !           407:                                 * queued mediated connection */
        !           408:                                charon->connect_manager->check_and_initiate(
        !           409:                                                charon->connect_manager,
        !           410:                                                this->ike_sa->get_id(this->ike_sa),
        !           411:                                                this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
        !           412:                                return SUCCESS;
        !           413:                        }
        !           414: 
        !           415:                        if (this->response)
        !           416:                        {
        !           417:                                /* FIXME: handle result of set_responder_data
        !           418:                                 * as initiator, upon receiving a response from another peer,
        !           419:                                 * update the checklist and start sending checks */
        !           420:                                charon->connect_manager->set_responder_data(
        !           421:                                                charon->connect_manager,
        !           422:                                                this->connect_id, this->connect_key,
        !           423:                                                this->remote_endpoints);
        !           424:                        }
        !           425:                        else
        !           426:                        {
        !           427:                                /* FIXME: handle result of set_initiator_data
        !           428:                                 * as responder, create a checklist with the initiator's data */
        !           429:                                charon->connect_manager->set_initiator_data(
        !           430:                                                charon->connect_manager,
        !           431:                                                this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
        !           432:                                                this->connect_id, this->connect_key,
        !           433:                                                this->remote_endpoints, FALSE);
        !           434:                                if (this->ike_sa->respond(this->ike_sa, this->peer_id,
        !           435:                                                                                  this->connect_id) != SUCCESS)
        !           436:                                {
        !           437:                                        return FAILED;
        !           438:                                }
        !           439:                        }
        !           440:                        break;
        !           441:                }
        !           442:                default:
        !           443:                        break;
        !           444:        }
        !           445:        return SUCCESS;
        !           446: }
        !           447: 
        !           448: METHOD(task_t, process_i, status_t,
        !           449:        private_ike_me_t *this, message_t *message)
        !           450: {
        !           451:        switch(message->get_exchange_type(message))
        !           452:        {
        !           453:                case IKE_SA_INIT:
        !           454:                {
        !           455:                        process_payloads(this, message);
        !           456:                        if (!this->mediation)
        !           457:                        {
        !           458:                                DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting");
        !           459:                                return FAILED;
        !           460:                        }
        !           461:                        /* if we are on a mediation connection we switch to port 4500 even
        !           462:                         * if no NAT is detected. */
        !           463:                        this->ike_sa->float_ports(this->ike_sa);
        !           464:                        return NEED_MORE;
        !           465:                }
        !           466:                case IKE_AUTH:
        !           467:                {
        !           468:                        process_payloads(this, message);
        !           469:                        /* FIXME: we should update the server reflexive endpoint somehow,
        !           470:                         * if mobike notices a change */
        !           471:                        endpoint_notify_t *reflexive;
        !           472:                        if (this->remote_endpoints->get_first(this->remote_endpoints,
        !           473:                                                                                        (void**)&reflexive) == SUCCESS &&
        !           474:                                reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
        !           475:                        {       /* FIXME: should we accept this endpoint even if we did not send
        !           476:                                 * a request? */
        !           477:                                host_t *endpoint = reflexive->get_host(reflexive);
        !           478:                                endpoint = endpoint->clone(endpoint);
        !           479:                                this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint);
        !           480:                        }
        !           481:                        break;
        !           482:                }
        !           483:                case ME_CONNECT:
        !           484:                {
        !           485:                        process_payloads(this, message);
        !           486: 
        !           487:                        if (this->failed)
        !           488:                        {
        !           489:                                DBG1(DBG_IKE, "peer '%Y' is not online", this->peer_id);
        !           490:                                /* FIXME: notify the mediated connection (job?) */
        !           491:                        }
        !           492:                        else
        !           493:                        {
        !           494:                                if (this->response)
        !           495:                                {
        !           496:                                        /* FIXME: handle result of set_responder_data. */
        !           497:                                        /* as responder, we update the checklist and start sending
        !           498:                                         * checks */
        !           499:                                        charon->connect_manager->set_responder_data(
        !           500:                                                        charon->connect_manager, this->connect_id,
        !           501:                                                        this->connect_key, this->local_endpoints);
        !           502:                                }
        !           503:                                else
        !           504:                                {
        !           505:                                        /* FIXME: handle result of set_initiator_data */
        !           506:                                        /* as initiator, we create a checklist and set the
        !           507:                                         * initiator's data */
        !           508:                                        charon->connect_manager->set_initiator_data(
        !           509:                                                        charon->connect_manager,
        !           510:                                                        this->ike_sa->get_my_id(this->ike_sa),
        !           511:                                                        this->peer_id, this->connect_id, this->connect_key,
        !           512:                                                        this->local_endpoints, TRUE);
        !           513:                                        /* FIXME: also start a timer for the whole transaction
        !           514:                                         * (maybe within the connect_manager?) */
        !           515:                                }
        !           516:                        }
        !           517:                        break;
        !           518:                }
        !           519:                default:
        !           520:                        break;
        !           521:        }
        !           522:        return SUCCESS;
        !           523: }
        !           524: 
        !           525: /**
        !           526:  *  For mediation server
        !           527:  */
        !           528: METHOD(task_t, build_i_ms, status_t,
        !           529:        private_ike_me_t *this, message_t *message)
        !           530: {
        !           531:        switch(message->get_exchange_type(message))
        !           532:        {
        !           533:                case ME_CONNECT:
        !           534:                {
        !           535:                        id_payload_t *id_payload;
        !           536:                        id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
        !           537:                                                                                                                           this->peer_id);
        !           538:                        message->add_payload(message, (payload_t*)id_payload);
        !           539: 
        !           540:                        if (this->callback)
        !           541:                        {
        !           542:                                message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
        !           543:                        }
        !           544:                        else
        !           545:                        {
        !           546:                                if (this->response)
        !           547:                                {
        !           548:                                        message->add_notify(message, FALSE, ME_RESPONSE,
        !           549:                                                                                chunk_empty);
        !           550:                                }
        !           551:                                message->add_notify(message, FALSE, ME_CONNECTID,
        !           552:                                                                        this->connect_id);
        !           553:                                message->add_notify(message, FALSE, ME_CONNECTKEY,
        !           554:                                                                        this->connect_key);
        !           555:                                add_endpoints_to_message(message, this->remote_endpoints);
        !           556:                        }
        !           557:                        break;
        !           558:                }
        !           559:                default:
        !           560:                        break;
        !           561:        }
        !           562:        return NEED_MORE;
        !           563: }
        !           564: 
        !           565: /**
        !           566:  * For mediation server
        !           567:  */
        !           568: METHOD(task_t, process_r_ms, status_t,
        !           569:        private_ike_me_t *this, message_t *message)
        !           570: {
        !           571:        switch(message->get_exchange_type(message))
        !           572:        {
        !           573:                case IKE_SA_INIT:
        !           574:                {
        !           575:                        /* FIXME: we should check for SA* and TS* payloads. if there are
        !           576:                         * any, send NO_ADDITIONAL_SAS back and delete this SA */
        !           577:                        process_payloads(this, message);
        !           578:                        return this->mediation ? NEED_MORE : SUCCESS;
        !           579:                }
        !           580:                case IKE_AUTH:
        !           581:                {
        !           582:                        /* FIXME: we should check whether the current peer_config is
        !           583:                         * configured as mediation connection */
        !           584:                        process_payloads(this, message);
        !           585:                        break;
        !           586:                }
        !           587:                case CREATE_CHILD_SA:
        !           588:                {
        !           589:                        /* FIXME: if this is not to rekey the IKE SA we have to return a
        !           590:                         * NO_ADDITIONAL_SAS and then delete the SA */
        !           591:                        break;
        !           592:                }
        !           593:                case ME_CONNECT:
        !           594:                {
        !           595:                        id_payload_t *id_payload;
        !           596:                        id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
        !           597:                        if (!id_payload)
        !           598:                        {
        !           599:                                DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
        !           600:                                         ", aborting");
        !           601:                                this->invalid_syntax = TRUE;
        !           602:                                break;
        !           603:                        }
        !           604:                        this->peer_id = id_payload->get_identification(id_payload);
        !           605: 
        !           606:                        process_payloads(this, message);
        !           607: 
        !           608:                        if (!this->connect_id.ptr)
        !           609:                        {
        !           610:                                DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
        !           611:                                         ", aborting");
        !           612:                                this->invalid_syntax = TRUE;
        !           613:                                break;
        !           614:                        }
        !           615: 
        !           616:                        if (!this->connect_key.ptr)
        !           617:                        {
        !           618:                                DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify"
        !           619:                                         ", aborting");
        !           620:                                this->invalid_syntax = TRUE;
        !           621:                                break;
        !           622:                        }
        !           623: 
        !           624:                        if (!this->remote_endpoints->get_count(this->remote_endpoints))
        !           625:                        {
        !           626:                                DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
        !           627:                                         "payloads, aborting");
        !           628:                                this->invalid_syntax = TRUE;
        !           629:                                break;
        !           630:                        }
        !           631:                        break;
        !           632:                }
        !           633:                default:
        !           634:                        break;
        !           635:        }
        !           636:        return NEED_MORE;
        !           637: }
        !           638: 
        !           639: /**
        !           640:  * For mediation server
        !           641:  */
        !           642: METHOD(task_t, build_r_ms, status_t,
        !           643:        private_ike_me_t *this, message_t *message)
        !           644: {
        !           645:        switch(message->get_exchange_type(message))
        !           646:        {
        !           647:                case IKE_SA_INIT:
        !           648:                {
        !           649:                        message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
        !           650:                        return NEED_MORE;
        !           651:                }
        !           652:                case IKE_AUTH:
        !           653:                {
        !           654:                        endpoint_notify_t *endpoint;
        !           655:                        if (this->remote_endpoints->get_first(this->remote_endpoints,
        !           656:                                                                                        (void**)&endpoint) == SUCCESS &&
        !           657:                                endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
        !           658:                        {
        !           659:                                host_t *host = this->ike_sa->get_other_host(this->ike_sa);
        !           660:                                DBG2(DBG_IKE, "received request for a server reflexive "
        !           661:                                         "endpoint sending: %#H", host);
        !           662:                                endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
        !           663:                                                                                                                        host, NULL);
        !           664:                                message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
        !           665:                                endpoint->destroy(endpoint);
        !           666:                        }
        !           667:                        this->ike_sa->act_as_mediation_server(this->ike_sa);
        !           668:                        break;
        !           669:                }
        !           670:                case ME_CONNECT:
        !           671:                {
        !           672:                        if (this->invalid_syntax)
        !           673:                        {
        !           674:                                message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
        !           675:                                break;
        !           676:                        }
        !           677: 
        !           678:                        ike_sa_id_t *peer_sa;
        !           679:                        if (this->callback)
        !           680:                        {
        !           681:                                peer_sa = charon->mediation_manager->check_and_register(
        !           682:                                                                        charon->mediation_manager, this->peer_id,
        !           683:                                                                        this->ike_sa->get_other_id(this->ike_sa));
        !           684:                        }
        !           685:                        else
        !           686:                        {
        !           687:                                peer_sa = charon->mediation_manager->check(
        !           688:                                                                        charon->mediation_manager, this->peer_id);
        !           689:                        }
        !           690: 
        !           691:                        if (!peer_sa)
        !           692:                        {
        !           693:                                /* the peer is not online */
        !           694:                                message->add_notify(message, TRUE, ME_CONNECT_FAILED,
        !           695:                                                                        chunk_empty);
        !           696:                                break;
        !           697:                        }
        !           698: 
        !           699:                        job_t *job = (job_t*)mediation_job_create(this->peer_id,
        !           700:                                        this->ike_sa->get_other_id(this->ike_sa), this->connect_id,
        !           701:                                        this->connect_key, this->remote_endpoints, this->response);
        !           702:                        lib->processor->queue_job(lib->processor, job);
        !           703:                        break;
        !           704:                }
        !           705:                default:
        !           706:                        break;
        !           707:        }
        !           708:        return SUCCESS;
        !           709: }
        !           710: 
        !           711: /**
        !           712:  * For mediation server
        !           713:  */
        !           714: METHOD(task_t, process_i_ms, status_t,
        !           715:        private_ike_me_t *this, message_t *message)
        !           716: {
        !           717:        /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
        !           718:         * here if the responding peer is not able to proceed. in this case we shall
        !           719:         * notify the initiating peer with a ME_CONNECT request containing only a
        !           720:         * ME_CONNECT_FAILED */
        !           721:        return SUCCESS;
        !           722: }
        !           723: 
        !           724: METHOD(ike_me_t, me_connect, void,
        !           725:        private_ike_me_t *this, identification_t *peer_id)
        !           726: {
        !           727:        this->peer_id = peer_id->clone(peer_id);
        !           728: }
        !           729: 
        !           730: METHOD(ike_me_t, me_respond, void,
        !           731:        private_ike_me_t *this, identification_t *peer_id, chunk_t connect_id)
        !           732: {
        !           733:        this->peer_id = peer_id->clone(peer_id);
        !           734:        this->connect_id = chunk_clone(connect_id);
        !           735:        this->response = TRUE;
        !           736: }
        !           737: 
        !           738: METHOD(ike_me_t, me_callback, void,
        !           739:        private_ike_me_t *this, identification_t *peer_id)
        !           740: {
        !           741:        this->peer_id = peer_id->clone(peer_id);
        !           742:        this->callback = TRUE;
        !           743: }
        !           744: 
        !           745: METHOD(ike_me_t, relay, void,
        !           746:        private_ike_me_t *this, identification_t *requester, chunk_t connect_id,
        !           747:        chunk_t connect_key, linked_list_t *endpoints, bool response)
        !           748: {
        !           749:        this->peer_id = requester->clone(requester);
        !           750:        this->connect_id = chunk_clone(connect_id);
        !           751:        this->connect_key = chunk_clone(connect_key);
        !           752: 
        !           753:        this->remote_endpoints->destroy_offset(this->remote_endpoints,
        !           754:                                                                                offsetof(endpoint_notify_t, destroy));
        !           755:        this->remote_endpoints = endpoints->clone_offset(endpoints,
        !           756:                                                                                offsetof(endpoint_notify_t, clone));
        !           757: 
        !           758:        this->response = response;
        !           759: }
        !           760: 
        !           761: METHOD(task_t, get_type, task_type_t,
        !           762:        private_ike_me_t *this)
        !           763: {
        !           764:        return TASK_IKE_ME;
        !           765: }
        !           766: 
        !           767: METHOD(task_t, migrate, void,
        !           768:        private_ike_me_t *this, ike_sa_t *ike_sa)
        !           769: {
        !           770:        this->ike_sa = ike_sa;
        !           771: }
        !           772: 
        !           773: METHOD(task_t, destroy, void,
        !           774:        private_ike_me_t *this)
        !           775: {
        !           776:        DESTROY_IF(this->peer_id);
        !           777: 
        !           778:        chunk_free(&this->connect_id);
        !           779:        chunk_free(&this->connect_key);
        !           780: 
        !           781:        this->local_endpoints->destroy_offset(this->local_endpoints,
        !           782:                                                                                offsetof(endpoint_notify_t, destroy));
        !           783:        this->remote_endpoints->destroy_offset(this->remote_endpoints,
        !           784:                                                                                offsetof(endpoint_notify_t, destroy));
        !           785: 
        !           786:        DESTROY_IF(this->mediated_cfg);
        !           787:        free(this);
        !           788: }
        !           789: 
        !           790: /*
        !           791:  * Described in header.
        !           792:  */
        !           793: ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
        !           794: {
        !           795:        private_ike_me_t *this;
        !           796: 
        !           797:        INIT(this,
        !           798:                .public = {
        !           799:                        .task = {
        !           800:                                .get_type = _get_type,
        !           801:                                .migrate = _migrate,
        !           802:                                .destroy = _destroy,
        !           803:                        },
        !           804:                        .connect = _me_connect,
        !           805:                        .respond = _me_respond,
        !           806:                        .callback = _me_callback,
        !           807:                        .relay = _relay,
        !           808:                },
        !           809:                .ike_sa = ike_sa,
        !           810:                .initiator = initiator,
        !           811:                .local_endpoints = linked_list_create(),
        !           812:                .remote_endpoints = linked_list_create(),
        !           813:        );
        !           814: 
        !           815:        if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
        !           816:        {
        !           817:                if (initiator)
        !           818:                {
        !           819:                        this->public.task.build = _build_i;
        !           820:                        this->public.task.process = _process_i;
        !           821:                }
        !           822:                else
        !           823:                {
        !           824:                        this->public.task.build = _build_r;
        !           825:                        this->public.task.process = _process_r;
        !           826:                }
        !           827:        }
        !           828:        else
        !           829:        {
        !           830:                /* mediation server */
        !           831:                if (initiator)
        !           832:                {
        !           833:                        this->public.task.build = _build_i_ms;
        !           834:                        this->public.task.process = _process_i_ms;
        !           835:                }
        !           836:                else
        !           837:                {
        !           838:                        this->public.task.build = _build_r_ms;
        !           839:                        this->public.task.process = _process_r_ms;
        !           840:                }
        !           841:        }
        !           842: 
        !           843:        return &this->public;
        !           844: }

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