Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_delete.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2016 Tobias Brunner
                      3:  * Copyright (C) 2006-2007 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "ike_delete.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <encoding/payloads/delete_payload.h>
                     21: #include <sa/ikev2/tasks/ike_rekey.h>
                     22: 
                     23: typedef struct private_ike_delete_t private_ike_delete_t;
                     24: 
                     25: /**
                     26:  * Private members of a ike_delete_t task.
                     27:  */
                     28: struct private_ike_delete_t {
                     29: 
                     30:        /**
                     31:         * Public methods and task_t interface.
                     32:         */
                     33:        ike_delete_t public;
                     34: 
                     35:        /**
                     36:         * Assigned IKE_SA.
                     37:         */
                     38:        ike_sa_t *ike_sa;
                     39: 
                     40:        /**
                     41:         * Are we the initiator?
                     42:         */
                     43:        bool initiator;
                     44: 
                     45:        /**
                     46:         * are we deleting a rekeyed SA?
                     47:         */
                     48:        bool rekeyed;
                     49: };
                     50: 
                     51: METHOD(task_t, build_i, status_t,
                     52:        private_ike_delete_t *this, message_t *message)
                     53: {
                     54:        delete_payload_t *delete_payload;
                     55: 
                     56:        DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
                     57:                 this->ike_sa->get_name(this->ike_sa),
                     58:                 this->ike_sa->get_unique_id(this->ike_sa),
                     59:                 this->ike_sa->get_my_host(this->ike_sa),
                     60:                 this->ike_sa->get_my_id(this->ike_sa),
                     61:                 this->ike_sa->get_other_host(this->ike_sa),
                     62:                 this->ike_sa->get_other_id(this->ike_sa));
                     63: 
                     64:        delete_payload = delete_payload_create(PLV2_DELETE, PROTO_IKE);
                     65:        message->add_payload(message, (payload_t*)delete_payload);
                     66: 
                     67:        if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
                     68:                this->ike_sa->get_state(this->ike_sa) == IKE_REKEYED)
                     69:        {
                     70:                this->rekeyed = TRUE;
                     71:        }
                     72:        this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
                     73: 
                     74:        DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]",
                     75:                 this->ike_sa->get_name(this->ike_sa),
                     76:                 this->ike_sa->get_unique_id(this->ike_sa));
                     77: 
                     78:        return NEED_MORE;
                     79: }
                     80: 
                     81: METHOD(task_t, process_i, status_t,
                     82:        private_ike_delete_t *this, message_t *message)
                     83: {
                     84:        DBG0(DBG_IKE, "IKE_SA deleted");
                     85:        if (!this->rekeyed)
                     86:        {       /* invoke ike_down() hook if SA has not been rekeyed */
                     87:                charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
                     88:        }
                     89:        /* completed, delete IKE_SA by returning DESTROY_ME */
                     90:        return DESTROY_ME;
                     91: }
                     92: 
                     93: /**
                     94:  * Check if this delete happened after a rekey collision
                     95:  */
                     96: static bool after_rekey_collision(private_ike_delete_t *this)
                     97: {
                     98:        enumerator_t *tasks;
                     99:        task_t *task;
                    100: 
                    101:        tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
                    102:                                                                                                 TASK_QUEUE_ACTIVE);
                    103:        while (tasks->enumerate(tasks, &task))
                    104:        {
                    105:                if (task->get_type(task) == TASK_IKE_REKEY)
                    106:                {
                    107:                        ike_rekey_t *rekey = (ike_rekey_t*)task;
                    108: 
                    109:                        if (rekey->did_collide(rekey))
                    110:                        {
                    111:                                tasks->destroy(tasks);
                    112:                                return TRUE;
                    113:                        }
                    114:                }
                    115:        }
                    116:        tasks->destroy(tasks);
                    117:        return FALSE;
                    118: }
                    119: 
                    120: METHOD(task_t, process_r, status_t,
                    121:        private_ike_delete_t *this, message_t *message)
                    122: {
                    123:        /* we don't even scan the payloads, as the message wouldn't have
                    124:         * come so far without being correct */
                    125:        DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]",
                    126:                 this->ike_sa->get_name(this->ike_sa),
                    127:                 this->ike_sa->get_unique_id(this->ike_sa));
                    128:        DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%Y]...%H[%Y]",
                    129:                 this->ike_sa->get_name(this->ike_sa),
                    130:                 this->ike_sa->get_unique_id(this->ike_sa),
                    131:                 this->ike_sa->get_my_host(this->ike_sa),
                    132:                 this->ike_sa->get_my_id(this->ike_sa),
                    133:                 this->ike_sa->get_other_host(this->ike_sa),
                    134:                 this->ike_sa->get_other_id(this->ike_sa));
                    135: 
                    136:        if (message->get_exchange_type(message) == INFORMATIONAL &&
                    137:                message->get_notify(message, AUTHENTICATION_FAILED))
                    138:        {
                    139:                /* a late AUTHENTICATION_FAILED notify from the initiator after
                    140:                 * we have established the IKE_SA: signal auth failure */
                    141:                charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
                    142:        }
                    143: 
                    144:        switch (this->ike_sa->get_state(this->ike_sa))
                    145:        {
                    146:                case IKE_REKEYING:
                    147:                        /* if the peer concurrently deleted the IKE_SA we treat this as
                    148:                         * regular delete.  however, in case the peer did not detect a rekey
                    149:                         * collision it will delete the replaced IKE_SA if we are still in
                    150:                         * state IKE_REKEYING */
                    151:                        if (after_rekey_collision(this))
                    152:                        {
                    153:                                this->rekeyed = TRUE;
                    154:                                break;
                    155:                        }
                    156:                        /* fall-through */
                    157:                case IKE_ESTABLISHED:
                    158:                        this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
                    159:                        this->ike_sa->reestablish(this->ike_sa);
                    160:                        return NEED_MORE;
                    161:                case IKE_REKEYED:
                    162:                        this->rekeyed = TRUE;
                    163:                        break;
                    164:                default:
                    165:                        break;
                    166:        }
                    167:        this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
                    168:        return NEED_MORE;
                    169: }
                    170: 
                    171: /**
                    172:  * Check if we are currently deleting this IKE_SA in a break-before-make reauth.
                    173:  */
                    174: static bool is_reauthenticating(private_ike_delete_t *this)
                    175: {
                    176:        enumerator_t *tasks;
                    177:        task_t *task;
                    178: 
                    179:        if (!this->ike_sa->has_condition(this->ike_sa, COND_REAUTHENTICATING))
                    180:        {
                    181:                return FALSE;
                    182:        }
                    183: 
                    184:        tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
                    185:                                                                                                 TASK_QUEUE_ACTIVE);
                    186:        while (tasks->enumerate(tasks, &task))
                    187:        {
                    188:                if (task->get_type(task) == TASK_IKE_REAUTH)
                    189:                {
                    190:                        tasks->destroy(tasks);
                    191:                        return TRUE;
                    192:                }
                    193:        }
                    194:        tasks->destroy(tasks);
                    195:        return FALSE;
                    196: }
                    197: 
                    198: METHOD(task_t, build_r, status_t,
                    199:        private_ike_delete_t *this, message_t *message)
                    200: {
                    201:        DBG0(DBG_IKE, "IKE_SA deleted");
                    202: 
                    203:        if (!this->rekeyed)
                    204:        {       /* invoke ike_down() hook if SA has not been rekeyed */
                    205:                charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
                    206:        }
                    207: 
                    208:        /* if we are currently deleting this IKE_SA due to a break-before-make
                    209:         * reauthentication, make sure to not just silently destroy the SA if
                    210:         * the peer concurrently deletes it */
                    211:        if (is_reauthenticating(this))
                    212:        {
                    213:                if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS)
                    214:                {
                    215:                        DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
                    216:                }
                    217:        }
                    218: 
                    219:        /* completed, delete IKE_SA by returning DESTROY_ME */
                    220:        return DESTROY_ME;
                    221: }
                    222: 
                    223: METHOD(task_t, get_type, task_type_t,
                    224:        private_ike_delete_t *this)
                    225: {
                    226:        return TASK_IKE_DELETE;
                    227: }
                    228: 
                    229: METHOD(task_t, migrate, void,
                    230:        private_ike_delete_t *this, ike_sa_t *ike_sa)
                    231: {
                    232:        this->ike_sa = ike_sa;
                    233: }
                    234: 
                    235: METHOD(task_t, destroy, void,
                    236:        private_ike_delete_t *this)
                    237: {
                    238:        free(this);
                    239: }
                    240: 
                    241: /*
                    242:  * Described in header.
                    243:  */
                    244: ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator)
                    245: {
                    246:        private_ike_delete_t *this;
                    247: 
                    248:        INIT(this,
                    249:                .public = {
                    250:                        .task = {
                    251:                                .get_type = _get_type,
                    252:                                .migrate = _migrate,
                    253:                                .destroy = _destroy,
                    254:                        },
                    255:                },
                    256:                .ike_sa = ike_sa,
                    257:                .initiator = initiator,
                    258:        );
                    259: 
                    260:        if (initiator)
                    261:        {
                    262:                this->public.task.build = _build_i;
                    263:                this->public.task.process = _process_i;
                    264:        }
                    265:        else
                    266:        {
                    267:                this->public.task.build = _build_r;
                    268:                this->public.task.process = _process_r;
                    269:        }
                    270: 
                    271:        return &this->public;
                    272: }

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