added mobike=yes|no connection option
[strongswan.git] / src / charon / config / peer_cfg.c
1 /**
2 * @file peer_cfg.c
3 *
4 * @brief Implementation of peer_cfg_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <string.h>
25 #include <pthread.h>
26
27 #include "peer_cfg.h"
28
29 #include <utils/linked_list.h>
30 #include <utils/identification.h>
31
32 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
33 "CERT_ALWAYS_SEND",
34 "CERT_SEND_IF_ASKED",
35 "CERT_NEVER_SEND"
36 );
37
38 ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
39 "DPD_NONE",
40 "DPD_CLEAR",
41 "DPD_ROUTE",
42 "DPD_RESTART"
43 );
44
45 typedef struct private_peer_cfg_t private_peer_cfg_t;
46
47 /**
48 * Private data of an peer_cfg_t object
49 */
50 struct private_peer_cfg_t {
51
52 /**
53 * Public part
54 */
55 peer_cfg_t public;
56
57 /**
58 * Number of references hold by others to this peer_cfg
59 */
60 refcount_t refcount;
61
62 /**
63 * Name of the peer_cfg, used to query it
64 */
65 char *name;
66
67 /**
68 * IKE version to use for initiation
69 */
70 u_int ike_version;
71
72 /**
73 * IKE config associated to this peer config
74 */
75 ike_cfg_t *ike_cfg;
76
77 /**
78 * list of child configs associated to this peer config
79 */
80 linked_list_t *child_cfgs;
81
82 /**
83 * mutex to lock access to list of child_cfgs
84 */
85 pthread_mutex_t mutex;
86
87 /**
88 * id to use to identify us
89 */
90 identification_t *my_id;
91
92 /**
93 * allowed id for other
94 */
95 identification_t *other_id;
96
97 /**
98 * we have a cert issued by this CA
99 */
100 identification_t *my_ca;
101
102 /**
103 * we require the other end to have a cert issued by this CA
104 */
105 identification_t *other_ca;
106
107 /**
108 * should we send a certificate
109 */
110 cert_policy_t cert_policy;
111
112 /**
113 * Method to use for own authentication data
114 */
115 auth_method_t auth_method;
116
117 /**
118 * EAP type to use for peer authentication
119 */
120 eap_type_t eap_type;
121
122 /**
123 * number of tries after giving up if peer does not respond
124 */
125 u_int32_t keyingtries;
126
127 /**
128 * user reauthentication instead of rekeying
129 */
130 bool use_reauth;
131
132 /**
133 * enable support for MOBIKE
134 */
135 bool use_mobike;
136
137 /**
138 * Time before an SA gets invalid
139 */
140 u_int32_t lifetime;
141
142 /**
143 * Time before an SA gets rekeyed
144 */
145 u_int32_t rekeytime;
146
147 /**
148 * Time, which specifies the range of a random value
149 * substracted from lifetime.
150 */
151 u_int32_t jitter;
152
153 /**
154 * What to do with an SA when other peer seams to be dead?
155 */
156 bool dpd_delay;
157
158 /**
159 * What to do with CHILDren when other peer seams to be dead?
160 */
161 bool dpd_action;
162
163 /**
164 * virtual IP to use locally
165 */
166 host_t *my_virtual_ip;
167
168 /**
169 * virtual IP to use remotly
170 */
171 host_t *other_virtual_ip;
172 };
173
174 /**
175 * Implementation of peer_cfg_t.get_name
176 */
177 static char *get_name(private_peer_cfg_t *this)
178 {
179 return this->name;
180 }
181
182 /**
183 * Implementation of peer_cfg_t.get_ike_version
184 */
185 static u_int get_ike_version(private_peer_cfg_t *this)
186 {
187 return this->ike_version;
188 }
189
190 /**
191 * Implementation of peer_cfg_t.get_ike_cfg
192 */
193 static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
194 {
195 return this->ike_cfg;
196 }
197
198 /**
199 * Implementation of peer_cfg_t.add_child_cfg.
200 */
201 static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
202 {
203 pthread_mutex_lock(&this->mutex);
204 this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
205 pthread_mutex_unlock(&this->mutex);
206 }
207
208 /**
209 * Implementation of peer_cfg_t.create_child_cfg_iterator.
210 */
211 static iterator_t* create_child_cfg_iterator(private_peer_cfg_t *this)
212 {
213 return this->child_cfgs->create_iterator_locked(this->child_cfgs,
214 &this->mutex);
215 }
216
217 /**
218 * Check if child_cfg contains traffic selectors
219 */
220 static bool contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
221 host_t *host)
222 {
223 linked_list_t *selected;
224 bool contains = FALSE;
225
226 selected = child->get_traffic_selectors(child, mine, ts, host);
227 contains = selected->get_count(selected);
228 selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
229 return contains;
230 }
231
232 /**
233 * Implementation of peer_cfg_t.select_child_cfg
234 */
235 static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
236 linked_list_t *my_ts,
237 linked_list_t *other_ts,
238 host_t *my_host, host_t *other_host)
239 {
240 child_cfg_t *current, *found = NULL;
241 iterator_t *iterator;
242
243 iterator = create_child_cfg_iterator(this);
244 while (iterator->iterate(iterator, (void**)&current))
245 {
246 if (contains_ts(current, TRUE, my_ts, my_host) &&
247 contains_ts(current, FALSE, other_ts, other_host))
248 {
249 found = current;
250 found->get_ref(found);
251 break;
252 }
253 }
254 iterator->destroy(iterator);
255 return found;
256 }
257
258 /**
259 * Implementation of peer_cfg_t.get_my_id
260 */
261 static identification_t *get_my_id(private_peer_cfg_t *this)
262 {
263 return this->my_id;
264 }
265
266 /**
267 * Implementation of peer_cfg_t.get_other_id
268 */
269 static identification_t *get_other_id(private_peer_cfg_t *this)
270 {
271 return this->other_id;
272 }
273
274 /**
275 * Implementation of peer_cfg_t.get_my_ca
276 */
277 static identification_t *get_my_ca(private_peer_cfg_t *this)
278 {
279 return this->my_ca;
280 }
281
282 static identification_t *get_other_ca(private_peer_cfg_t *this)
283 {
284 return this->other_ca;
285 }
286
287 /**
288 * Implementation of peer_cfg_t.get_cert_policy.
289 */
290 static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
291 {
292 return this->cert_policy;
293 }
294
295 /**
296 * Implementation of connection_t.auth_method_t.
297 */
298 static auth_method_t get_auth_method(private_peer_cfg_t *this)
299 {
300 return this->auth_method;
301 }
302
303 /**
304 * Implementation of connection_t.get_eap_type.
305 */
306 static eap_type_t get_eap_type(private_peer_cfg_t *this)
307 {
308 return this->eap_type;
309 }
310
311 /**
312 * Implementation of connection_t.get_keyingtries.
313 */
314 static u_int32_t get_keyingtries(private_peer_cfg_t *this)
315 {
316 return this->keyingtries;
317 }
318
319 /**
320 * Implementation of peer_cfg_t.get_soft_lifetime
321 */
322 static u_int32_t get_lifetime(private_peer_cfg_t *this, bool rekey)
323 {
324 if (rekey)
325 {
326 if (this->jitter == 0)
327 {
328 return this->rekeytime;
329 }
330 return this->rekeytime - (random() % this->jitter);
331 }
332 return this->lifetime;
333 }
334
335 /**
336 * Implementation of peer_cfg_t.use_reauth.
337 */
338 static bool use_reauth(private_peer_cfg_t *this)
339 {
340 return this->use_reauth;
341 }
342
343 /**
344 * Implementation of peer_cfg_t.use_mobike.
345 */
346 static bool use_mobike(private_peer_cfg_t *this)
347 {
348 return this->use_mobike;
349 }
350
351 /**
352 * Implements peer_cfg_t.get_dpd_delay
353 */
354 static u_int32_t get_dpd_delay(private_peer_cfg_t *this)
355 {
356 return this->dpd_delay;
357 }
358
359 /**
360 * Implements peer_cfg_t.get_dpd_action
361 */
362 static dpd_action_t get_dpd_action(private_peer_cfg_t *this)
363 {
364 return this->dpd_action;
365 }
366
367 /**
368 * Implementation of peer_cfg_t.get_my_virtual_ip.
369 */
370 static host_t* get_my_virtual_ip(private_peer_cfg_t *this)
371 {
372 if (this->my_virtual_ip == NULL)
373 {
374 return NULL;
375 }
376 return this->my_virtual_ip->clone(this->my_virtual_ip);
377 }
378
379 /**
380 * Implementation of peer_cfg_t.get_other_virtual_ip.
381 */
382 static host_t* get_other_virtual_ip(private_peer_cfg_t *this, host_t *suggestion)
383 {
384 if (this->other_virtual_ip == NULL)
385 { /* disallow */
386 return NULL;
387 }
388 if (!this->other_virtual_ip->is_anyaddr(this->other_virtual_ip))
389 { /* force own configuration */
390 return this->other_virtual_ip->clone(this->other_virtual_ip);
391 }
392 if (suggestion == NULL || suggestion->is_anyaddr(suggestion))
393 {
394 return NULL;
395 }
396 return suggestion->clone(suggestion);
397 }
398
399 /**
400 * Implements peer_cfg_t.get_ref.
401 */
402 static void get_ref(private_peer_cfg_t *this)
403 {
404 ref_get(&this->refcount);
405 }
406
407 /**
408 * Implements peer_cfg_t.destroy.
409 */
410 static void destroy(private_peer_cfg_t *this)
411 {
412 if (ref_put(&this->refcount))
413 {
414 this->ike_cfg->destroy(this->ike_cfg);
415 this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy));
416 this->my_id->destroy(this->my_id);
417 this->other_id->destroy(this->other_id);
418 DESTROY_IF(this->my_ca);
419 DESTROY_IF(this->other_ca);
420
421 DESTROY_IF(this->my_virtual_ip);
422 DESTROY_IF(this->other_virtual_ip);
423 free(this->name);
424 free(this);
425 }
426 }
427
428 /*
429 * Described in header-file
430 */
431 peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
432 identification_t *my_id, identification_t *other_id,
433 identification_t *my_ca, identification_t *other_ca,
434 cert_policy_t cert_policy, auth_method_t auth_method,
435 eap_type_t eap_type, u_int32_t keyingtries,
436 u_int32_t lifetime, u_int32_t rekeytime,
437 u_int32_t jitter, bool reauth, bool mobike,
438 u_int32_t dpd_delay, dpd_action_t dpd_action,
439 host_t *my_virtual_ip, host_t *other_virtual_ip)
440 {
441 private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t);
442
443 /* public functions */
444 this->public.get_name = (char* (*) (peer_cfg_t *))get_name;
445 this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version;
446 this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg;
447 this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg;
448 this->public.create_child_cfg_iterator = (iterator_t* (*) (peer_cfg_t *))create_child_cfg_iterator;
449 this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg;
450 this->public.get_my_id = (identification_t* (*)(peer_cfg_t*))get_my_id;
451 this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
452 this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca;
453 this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca;
454 this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
455 this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
456 this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type;
457 this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
458 this->public.get_lifetime = (u_int32_t (*) (peer_cfg_t *, bool rekey))get_lifetime;
459 this->public.use_reauth = (bool (*) (peer_cfg_t *))use_reauth;
460 this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike;
461 this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
462 this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
463 this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip;
464 this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip;
465 this->public.get_ref = (void(*)(peer_cfg_t *))get_ref;
466 this->public.destroy = (void(*)(peer_cfg_t *))destroy;
467
468 /* apply init values */
469 this->name = strdup(name);
470 this->ike_version = ike_version;
471 this->ike_cfg = ike_cfg;
472 this->child_cfgs = linked_list_create();
473 pthread_mutex_init(&this->mutex, NULL);
474 this->my_id = my_id;
475 this->other_id = other_id;
476 this->my_ca = my_ca;
477 this->other_ca = other_ca;
478 this->cert_policy = cert_policy;
479 this->auth_method = auth_method;
480 this->eap_type = eap_type;
481 this->keyingtries = keyingtries;
482 this->lifetime = lifetime;
483 this->rekeytime = rekeytime;
484 this->jitter = jitter;
485 this->use_reauth = reauth;
486 this->use_mobike = mobike;
487 this->dpd_delay = dpd_delay;
488 this->dpd_action = dpd_action;
489 this->my_virtual_ip = my_virtual_ip;
490 this->other_virtual_ip = other_virtual_ip;
491 this->refcount = 1;
492
493 return &this->public;
494 }