/* * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "hook.h" #include typedef struct private_force_cookie_t private_force_cookie_t; /** * Private data of an force_cookie_t object. */ struct private_force_cookie_t { /** * Implements the hook_t interface. */ hook_t hook; }; METHOD(listener_t, message, bool, private_force_cookie_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain) { if (incoming && plain && message->get_request(message) && message->get_exchange_type(message) == IKE_SA_INIT) { enumerator_t *enumerator; bool has_cookie = FALSE; payload_t *payload; enumerator = message->create_payload_enumerator(message); while (enumerator->enumerate(enumerator, &payload)) { if (payload->get_type(payload) == PLV2_NOTIFY) { notify_payload_t *notify = (notify_payload_t*)payload; chunk_t data; if (notify->get_notify_type(notify) == COOKIE) { data = notify->get_notification_data(notify); DBG1(DBG_CFG, "received COOKIE: %#B", &data); has_cookie = TRUE; break; } } } enumerator->destroy(enumerator); if (!has_cookie) { message_t *response; host_t *src, *dst; packet_t *packet; ike_sa_id_t *ike_sa_id; chunk_t data = chunk_from_thing("COOKIE test data"); DBG1(DBG_CFG, "sending COOKIE: %#B", &data); response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION); dst = message->get_source(message); src = message->get_destination(message); response->set_source(response, src->clone(src)); response->set_destination(response, dst->clone(dst)); response->set_exchange_type(response, IKE_SA_INIT); response->set_request(response, FALSE); response->set_message_id(response, 0); ike_sa_id = message->get_ike_sa_id(message); ike_sa_id->switch_initiator(ike_sa_id); response->set_ike_sa_id(response, ike_sa_id); response->add_notify(response, FALSE, COOKIE, data); if (response->generate(response, NULL, &packet) == SUCCESS) { charon->sender->send(charon->sender, packet); response->destroy(response); } message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED); } } return TRUE; } METHOD(hook_t, destroy, void, private_force_cookie_t *this) { free(this); } /** * Create the IKE_AUTH fill hook */ hook_t *force_cookie_hook_create(char *name) { private_force_cookie_t *this; INIT(this, .hook = { .listener = { .message = _message, }, .destroy = _destroy, }, ); return &this->hook; }