Migrated peer_cfg_t to INIT/METHOD macros.
[strongswan.git] / src / libcharon / config / peer_cfg.c
1 /*
2 * Copyright (C) 2007-2008 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <string.h>
19
20 #include "peer_cfg.h"
21
22 #include <daemon.h>
23
24 #include <threading/mutex.h>
25 #include <utils/linked_list.h>
26 #include <utils/identification.h>
27
28 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
29 "CERT_ALWAYS_SEND",
30 "CERT_SEND_IF_ASKED",
31 "CERT_NEVER_SEND",
32 );
33
34 ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
35 "UNIQUE_NO",
36 "UNIQUE_REPLACE",
37 "UNIQUE_KEEP",
38 );
39
40 typedef struct private_peer_cfg_t private_peer_cfg_t;
41
42 /**
43 * Private data of an peer_cfg_t object
44 */
45 struct private_peer_cfg_t {
46
47 /**
48 * Public part
49 */
50 peer_cfg_t public;
51
52 /**
53 * Number of references hold by others to this peer_cfg
54 */
55 refcount_t refcount;
56
57 /**
58 * Name of the peer_cfg, used to query it
59 */
60 char *name;
61
62 /**
63 * IKE version to use for initiation
64 */
65 u_int ike_version;
66
67 /**
68 * IKE config associated to this peer config
69 */
70 ike_cfg_t *ike_cfg;
71
72 /**
73 * list of child configs associated to this peer config
74 */
75 linked_list_t *child_cfgs;
76
77 /**
78 * mutex to lock access to list of child_cfgs
79 */
80 mutex_t *mutex;
81
82 /**
83 * should we send a certificate
84 */
85 cert_policy_t cert_policy;
86
87 /**
88 * uniqueness of an IKE_SA
89 */
90 unique_policy_t unique;
91
92 /**
93 * number of tries after giving up if peer does not respond
94 */
95 u_int32_t keyingtries;
96
97 /**
98 * enable support for MOBIKE
99 */
100 bool use_mobike;
101
102 /**
103 * Time before starting rekeying
104 */
105 u_int32_t rekey_time;
106
107 /**
108 * Time before starting reauthentication
109 */
110 u_int32_t reauth_time;
111
112 /**
113 * Time, which specifies the range of a random value subtracted from above.
114 */
115 u_int32_t jitter_time;
116
117 /**
118 * Delay before deleting a rekeying/reauthenticating SA
119 */
120 u_int32_t over_time;
121
122 /**
123 * DPD check intervall
124 */
125 u_int32_t dpd;
126
127 /**
128 * virtual IP to use locally
129 */
130 host_t *virtual_ip;
131
132 /**
133 * pool to acquire configuration attributes from
134 */
135 char *pool;
136
137 /**
138 * local authentication configs (rulesets)
139 */
140 linked_list_t *local_auth;
141
142 /**
143 * remote authentication configs (constraints)
144 */
145 linked_list_t *remote_auth;
146
147 #ifdef ME
148 /**
149 * Is this a mediation connection?
150 */
151 bool mediation;
152
153 /**
154 * Name of the mediation connection to mediate through
155 */
156 peer_cfg_t *mediated_by;
157
158 /**
159 * ID of our peer at the mediation server (= leftid of the peer's conn with
160 * the mediation server)
161 */
162 identification_t *peer_id;
163 #endif /* ME */
164 };
165
166 METHOD(peer_cfg_t, get_name, char*,
167 private_peer_cfg_t *this)
168 {
169 return this->name;
170 }
171
172 METHOD(peer_cfg_t, get_ike_version, u_int,
173 private_peer_cfg_t *this)
174 {
175 return this->ike_version;
176 }
177
178 METHOD(peer_cfg_t, get_ike_cfg, ike_cfg_t*,
179 private_peer_cfg_t *this)
180 {
181 return this->ike_cfg;
182 }
183
184 METHOD(peer_cfg_t, add_child_cfg, void,
185 private_peer_cfg_t *this, child_cfg_t *child_cfg)
186 {
187 this->mutex->lock(this->mutex);
188 this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
189 this->mutex->unlock(this->mutex);
190 }
191
192 /**
193 * child_cfg enumerator
194 */
195 typedef struct {
196 enumerator_t public;
197 enumerator_t *wrapped;
198 mutex_t *mutex;
199 } child_cfg_enumerator_t;
200
201 METHOD(peer_cfg_t, remove_child_cfg, void,
202 private_peer_cfg_t *this, child_cfg_enumerator_t *enumerator)
203 {
204 this->child_cfgs->remove_at(this->child_cfgs, enumerator->wrapped);
205 }
206
207 METHOD(enumerator_t, child_cfg_enumerator_destroy, void,
208 child_cfg_enumerator_t *this)
209 {
210 this->mutex->unlock(this->mutex);
211 this->wrapped->destroy(this->wrapped);
212 free(this);
213 }
214
215 METHOD(enumerator_t, child_cfg_enumerate, bool,
216 child_cfg_enumerator_t *this, child_cfg_t **chd)
217 {
218 return this->wrapped->enumerate(this->wrapped, chd);
219 }
220
221 METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*,
222 private_peer_cfg_t *this)
223 {
224 child_cfg_enumerator_t *enumerator;
225
226 INIT(enumerator,
227 .public = {
228 .enumerate = (void*)_child_cfg_enumerate,
229 .destroy = (void*)_child_cfg_enumerator_destroy,
230 },
231 .mutex = this->mutex,
232 .wrapped = this->child_cfgs->create_enumerator(this->child_cfgs),
233 );
234
235 this->mutex->lock(this->mutex);
236 return &enumerator->public;
237 }
238
239 /**
240 * Check how good a list of TS matches a given child config
241 */
242 static int get_ts_match(child_cfg_t *cfg, bool local,
243 linked_list_t *sup_list, host_t *host)
244 {
245 linked_list_t *cfg_list;
246 enumerator_t *sup_enum, *cfg_enum;
247 traffic_selector_t *sup_ts, *cfg_ts;
248 int match = 0, round;
249
250 /* fetch configured TS list, narrowing dynamic TS */
251 cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, host);
252
253 /* use a round counter to rate leading TS with higher priority */
254 round = sup_list->get_count(sup_list);
255
256 sup_enum = sup_list->create_enumerator(sup_list);
257 while (sup_enum->enumerate(sup_enum, &sup_ts))
258 {
259 cfg_enum = cfg_list->create_enumerator(cfg_list);
260 while (cfg_enum->enumerate(cfg_enum, &cfg_ts))
261 {
262 if (cfg_ts->equals(cfg_ts, sup_ts))
263 { /* equality is honored better than matches */
264 match += round * 5;
265 }
266 else if (cfg_ts->is_contained_in(cfg_ts, sup_ts) ||
267 sup_ts->is_contained_in(sup_ts, cfg_ts))
268 {
269 match += round * 1;
270 }
271 }
272 cfg_enum->destroy(cfg_enum);
273 round--;
274 }
275 sup_enum->destroy(sup_enum);
276
277 cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
278
279 return match;
280 }
281
282 METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
283 private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts,
284 host_t *my_host, host_t *other_host)
285 {
286 child_cfg_t *current, *found = NULL;
287 enumerator_t *enumerator;
288 int best = 0;
289
290 DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
291 enumerator = create_child_cfg_enumerator(this);
292 while (enumerator->enumerate(enumerator, &current))
293 {
294 int my_prio, other_prio;
295
296 my_prio = get_ts_match(current, TRUE, my_ts, my_host);
297 other_prio = get_ts_match(current, FALSE, other_ts, other_host);
298
299 if (my_prio && other_prio)
300 {
301 DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
302 current->get_name(current), my_prio, other_prio);
303 if (my_prio + other_prio > best)
304 {
305 best = my_prio + other_prio;
306 DESTROY_IF(found);
307 found = current->get_ref(current);
308 }
309 }
310 }
311 enumerator->destroy(enumerator);
312 if (found)
313 {
314 DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
315 found->get_name(found), best);
316 }
317 return found;
318 }
319
320 METHOD(peer_cfg_t, get_cert_policy, cert_policy_t,
321 private_peer_cfg_t *this)
322 {
323 return this->cert_policy;
324 }
325
326 METHOD(peer_cfg_t, get_unique_policy, unique_policy_t,
327 private_peer_cfg_t *this)
328 {
329 return this->unique;
330 }
331
332 METHOD(peer_cfg_t, get_keyingtries, u_int32_t,
333 private_peer_cfg_t *this)
334 {
335 return this->keyingtries;
336 }
337
338 METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
339 private_peer_cfg_t *this)
340 {
341 if (this->rekey_time == 0)
342 {
343 return 0;
344 }
345 if (this->jitter_time == 0)
346 {
347 return this->rekey_time;
348 }
349 return this->rekey_time - (random() % this->jitter_time);
350 }
351
352 METHOD(peer_cfg_t, get_reauth_time, u_int32_t,
353 private_peer_cfg_t *this)
354 {
355 if (this->reauth_time == 0)
356 {
357 return 0;
358 }
359 if (this->jitter_time == 0)
360 {
361 return this->reauth_time;
362 }
363 return this->reauth_time - (random() % this->jitter_time);
364 }
365
366 METHOD(peer_cfg_t, get_over_time, u_int32_t,
367 private_peer_cfg_t *this)
368 {
369 return this->over_time;
370 }
371
372 METHOD(peer_cfg_t, use_mobike, bool,
373 private_peer_cfg_t *this)
374 {
375 return this->use_mobike;
376 }
377
378 METHOD(peer_cfg_t, get_dpd, u_int32_t,
379 private_peer_cfg_t *this)
380 {
381 return this->dpd;
382 }
383
384 METHOD(peer_cfg_t, get_virtual_ip, host_t*,
385 private_peer_cfg_t *this)
386 {
387 return this->virtual_ip;
388 }
389
390 METHOD(peer_cfg_t, get_pool, char*,
391 private_peer_cfg_t *this)
392 {
393 return this->pool;
394 }
395
396 METHOD(peer_cfg_t, add_auth_cfg, void,
397 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
398 {
399 if (local)
400 {
401 this->local_auth->insert_last(this->local_auth, cfg);
402 }
403 else
404 {
405 this->remote_auth->insert_last(this->remote_auth, cfg);
406 }
407 }
408
409 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
410 private_peer_cfg_t *this, bool local)
411 {
412 if (local)
413 {
414 return this->local_auth->create_enumerator(this->local_auth);
415 }
416 return this->remote_auth->create_enumerator(this->remote_auth);
417 }
418
419 #ifdef ME
420 METHOD(peer_cfg_t, is_mediation, bool,
421 private_peer_cfg_t *this)
422 {
423 return this->mediation;
424 }
425
426 METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
427 private_peer_cfg_t *this)
428 {
429 return this->mediated_by;
430 }
431
432 METHOD(peer_cfg_t, get_peer_id, identification_t*,
433 private_peer_cfg_t *this)
434 {
435 return this->peer_id;
436 }
437 #endif /* ME */
438
439 /**
440 * check auth configs for equality
441 */
442 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
443 {
444 enumerator_t *e1, *e2;
445 auth_cfg_t *cfg1, *cfg2;
446 bool equal = TRUE;
447
448 if (this->local_auth->get_count(this->local_auth) !=
449 other->local_auth->get_count(other->local_auth))
450 {
451 return FALSE;
452 }
453 if (this->remote_auth->get_count(this->remote_auth) !=
454 other->remote_auth->get_count(other->remote_auth))
455 {
456 return FALSE;
457 }
458
459 e1 = this->local_auth->create_enumerator(this->local_auth);
460 e2 = other->local_auth->create_enumerator(other->local_auth);
461 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
462 {
463 if (!cfg1->equals(cfg1, cfg2))
464 {
465 equal = FALSE;
466 break;
467 }
468 }
469 e1->destroy(e1);
470 e2->destroy(e2);
471
472 if (!equal)
473 {
474 return FALSE;
475 }
476
477 e1 = this->remote_auth->create_enumerator(this->remote_auth);
478 e2 = other->remote_auth->create_enumerator(other->remote_auth);
479 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
480 {
481 if (!cfg1->equals(cfg1, cfg2))
482 {
483 equal = FALSE;
484 break;
485 }
486 }
487 e1->destroy(e1);
488 e2->destroy(e2);
489
490 return equal;
491 }
492
493 METHOD(peer_cfg_t, equals, bool,
494 private_peer_cfg_t *this, private_peer_cfg_t *other)
495 {
496 if (this == other)
497 {
498 return TRUE;
499 }
500 if (this->public.equals != other->public.equals)
501 {
502 return FALSE;
503 }
504
505 return (
506 this->ike_version == other->ike_version &&
507 this->cert_policy == other->cert_policy &&
508 this->unique == other->unique &&
509 this->keyingtries == other->keyingtries &&
510 this->use_mobike == other->use_mobike &&
511 this->rekey_time == other->rekey_time &&
512 this->reauth_time == other->reauth_time &&
513 this->jitter_time == other->jitter_time &&
514 this->over_time == other->over_time &&
515 this->dpd == other->dpd &&
516 (this->virtual_ip == other->virtual_ip ||
517 (this->virtual_ip && other->virtual_ip &&
518 this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
519 (this->pool == other->pool ||
520 (this->pool && other->pool && streq(this->pool, other->pool))) &&
521 auth_cfg_equal(this, other)
522 #ifdef ME
523 && this->mediation == other->mediation &&
524 this->mediated_by == other->mediated_by &&
525 (this->peer_id == other->peer_id ||
526 (this->peer_id && other->peer_id &&
527 this->peer_id->equals(this->peer_id, other->peer_id)))
528 #endif /* ME */
529 );
530 }
531
532 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
533 private_peer_cfg_t *this)
534 {
535 ref_get(&this->refcount);
536 return &this->public;
537 }
538
539 METHOD(peer_cfg_t, destroy, void,
540 private_peer_cfg_t *this)
541 {
542 if (ref_put(&this->refcount))
543 {
544 this->ike_cfg->destroy(this->ike_cfg);
545 this->child_cfgs->destroy_offset(this->child_cfgs,
546 offsetof(child_cfg_t, destroy));
547 DESTROY_IF(this->virtual_ip);
548 this->local_auth->destroy_offset(this->local_auth,
549 offsetof(auth_cfg_t, destroy));
550 this->remote_auth->destroy_offset(this->remote_auth,
551 offsetof(auth_cfg_t, destroy));
552 #ifdef ME
553 DESTROY_IF(this->mediated_by);
554 DESTROY_IF(this->peer_id);
555 #endif /* ME */
556 this->mutex->destroy(this->mutex);
557 free(this->name);
558 free(this->pool);
559 free(this);
560 }
561 }
562
563 /*
564 * Described in header-file
565 */
566 peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
567 cert_policy_t cert_policy, unique_policy_t unique,
568 u_int32_t keyingtries, u_int32_t rekey_time,
569 u_int32_t reauth_time, u_int32_t jitter_time,
570 u_int32_t over_time, bool mobike, u_int32_t dpd,
571 host_t *virtual_ip, char *pool,
572 bool mediation, peer_cfg_t *mediated_by,
573 identification_t *peer_id)
574 {
575 private_peer_cfg_t *this;
576
577 if (rekey_time && jitter_time > rekey_time)
578 {
579 jitter_time = rekey_time;
580 }
581 if (reauth_time && jitter_time > reauth_time)
582 {
583 jitter_time = reauth_time;
584 }
585
586 INIT(this,
587 .public = {
588 .get_name = _get_name,
589 .get_ike_version = _get_ike_version,
590 .get_ike_cfg = _get_ike_cfg,
591 .add_child_cfg = _add_child_cfg,
592 .remove_child_cfg = (void*)_remove_child_cfg,
593 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
594 .select_child_cfg = _select_child_cfg,
595 .get_cert_policy = _get_cert_policy,
596 .get_unique_policy = _get_unique_policy,
597 .get_keyingtries = _get_keyingtries,
598 .get_rekey_time = _get_rekey_time,
599 .get_reauth_time = _get_reauth_time,
600 .get_over_time = _get_over_time,
601 .use_mobike = _use_mobike,
602 .get_dpd = _get_dpd,
603 .get_virtual_ip = _get_virtual_ip,
604 .get_pool = _get_pool,
605 .add_auth_cfg = _add_auth_cfg,
606 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
607 .equals = (void*)_equals,
608 .get_ref = _get_ref,
609 .destroy = _destroy,
610 #ifdef ME
611 .is_mediation = _is_mediation,
612 .get_mediated_by = _get_mediated_by,
613 .get_peer_id = _get_peer_id,
614 #endif /* ME */
615 },
616 .name = strdup(name),
617 .ike_version = ike_version,
618 .ike_cfg = ike_cfg,
619 .child_cfgs = linked_list_create(),
620 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
621 .cert_policy = cert_policy,
622 .unique = unique,
623 .keyingtries = keyingtries,
624 .rekey_time = rekey_time,
625 .reauth_time = reauth_time,
626 .jitter_time = jitter_time,
627 .over_time = over_time,
628 .use_mobike = mobike,
629 .dpd = dpd,
630 .virtual_ip = virtual_ip,
631 .pool = strdupnull(pool),
632 .local_auth = linked_list_create(),
633 .remote_auth = linked_list_create(),
634 .refcount = 1,
635 );
636
637 #ifdef ME
638 this->mediation = mediation;
639 this->mediated_by = mediated_by;
640 this->peer_id = peer_id;
641 #else /* ME */
642 DESTROY_IF(mediated_by);
643 DESTROY_IF(peer_id);
644 #endif /* ME */
645
646 return &this->public;
647 }