added a dispatcher class to receive HA sync messages
[strongswan.git] / src / charon / plugins / ha_sync / ha_sync_ike.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * 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 * $Id$
16 */
17
18 #include "ha_sync_ike.h"
19
20 typedef struct private_ha_sync_ike_t private_ha_sync_ike_t;
21
22 /**
23 * Private data of an ha_sync_ike_t object.
24 */
25 struct private_ha_sync_ike_t {
26
27 /**
28 * Public ha_sync_ike_t interface.
29 */
30 ha_sync_ike_t public;
31
32 /**
33 * socket we use for syncing
34 */
35 ha_sync_socket_t *socket;
36 };
37
38 /**
39 * Return condition if it is set on ike_sa
40 */
41 static ike_condition_t copy_condition(ike_sa_t *ike_sa, ike_condition_t cond)
42 {
43 if (ike_sa->has_condition(ike_sa, cond))
44 {
45 return cond;
46 }
47 return 0;
48 }
49
50 /**
51 * Return extension if it is supported by peers IKE_SA
52 */
53 static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
54 {
55 if (ike_sa->supports_extension(ike_sa, ext))
56 {
57 return ext;
58 }
59 return 0;
60 }
61
62 /**
63 * Implementation of listener_t.ike_keys
64 */
65 static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa,
66 diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
67 ike_sa_t *rekey)
68 {
69 iterator_t *iterator;
70 ha_sync_message_t *m;
71 peer_cfg_t *peer_cfg;
72 u_int32_t extension, condition;
73 host_t *local_vip, *remote_vip, *addr;
74 identification_t *eap_id;
75 chunk_t secret;
76
77 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
78
79 condition = copy_condition(ike_sa, COND_NAT_ANY)
80 | copy_condition(ike_sa, COND_NAT_HERE)
81 | copy_condition(ike_sa, COND_NAT_THERE)
82 | copy_condition(ike_sa, COND_NAT_FAKE)
83 | copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
84 | copy_condition(ike_sa, COND_CERTREQ_SEEN)
85 | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR);
86
87 extension = copy_extension(ike_sa, EXT_NATT)
88 | copy_extension(ike_sa, EXT_MOBIKE)
89 | copy_extension(ike_sa, EXT_HASH_AND_URL);
90
91 local_vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
92 remote_vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
93 eap_id = ike_sa->get_eap_identity(ike_sa);
94
95 if (dh->get_shared_secret(dh, &secret) != SUCCESS)
96 {
97 return TRUE;
98 }
99
100 if (rekey == NULL)
101 {
102 m = ha_sync_message_create(HA_SYNC_IKE_ADD);
103
104 m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
105 m->add_attribute(m, HA_SYNC_LOCAL_ID, ike_sa->get_my_id(ike_sa));
106 m->add_attribute(m, HA_SYNC_REMOTE_ID, ike_sa->get_other_id(ike_sa));
107 m->add_attribute(m, HA_SYNC_LOCAL_ADDR, ike_sa->get_my_host(ike_sa));
108 m->add_attribute(m, HA_SYNC_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
109 m->add_attribute(m, HA_SYNC_CONDITIONS, condition);
110 m->add_attribute(m, HA_SYNC_EXTENSIONS, extension);
111 if (local_vip)
112 {
113 m->add_attribute(m, HA_SYNC_LOCAL_VIP, local_vip);
114 }
115 if (remote_vip)
116 {
117 m->add_attribute(m, HA_SYNC_REMOTE_VIP, remote_vip);
118 }
119 if (eap_id)
120 {
121 m->add_attribute(m, HA_SYNC_EAP_ID, eap_id);
122 }
123 iterator = ike_sa->create_additional_address_iterator(ike_sa);
124 while (iterator->iterate(iterator, (void**)&addr))
125 {
126 m->add_attribute(m, HA_SYNC_ADDITIONAL_ADDR, addr);
127 }
128 iterator->destroy(iterator);
129 }
130 else
131 {
132 m = ha_sync_message_create(HA_SYNC_IKE_REKEY);
133
134 m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
135 m->add_attribute(m, HA_SYNC_IKE_REKEY_ID, rekey->get_id(rekey));
136 }
137
138 m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i);
139 m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r);
140 m->add_attribute(m, HA_SYNC_SECRET, secret);
141 chunk_clear(&secret);
142
143 this->socket->push(this->socket, m);
144 m->destroy(m);
145
146 return TRUE;
147 }
148
149 /**
150 * Implementation of ha_sync_ike_t.destroy.
151 */
152 static void destroy(private_ha_sync_ike_t *this)
153 {
154 free(this);
155 }
156
157 /**
158 * See header
159 */
160 ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket)
161 {
162 private_ha_sync_ike_t *this = malloc_thing(private_ha_sync_ike_t);
163
164 memset(&this->public.listener, 0, sizeof(listener_t));
165 this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
166 this->public.destroy = (void(*)(ha_sync_ike_t*))destroy;
167
168 this->socket = socket;
169
170 return &this->public;
171 }
172