Make the UDP ports charon listens for packets on (and uses as source ports) configurable.
[strongswan.git] / src / libcharon / plugins / ha / ha_tunnel.c
1 /*
2 * Copyright (C) 2009 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
16 #include "ha_tunnel.h"
17 #include "ha_plugin.h"
18
19 #include <daemon.h>
20 #include <utils/identification.h>
21 #include <processing/jobs/callback_job.h>
22
23 typedef struct private_ha_tunnel_t private_ha_tunnel_t;
24 typedef struct ha_backend_t ha_backend_t;
25 typedef struct ha_creds_t ha_creds_t;
26
27 /**
28 * Serves credentials for the HA SA
29 */
30 struct ha_creds_t {
31
32 /**
33 * Implements credential_set_t
34 */
35 credential_set_t public;
36
37 /**
38 * own identity
39 */
40 identification_t *local;
41
42 /**
43 * peer identity
44 */
45 identification_t *remote;
46
47 /**
48 * Shared key to serve
49 */
50 shared_key_t *key;
51 };
52
53 /**
54 * Serves configurations for the HA SA
55 */
56 struct ha_backend_t {
57
58 /**
59 * Implements backend_t
60 */
61 backend_t public;
62
63 /**
64 * peer config we serve
65 */
66 peer_cfg_t *cfg;
67 };
68
69 /**
70 * Private data of an ha_tunnel_t object.
71 */
72 struct private_ha_tunnel_t {
73
74 /**
75 * Public ha_tunnel_t interface.
76 */
77 ha_tunnel_t public;
78
79 /**
80 * Reqid of installed trap
81 */
82 u_int32_t trap;
83
84 /**
85 * backend for HA SA
86 */
87 ha_backend_t backend;
88
89 /**
90 * credential set for HA SA
91 */
92 ha_creds_t creds;
93 };
94
95 METHOD(ha_tunnel_t, is_sa, bool,
96 private_ha_tunnel_t *this, ike_sa_t *ike_sa)
97 {
98 peer_cfg_t *cfg = this->backend.cfg;
99
100 return cfg && ike_sa->get_ike_cfg(ike_sa) == cfg->get_ike_cfg(cfg);
101 }
102
103 /**
104 * Enumerator over HA shared_key
105 */
106 typedef struct {
107 /** Implements enumerator_t */
108 enumerator_t public;
109 /** a single secret we serve */
110 shared_key_t *key;
111 } shared_enum_t;
112
113 METHOD(enumerator_t, shared_enumerate, bool,
114 shared_enum_t *this, shared_key_t **key, id_match_t *me, id_match_t *other)
115 {
116 if (this->key)
117 {
118 if (me)
119 {
120 *me = ID_MATCH_PERFECT;
121 }
122 if (other)
123 {
124 *other = ID_MATCH_PERFECT;
125 }
126 *key = this->key;
127 this->key = NULL;
128 return TRUE;
129 }
130 return FALSE;
131 }
132
133 METHOD(ha_creds_t, create_shared_enumerator, enumerator_t*,
134 ha_creds_t *this, shared_key_type_t type,
135 identification_t *me, identification_t *other)
136 {
137 shared_enum_t *enumerator;
138
139 if (type != SHARED_IKE && type != SHARED_ANY)
140 {
141 return NULL;
142 }
143 if (me && !me->equals(me, this->local))
144 {
145 return NULL;
146 }
147 if (other && !other->equals(other, this->remote))
148 {
149 return NULL;
150 }
151
152 INIT(enumerator,
153 .public = {
154 .enumerate = (void*)_shared_enumerate,
155 .destroy = (void*)free,
156 },
157 .key = this->key,
158 );
159
160 return &enumerator->public;
161 }
162
163 METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
164 ha_backend_t *this, identification_t *me, identification_t *other)
165 {
166 return enumerator_create_single(this->cfg, NULL);
167 }
168
169 METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
170 ha_backend_t *this, host_t *me, host_t *other)
171 {
172 return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL);
173 }
174
175 /**
176 * Install configs and a a trap for secured HA message exchange
177 */
178 static void setup_tunnel(private_ha_tunnel_t *this,
179 char *local, char *remote, char *secret)
180 {
181 peer_cfg_t *peer_cfg;
182 ike_cfg_t *ike_cfg;
183 auth_cfg_t *auth_cfg;
184 child_cfg_t *child_cfg;
185 traffic_selector_t *ts;
186 lifetime_cfg_t lifetime = {
187 .time = {
188 .life = 21600, .rekey = 20400, .jitter = 400,
189 },
190 };
191
192 /* setup credentials */
193 this->creds.local = identification_create_from_string(local);
194 this->creds.remote = identification_create_from_string(remote);
195 this->creds.key = shared_key_create(SHARED_IKE,
196 chunk_clone(chunk_create(secret, strlen(secret))));
197 this->creds.public.create_private_enumerator = (void*)return_null;
198 this->creds.public.create_cert_enumerator = (void*)return_null;
199 this->creds.public.create_shared_enumerator = (void*)_create_shared_enumerator;
200 this->creds.public.create_cdp_enumerator = (void*)return_null;
201 this->creds.public.cache_cert = (void*)nop;
202
203 lib->credmgr->add_set(lib->credmgr, &this->creds.public);
204
205 /* create config and backend */
206 ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, CHARON_UDP_PORT,
207 remote, FALSE, IKEV2_UDP_PORT);
208 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
209 peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
210 UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
211 0, NULL, NULL, FALSE, NULL, NULL);
212
213 auth_cfg = auth_cfg_create();
214 auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
215 auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY,
216 identification_create_from_string(local));
217 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
218
219 auth_cfg = auth_cfg_create();
220 auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
221 auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY,
222 identification_create_from_string(remote));
223 peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
224
225 child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
226 ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
227 0, 0, NULL, NULL, 0);
228 ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
229 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
230 ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
231 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
232 ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
233 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
234 ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
235 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
236 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
237 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
238
239 this->backend.cfg = peer_cfg;
240 this->backend.public.create_peer_cfg_enumerator = (void*)_create_peer_cfg_enumerator;
241 this->backend.public.create_ike_cfg_enumerator = (void*)_create_ike_cfg_enumerator;
242 this->backend.public.get_peer_cfg_by_name = (void*)return_null;
243
244 charon->backends->add_backend(charon->backends, &this->backend.public);
245
246 /* install an acquiring trap */
247 this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg);
248 }
249
250 METHOD(ha_tunnel_t, destroy, void,
251 private_ha_tunnel_t *this)
252 {
253 if (this->backend.cfg)
254 {
255 charon->backends->remove_backend(charon->backends, &this->backend.public);
256 this->backend.cfg->destroy(this->backend.cfg);
257 }
258 if (this->creds.key)
259 {
260 lib->credmgr->remove_set(lib->credmgr, &this->creds.public);
261 this->creds.key->destroy(this->creds.key);
262 }
263 this->creds.local->destroy(this->creds.local);
264 this->creds.remote->destroy(this->creds.remote);
265 if (this->trap)
266 {
267 charon->traps->uninstall(charon->traps, this->trap);
268 }
269 free(this);
270 }
271
272 /**
273 * See header
274 */
275 ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret)
276 {
277 private_ha_tunnel_t *this;
278
279 INIT(this,
280 .public = {
281 .is_sa = _is_sa,
282 .destroy = _destroy,
283 },
284 );
285
286 setup_tunnel(this, local, remote, secret);
287
288 return &this->public;
289 }
290