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