46af18694bbbd157da061a42b12b7b57429fe9cc
[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_CONFIG_NAME, peer_cfg->get_name(peer_cfg));
110 m->add_attribute(m, HA_SYNC_CONDITIONS, condition);
111 m->add_attribute(m, HA_SYNC_EXTENSIONS, extension);
112 if (local_vip)
113 {
114 m->add_attribute(m, HA_SYNC_LOCAL_VIP, local_vip);
115 }
116 if (remote_vip)
117 {
118 m->add_attribute(m, HA_SYNC_REMOTE_VIP, remote_vip);
119 }
120 if (eap_id)
121 {
122 m->add_attribute(m, HA_SYNC_EAP_ID, eap_id);
123 }
124 iterator = ike_sa->create_additional_address_iterator(ike_sa);
125 while (iterator->iterate(iterator, (void**)&addr))
126 {
127 m->add_attribute(m, HA_SYNC_ADDITIONAL_ADDR, addr);
128 }
129 iterator->destroy(iterator);
130 }
131 else
132 {
133 m = ha_sync_message_create(HA_SYNC_IKE_REKEY);
134
135 m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
136 m->add_attribute(m, HA_SYNC_IKE_REKEY_ID, rekey->get_id(rekey));
137 }
138
139 m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i);
140 m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r);
141 m->add_attribute(m, HA_SYNC_SECRET, secret);
142 chunk_clear(&secret);
143
144 this->socket->push(this->socket, m);
145 m->destroy(m);
146
147 return TRUE;
148 }
149
150 /**
151 * Implementation of ha_sync_ike_t.destroy.
152 */
153 static void destroy(private_ha_sync_ike_t *this)
154 {
155 free(this);
156 }
157
158 /**
159 * See header
160 */
161 ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket)
162 {
163 private_ha_sync_ike_t *this = malloc_thing(private_ha_sync_ike_t);
164
165 memset(&this->public.listener, 0, sizeof(listener_t));
166 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;
167 this->public.destroy = (void(*)(ha_sync_ike_t*))destroy;
168
169 this->socket = socket;
170
171 return &this->public;
172 }
173