4 * @brief Implementation of policy_t.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
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>.
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
31 #include <utils/linked_list.h>
32 #include <utils/identification.h>
34 ENUM(dpd_action_names
, DPD_NONE
, DPD_RESTART
,
41 ENUM(mode_names
, MODE_TRANSPORT
, MODE_BEET
,
49 typedef struct private_policy_t private_policy_t
;
52 * Private data of an policy_t object
54 struct private_policy_t
{
62 * Number of references hold by others to this policy
67 * Name of the policy, used to query it
72 * id to use to identify us
74 identification_t
*my_id
;
77 * allowed id for other
79 identification_t
*other_id
;
82 * virtual IP to use locally
84 host_t
*my_virtual_ip
;
87 * virtual IP to use remotly
89 host_t
*other_virtual_ip
;
92 * Method to use for own authentication data
94 auth_method_t auth_method
;
97 * EAP type to use for peer authentication
102 * we have a cert issued by this CA
104 identification_t
*my_ca
;
107 * we require the other end to have a cert issued by this CA
109 identification_t
*other_ca
;
122 * list for all proposals
124 linked_list_t
*proposals
;
127 * list for traffic selectors for my site
129 linked_list_t
*my_ts
;
132 * list for traffic selectors for others site
134 linked_list_t
*other_ts
;
137 * Time before an SA gets invalid
139 u_int32_t soft_lifetime
;
142 * Time before an SA gets rekeyed
144 u_int32_t hard_lifetime
;
147 * Time, which specifies the range of a random value
148 * substracted from soft_lifetime.
153 * What to do with an SA when other peer seams to be dead?
158 * Mode to propose for a initiated CHILD: tunnel/transport
164 * Implementation of policy_t.get_name
166 static char *get_name(private_policy_t
*this)
172 * Implementation of policy_t.get_my_id
174 static identification_t
*get_my_id(private_policy_t
*this)
180 * Implementation of policy_t.get_other_id
182 static identification_t
*get_other_id(private_policy_t
*this)
184 return this->other_id
;
188 * Implementation of policy_t.get_my_ca
190 static identification_t
*get_my_ca(private_policy_t
*this)
196 * Implementation of policy_t.get_other_ca
198 static identification_t
*get_other_ca(private_policy_t
*this)
200 return this->other_ca
;
204 * Implementation of connection_t.auth_method_t.
206 static auth_method_t
get_auth_method(private_policy_t
*this)
208 return this->auth_method
;
212 * Implementation of connection_t.get_eap_type.
214 static eap_type_t
get_eap_type(private_policy_t
*this)
216 return this->eap_type
;
220 * Get traffic selectors, with wildcard-address update
222 static linked_list_t
*get_traffic_selectors(private_policy_t
*this,
223 linked_list_t
*list
, host_t
*host
)
225 iterator_t
*iterator
;
226 traffic_selector_t
*current
;
227 linked_list_t
*result
= linked_list_create();
229 iterator
= list
->create_iterator(list
, TRUE
);
231 while (iterator
->iterate(iterator
, (void**)¤t
))
233 /* we make a copy of the TS, this allows us to update wildcard
234 * addresses in it. We won't pollute the shared policy. */
235 current
= current
->clone(current
);
238 current
->set_address(current
, host
);
241 result
->insert_last(result
, (void*)current
);
243 iterator
->destroy(iterator
);
248 * Implementation of policy_t.get_my_traffic_selectors
250 static linked_list_t
*get_my_traffic_selectors(private_policy_t
*this, host_t
*me
)
252 return get_traffic_selectors(this, this->my_ts
, me
);
256 * Implementation of policy_t.get_other_traffic_selectors
258 static linked_list_t
*get_other_traffic_selectors(private_policy_t
*this, host_t
*other
)
260 return get_traffic_selectors(this, this->other_ts
, other
);
264 * Narrow traffic selectors, with wildcard-address update in "stored".
266 static linked_list_t
*select_traffic_selectors(private_policy_t
*this,
267 linked_list_t
*stored
,
268 linked_list_t
*supplied
,
271 iterator_t
*supplied_iter
, *stored_iter
, *i1
, *i2
;
272 traffic_selector_t
*supplied_ts
, *stored_ts
, *selected_ts
, *ts1
, *ts2
;
273 linked_list_t
*selected
= linked_list_create();
275 DBG2(DBG_CFG
, "selecting traffic selectors");
277 stored_iter
= stored
->create_iterator(stored
, TRUE
);
278 supplied_iter
= supplied
->create_iterator(supplied
, TRUE
);
280 /* iterate over all stored selectors */
281 while (stored_iter
->iterate(stored_iter
, (void**)&stored_ts
))
283 /* we make a copy of the TS, this allows us to update wildcard
284 * addresses in it. We won't pollute the shared policy. */
285 stored_ts
= stored_ts
->clone(stored_ts
);
288 stored_ts
->set_address(stored_ts
, host
);
291 supplied_iter
->reset(supplied_iter
);
292 /* iterate over all supplied traffic selectors */
293 while (supplied_iter
->iterate(supplied_iter
, (void**)&supplied_ts
))
295 DBG2(DBG_CFG
, "stored %R <=> %R received",
296 stored_ts
, supplied_ts
);
298 selected_ts
= stored_ts
->get_subset(stored_ts
, supplied_ts
);
301 /* got a match, add to list */
302 selected
->insert_last(selected
, (void*)selected_ts
);
304 DBG2(DBG_CFG
, "found traffic selector for %s: %R",
305 stored
== this->my_ts ?
"us" : "other", selected_ts
);
308 stored_ts
->destroy(stored_ts
);
310 stored_iter
->destroy(stored_iter
);
311 supplied_iter
->destroy(supplied_iter
);
313 /* remove any redundant traffic selectors in the list */
314 i1
= selected
->create_iterator(selected
, TRUE
);
315 i2
= selected
->create_iterator(selected
, TRUE
);
316 while (i1
->iterate(i1
, (void**)&ts1
))
318 while (i2
->iterate(i2
, (void**)&ts2
))
320 if (ts1
!= ts2
&& ts2
->is_contained_in(ts2
, ts1
))
337 * Implementation of private_policy_t.select_my_traffic_selectors
339 static linked_list_t
*select_my_traffic_selectors(private_policy_t
*this,
340 linked_list_t
*supplied
,
343 return select_traffic_selectors(this, this->my_ts
, supplied
, me
);
347 * Implementation of private_policy_t.select_other_traffic_selectors
349 static linked_list_t
*select_other_traffic_selectors(private_policy_t
*this,
350 linked_list_t
*supplied
,
353 return select_traffic_selectors(this, this->other_ts
, supplied
, other
);
357 * Implementation of policy_t.get_proposal_iterator
359 static linked_list_t
*get_proposals(private_policy_t
*this)
361 iterator_t
*iterator
;
363 linked_list_t
*proposals
= linked_list_create();
365 iterator
= this->proposals
->create_iterator(this->proposals
, TRUE
);
366 while (iterator
->iterate(iterator
, (void**)¤t
))
368 current
= current
->clone(current
);
369 proposals
->insert_last(proposals
, (void*)current
);
371 iterator
->destroy(iterator
);
377 * Implementation of policy_t.select_proposal
379 static proposal_t
*select_proposal(private_policy_t
*this, linked_list_t
*proposals
)
381 iterator_t
*stored_iter
, *supplied_iter
;
382 proposal_t
*stored
, *supplied
, *selected
;
384 stored_iter
= this->proposals
->create_iterator(this->proposals
, TRUE
);
385 supplied_iter
= proposals
->create_iterator(proposals
, TRUE
);
387 /* compare all stored proposals with all supplied. Stored ones are preferred. */
388 while (stored_iter
->iterate(stored_iter
, (void**)&stored
))
390 supplied_iter
->reset(supplied_iter
);
391 while (supplied_iter
->iterate(supplied_iter
, (void**)&supplied
))
393 selected
= stored
->select(stored
, supplied
);
396 /* they match, return */
397 stored_iter
->destroy(stored_iter
);
398 supplied_iter
->destroy(supplied_iter
);
404 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
405 stored_iter
->destroy(stored_iter
);
406 supplied_iter
->destroy(supplied_iter
);
412 * Implementation of policy_t.add_authorities
414 static void add_authorities(private_policy_t
*this, identification_t
*my_ca
, identification_t
*other_ca
)
417 this->other_ca
= other_ca
;
421 * Implementation of policy_t.get_updown
423 static char* get_updown(private_policy_t
*this)
429 * Implementation of policy_t.get_hostaccess
431 static bool get_hostaccess(private_policy_t
*this)
433 return this->hostaccess
;
437 * Implements policy_t.get_dpd_action
439 static dpd_action_t
get_dpd_action(private_policy_t
*this)
441 return this->dpd_action
;
445 * Implementation of policy_t.add_my_traffic_selector
447 static void add_my_traffic_selector(private_policy_t
*this, traffic_selector_t
*traffic_selector
)
449 this->my_ts
->insert_last(this->my_ts
, (void*)traffic_selector
);
453 * Implementation of policy_t.add_other_traffic_selector
455 static void add_other_traffic_selector(private_policy_t
*this, traffic_selector_t
*traffic_selector
)
457 this->other_ts
->insert_last(this->other_ts
, (void*)traffic_selector
);
461 * Implementation of policy_t.add_proposal
463 static void add_proposal(private_policy_t
*this, proposal_t
*proposal
)
465 this->proposals
->insert_last(this->proposals
, (void*)proposal
);
469 * Implementation of policy_t.get_soft_lifetime
471 static u_int32_t
get_soft_lifetime(private_policy_t
*this)
473 if (this->jitter
== 0)
475 return this->soft_lifetime
;
477 return this->soft_lifetime
- (random() % this->jitter
);
481 * Implementation of policy_t.get_hard_lifetime
483 static u_int32_t
get_hard_lifetime(private_policy_t
*this)
485 return this->hard_lifetime
;
489 * Implementation of policy_t.get_mode.
491 static mode_t
get_mode(private_policy_t
*this)
497 * Implementation of policy_t.get_virtual_ip.
499 static host_t
* get_virtual_ip(private_policy_t
*this, host_t
*suggestion
)
501 if (suggestion
== NULL
)
503 if (this->my_virtual_ip
)
505 return this->my_virtual_ip
->clone(this->my_virtual_ip
);
509 if (this->other_virtual_ip
)
511 return this->other_virtual_ip
->clone(this->other_virtual_ip
);
513 if (suggestion
->is_anyaddr(suggestion
))
517 return suggestion
->clone(suggestion
);
521 * Implements policy_t.get_ref.
523 static void get_ref(private_policy_t
*this)
525 ref_get(&this->refcount
);
529 * Implements policy_t.destroy.
531 static void destroy(private_policy_t
*this)
533 if (ref_put(&this->refcount
))
536 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
537 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
538 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
540 /* delete certification authorities */
541 DESTROY_IF(this->my_ca
);
542 DESTROY_IF(this->other_ca
);
544 /* delete updown script */
551 this->my_id
->destroy(this->my_id
);
552 this->other_id
->destroy(this->other_id
);
553 DESTROY_IF(this->my_virtual_ip
);
554 DESTROY_IF(this->other_virtual_ip
);
562 * Described in header-file
564 policy_t
*policy_create(char *name
, identification_t
*my_id
, identification_t
*other_id
,
565 host_t
*my_virtual_ip
, host_t
*other_virtual_ip
,
566 auth_method_t auth_method
, eap_type_t eap_type
,
567 u_int32_t hard_lifetime
, u_int32_t soft_lifetime
,
568 u_int32_t jitter
, char *updown
, bool hostaccess
,
569 mode_t mode
, dpd_action_t dpd_action
)
571 private_policy_t
*this = malloc_thing(private_policy_t
);
573 /* public functions */
574 this->public.get_name
= (char* (*) (policy_t
*))get_name
;
575 this->public.get_my_id
= (identification_t
* (*) (policy_t
*))get_my_id
;
576 this->public.get_other_id
= (identification_t
* (*) (policy_t
*))get_other_id
;
577 this->public.get_my_ca
= (identification_t
* (*) (policy_t
*))get_my_ca
;
578 this->public.get_other_ca
= (identification_t
* (*) (policy_t
*))get_other_ca
;
579 this->public.get_auth_method
= (auth_method_t (*) (policy_t
*)) get_auth_method
;
580 this->public.get_eap_type
= (eap_type_t (*) (policy_t
*)) get_eap_type
;
581 this->public.get_my_traffic_selectors
= (linked_list_t
* (*) (policy_t
*,host_t
*))get_my_traffic_selectors
;
582 this->public.get_other_traffic_selectors
= (linked_list_t
* (*) (policy_t
*,host_t
*))get_other_traffic_selectors
;
583 this->public.select_my_traffic_selectors
= (linked_list_t
* (*) (policy_t
*,linked_list_t
*,host_t
*))select_my_traffic_selectors
;
584 this->public.select_other_traffic_selectors
= (linked_list_t
* (*) (policy_t
*,linked_list_t
*,host_t
*))select_other_traffic_selectors
;
585 this->public.get_proposals
= (linked_list_t
* (*) (policy_t
*))get_proposals
;
586 this->public.select_proposal
= (proposal_t
* (*) (policy_t
*,linked_list_t
*))select_proposal
;
587 this->public.add_my_traffic_selector
= (void (*) (policy_t
*,traffic_selector_t
*))add_my_traffic_selector
;
588 this->public.add_other_traffic_selector
= (void (*) (policy_t
*,traffic_selector_t
*))add_other_traffic_selector
;
589 this->public.add_proposal
= (void (*) (policy_t
*,proposal_t
*))add_proposal
;
590 this->public.add_authorities
= (void (*) (policy_t
*,identification_t
*,identification_t
*))add_authorities
;
591 this->public.get_updown
= (char* (*) (policy_t
*))get_updown
;
592 this->public.get_hostaccess
= (bool (*) (policy_t
*))get_hostaccess
;
593 this->public.get_dpd_action
= (dpd_action_t (*) (policy_t
*))get_dpd_action
;
594 this->public.get_soft_lifetime
= (u_int32_t (*) (policy_t
*))get_soft_lifetime
;
595 this->public.get_hard_lifetime
= (u_int32_t (*) (policy_t
*))get_hard_lifetime
;
596 this->public.get_mode
= (mode_t (*) (policy_t
*))get_mode
;
597 this->public.get_virtual_ip
= (host_t
* (*)(policy_t
*,host_t
*))get_virtual_ip
;
598 this->public.get_ref
= (void (*) (policy_t
*))get_ref
;
599 this->public.destroy
= (void (*) (policy_t
*))destroy
;
601 /* apply init values */
602 this->name
= strdup(name
);
604 this->other_id
= other_id
;
605 this->my_virtual_ip
= my_virtual_ip
;
606 this->other_virtual_ip
= other_virtual_ip
;
607 this->auth_method
= auth_method
;
608 this->eap_type
= eap_type
;
609 this->hard_lifetime
= hard_lifetime
;
610 this->soft_lifetime
= soft_lifetime
;
611 this->jitter
= jitter
;
612 this->updown
= (updown
== NULL
) ? NULL
: strdup(updown
);
613 this->hostaccess
= hostaccess
;
614 this->dpd_action
= dpd_action
;
617 /* initialize private members*/
620 this->other_ca
= NULL
;
621 this->proposals
= linked_list_create();
622 this->my_ts
= linked_list_create();
623 this->other_ts
= linked_list_create();
625 return &this->public;