Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_me.c, revision 1.1.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>