Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/informational.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011 Martin Willi
                      3:  * Copyright (C) 2011 revosec AG
                      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 "informational.h"
                     17: 
                     18: #include <daemon.h>
                     19: #include <sa/ikev1/tasks/isakmp_delete.h>
                     20: #include <sa/ikev1/tasks/quick_delete.h>
                     21: 
                     22: #include <encoding/payloads/delete_payload.h>
                     23: 
                     24: typedef struct private_informational_t private_informational_t;
                     25: 
                     26: /**
                     27:  * Private members of a informational_t task.
                     28:  */
                     29: struct private_informational_t {
                     30: 
                     31:        /**
                     32:         * Public methods and task_t interface.
                     33:         */
                     34:        informational_t public;
                     35: 
                     36:        /**
                     37:         * Assigned IKE_SA.
                     38:         */
                     39:        ike_sa_t *ike_sa;
                     40: 
                     41:        /**
                     42:         * Notify payload to send
                     43:         */
                     44:        notify_payload_t *notify;
                     45: 
                     46:        /**
                     47:         * Delete subtask
                     48:         */
                     49:        task_t *del;
                     50: };
                     51: 
                     52: /**
                     53:  * Cancel active quick mode after receiving an error
                     54:  */
                     55: static void cancel_quick_mode(private_informational_t *this)
                     56: {
                     57:        enumerator_t *enumerator;
                     58:        task_t *task;
                     59: 
                     60:        enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
                     61:                                                                                                          TASK_QUEUE_ACTIVE);
                     62:        while (enumerator->enumerate(enumerator, &task))
                     63:        {
                     64:                if (task->get_type(task) == TASK_QUICK_MODE)
                     65:                {
                     66:                        this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
                     67:                        break;
                     68:                }
                     69:        }
                     70:        enumerator->destroy(enumerator);
                     71: }
                     72: 
                     73: METHOD(task_t, build_i, status_t,
                     74:        private_informational_t *this, message_t *message)
                     75: {
                     76:        message->add_payload(message, &this->notify->payload_interface);
                     77:        this->notify = NULL;
                     78:        return SUCCESS;
                     79: }
                     80: 
                     81: METHOD(task_t, process_r, status_t,
                     82:        private_informational_t *this, message_t *message)
                     83: {
                     84:        enumerator_t *enumerator;
                     85:        delete_payload_t *delete;
                     86:        notify_payload_t *notify;
                     87:        notify_type_t type;
                     88:        payload_t *payload;
                     89:        status_t status = SUCCESS;
                     90: 
                     91:        enumerator = message->create_payload_enumerator(message);
                     92:        while (enumerator->enumerate(enumerator, &payload))
                     93:        {
                     94:                switch (payload->get_type(payload))
                     95:                {
                     96:                        case PLV1_NOTIFY:
                     97:                                notify = (notify_payload_t*)payload;
                     98:                                type = notify->get_notify_type(notify);
                     99: 
                    100:                                if (type == INITIAL_CONTACT_IKEV1)
                    101:                                {
                    102:                                        this->ike_sa->set_condition(this->ike_sa,
                    103:                                                                                                COND_INIT_CONTACT_SEEN, TRUE);
                    104:                                }
                    105:                                else if (type == UNITY_LOAD_BALANCE)
                    106:                                {
                    107:                                        host_t *redirect, *me;
                    108:                                        chunk_t data;
                    109: 
                    110:                                        data = notify->get_notification_data(notify);
                    111:                                        redirect = host_create_from_chunk(AF_INET, data,
                    112:                                                                                                          IKEV2_UDP_PORT);
                    113:                                        if (redirect)
                    114:                                        {       /* treat the redirect as reauthentication */
                    115:                                                DBG1(DBG_IKE, "received %N notify, redirected to %H",
                    116:                                                         notify_type_names, type, redirect);
                    117:                                                /* Cisco boxes reject the first message from 4500 */
                    118:                                                me = this->ike_sa->get_my_host(this->ike_sa);
                    119:                                                me->set_port(me, charon->socket->get_port(
                    120:                                                                                                                charon->socket, FALSE));
                    121:                                                this->ike_sa->set_other_host(this->ike_sa, redirect);
                    122:                                                status = this->ike_sa->reauth(this->ike_sa);
                    123:                                                enumerator->destroy(enumerator);
                    124:                                                return status;
                    125:                                        }
                    126:                                        else
                    127:                                        {
                    128:                                                DBG1(DBG_IKE, "received %N notify, invalid address");
                    129:                                        }
                    130:                                }
                    131:                                else if (type < 16384)
                    132:                                {
                    133:                                        DBG1(DBG_IKE, "received %N error notify",
                    134:                                                 notify_type_names, type);
                    135:                                        if (this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING)
                    136:                                        {       /* only critical during main mode */
                    137:                                                status = FAILED;
                    138:                                        }
                    139:                                        switch (type)
                    140:                                        {
                    141:                                                case INVALID_ID_INFORMATION:
                    142:                                                case NO_PROPOSAL_CHOSEN:
                    143:                                                        cancel_quick_mode(this);
                    144:                                                        break;
                    145:                                                default:
                    146:                                                        break;
                    147:                                        }
                    148:                                        break;
                    149:                                }
                    150:                                else
                    151:                                {
                    152:                                        DBG1(DBG_IKE, "received %N notify",
                    153:                                                 notify_type_names, type);
                    154:                                }
                    155:                                continue;
                    156:                        case PLV1_DELETE:
                    157:                                if (!this->del)
                    158:                                {
                    159:                                        delete = (delete_payload_t*)payload;
                    160:                                        if (delete->get_protocol_id(delete) == PROTO_IKE)
                    161:                                        {
                    162:                                                this->del = (task_t*)isakmp_delete_create(this->ike_sa,
                    163:                                                                                                                                  FALSE);
                    164:                                        }
                    165:                                        else
                    166:                                        {
                    167:                                                this->del = (task_t*)quick_delete_create(this->ike_sa,
                    168:                                                                                                PROTO_NONE, 0, FALSE, FALSE);
                    169:                                        }
                    170:                                }
                    171:                                break;
                    172:                        default:
                    173:                                continue;
                    174:                }
                    175:                break;
                    176:        }
                    177:        enumerator->destroy(enumerator);
                    178: 
                    179:        if (this->del && status == SUCCESS)
                    180:        {
                    181:                return this->del->process(this->del, message);
                    182:        }
                    183:        return status;
                    184: }
                    185: 
                    186: METHOD(task_t, build_r, status_t,
                    187:        private_informational_t *this, message_t *message)
                    188: {
                    189:        if (this->del)
                    190:        {
                    191:                return this->del->build(this->del, message);
                    192:        }
                    193:        return FAILED;
                    194: }
                    195: 
                    196: METHOD(task_t, process_i, status_t,
                    197:        private_informational_t *this, message_t *message)
                    198: {
                    199:        return FAILED;
                    200: }
                    201: 
                    202: METHOD(task_t, get_type, task_type_t,
                    203:        private_informational_t *this)
                    204: {
                    205:        return TASK_INFORMATIONAL;
                    206: }
                    207: 
                    208: METHOD(task_t, migrate, void,
                    209:        private_informational_t *this, ike_sa_t *ike_sa)
                    210: {
                    211:        this->ike_sa = ike_sa;
                    212: }
                    213: 
                    214: METHOD(task_t, destroy, void,
                    215:        private_informational_t *this)
                    216: {
                    217:        DESTROY_IF(this->notify);
                    218:        DESTROY_IF(this->del);
                    219:        free(this);
                    220: }
                    221: 
                    222: /*
                    223:  * Described in header.
                    224:  */
                    225: informational_t *informational_create(ike_sa_t *ike_sa, notify_payload_t *notify)
                    226: {
                    227:        private_informational_t *this;
                    228: 
                    229:        INIT(this,
                    230:                .public = {
                    231:                        .task = {
                    232:                                .get_type = _get_type,
                    233:                                .migrate = _migrate,
                    234:                                .destroy = _destroy,
                    235:                        },
                    236:                },
                    237:                .ike_sa = ike_sa,
                    238:                .notify = notify,
                    239:        );
                    240: 
                    241:        if (notify)
                    242:        {
                    243:                this->public.task.build = _build_i;
                    244:                this->public.task.process = _process_i;
                    245:        }
                    246:        else
                    247:        {
                    248:                this->public.task.build = _build_r;
                    249:                this->public.task.process = _process_r;
                    250:        }
                    251: 
                    252:        return &this->public;
                    253: }

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