debug and logging improvements
[strongswan.git] / src / charon / config / policies / policy.c
1 /**
2 * @file policy.c
3 *
4 * @brief Implementation of policy_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <time.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "policy.h"
28
29 #include <utils/linked_list.h>
30 #include <utils/identification.h>
31 #include <utils/logger.h>
32
33 typedef struct private_policy_t private_policy_t;
34
35 /**
36 * Private data of an policy_t object
37 */
38 struct private_policy_t {
39
40 /**
41 * Public part
42 */
43 policy_t public;
44
45 /**
46 * Name of the policy, used to query it
47 */
48 char *name;
49
50 /**
51 * id to use to identify us
52 */
53 identification_t *my_id;
54
55 /**
56 * allowed id for other
57 */
58 identification_t *other_id;
59
60 /**
61 * we have a cert issued by this CA
62 */
63 identification_t *my_ca;
64
65 /**
66 * we require the other end to have a cert issued by this CA
67 */
68 identification_t *other_ca;
69
70 /**
71 * list for all proposals
72 */
73 linked_list_t *proposals;
74
75 /**
76 * list for traffic selectors for my site
77 */
78 linked_list_t *my_ts;
79
80 /**
81 * list for traffic selectors for others site
82 */
83 linked_list_t *other_ts;
84
85 /**
86 * Time before an SA gets invalid
87 */
88 u_int32_t soft_lifetime;
89
90 /**
91 * Time before an SA gets rekeyed
92 */
93 u_int32_t hard_lifetime;
94
95 /**
96 * Time, which specifies the range of a random value
97 * substracted from soft_lifetime.
98 */
99 u_int32_t jitter;
100
101 /**
102 * select_traffic_selectors for both
103 */
104 linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*);
105 };
106
107 /**
108 * Implementation of policy_t.get_name
109 */
110 static char *get_name(private_policy_t *this)
111 {
112 return this->name;
113 }
114
115 /**
116 * Implementation of policy_t.get_my_id
117 */
118 static identification_t *get_my_id(private_policy_t *this)
119 {
120 return this->my_id;
121 }
122
123 /**
124 * Implementation of policy_t.get_other_id
125 */
126 static identification_t *get_other_id(private_policy_t *this)
127 {
128 return this->other_id;
129 }
130
131 /**
132 * Implementation of policy_t.update_my_id
133 */
134 static void update_my_id(private_policy_t *this, identification_t *my_id)
135 {
136 this->my_id->destroy(this->my_id);
137 this->my_id = my_id;
138 }
139
140 /**
141 * Implementation of policy_t.update_other_id
142 */
143 static void update_other_id(private_policy_t *this, identification_t *other_id)
144 {
145 this->other_id->destroy(this->other_id);
146 this->other_id = other_id;
147 }
148
149 /**
150 * Helper function which does the work for policy_t.update_my_ts and update_other_ts
151 */
152 static void update_ts(linked_list_t* list, host_t *new_host)
153 {
154 traffic_selector_t *ts;
155 iterator_t *iterator;
156
157 iterator = list->create_iterator(list, TRUE);
158 while (iterator->has_next(iterator))
159 {
160 iterator->current(iterator, (void**)&ts);
161 ts->update_address_range(ts, new_host);
162 }
163 iterator->destroy(iterator);
164 }
165
166 /**
167 * Implementation of policy_t.update_my_id
168 */
169 static void update_my_ts(private_policy_t *this, host_t *my_host)
170 {
171 update_ts(this->my_ts, my_host);
172 }
173
174 /**
175 * Implementation of policy_t.update_other_ts
176 */
177 static void update_other_ts(private_policy_t *this, host_t *my_host)
178 {
179 update_ts(this->other_ts, my_host);
180 }
181
182 /**
183 * Implementation of policy_t.get_my_traffic_selectors
184 */
185 static linked_list_t *get_my_traffic_selectors(private_policy_t *this)
186 {
187 return this->my_ts;
188 }
189
190 /**
191 * Implementation of policy_t.get_other_traffic_selectors
192 */
193 static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[])
194 {
195 return this->other_ts;
196 }
197
198 /**
199 * Implementation of private_policy_t.select_my_traffic_selectors
200 */
201 static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
202 {
203 return this->select_traffic_selectors(this, this->my_ts, supplied);
204 }
205
206 /**
207 * Implementation of private_policy_t.select_other_traffic_selectors
208 */
209 static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
210 {
211 return this->select_traffic_selectors(this, this->other_ts, supplied);
212 }
213 /**
214 * Implementation of private_policy_t.select_traffic_selectors
215 */
216 static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
217 {
218 iterator_t *supplied_iter, *stored_iter;
219 traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
220 linked_list_t *selected = linked_list_create();
221
222
223 stored_iter = stored->create_iterator(stored, TRUE);
224 supplied_iter = supplied->create_iterator(supplied, TRUE);
225
226 /* iterate over all stored selectors */
227 while (stored_iter->has_next(stored_iter))
228 {
229 stored_iter->current(stored_iter, (void**)&stored_ts);
230
231 supplied_iter->reset(supplied_iter);
232 /* iterate over all supplied traffic selectors */
233 while (supplied_iter->has_next(supplied_iter))
234 {
235 supplied_iter->current(supplied_iter, (void**)&supplied_ts);
236
237 selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
238 if (selected_ts)
239 {
240 /* got a match, add to list */
241 selected->insert_last(selected, (void*)selected_ts);
242 }
243 }
244 }
245 stored_iter->destroy(stored_iter);
246 supplied_iter->destroy(supplied_iter);
247
248 return selected;
249 }
250
251 /**
252 * Implementation of policy_t.get_proposal_iterator
253 */
254 static linked_list_t *get_proposals(private_policy_t *this)
255 {
256 return this->proposals;
257 }
258
259 /**
260 * Implementation of policy_t.select_proposal
261 */
262 static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals)
263 {
264 iterator_t *stored_iter, *supplied_iter;
265 proposal_t *stored, *supplied, *selected;
266
267 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
268 supplied_iter = proposals->create_iterator(proposals, TRUE);
269
270 /* compare all stored proposals with all supplied. Stored ones are preferred. */
271 while (stored_iter->has_next(stored_iter))
272 {
273 supplied_iter->reset(supplied_iter);
274 stored_iter->current(stored_iter, (void**)&stored);
275
276 while (supplied_iter->has_next(supplied_iter))
277 {
278 supplied_iter->current(supplied_iter, (void**)&supplied);
279 selected = stored->select(stored, supplied);
280 if (selected)
281 {
282 /* they match, return */
283 stored_iter->destroy(stored_iter);
284 supplied_iter->destroy(supplied_iter);
285 return selected;
286 }
287 }
288 }
289
290 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
291 stored_iter->destroy(stored_iter);
292 supplied_iter->destroy(supplied_iter);
293
294 return NULL;
295 }
296
297 /**
298 * Implementation of policy_t.add_authorities
299 */
300 static void add_authorities(private_policy_t *this, identification_t *my_ca, identification_t *other_ca)
301 {
302 this->my_ca = my_ca;
303 this->other_ca = other_ca;
304 }
305
306 /**
307 * Implementation of policy_t.add_my_traffic_selector
308 */
309 static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
310 {
311 this->my_ts->insert_last(this->my_ts, (void*)traffic_selector);
312 }
313
314 /**
315 * Implementation of policy_t.add_other_traffic_selector
316 */
317 static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
318 {
319 this->other_ts->insert_last(this->other_ts, (void*)traffic_selector);
320 }
321
322 /**
323 * Implementation of policy_t.add_proposal
324 */
325 static void add_proposal(private_policy_t *this, proposal_t *proposal)
326 {
327 this->proposals->insert_last(this->proposals, (void*)proposal);
328 }
329
330 /**
331 * Implementation of policy_t.get_soft_lifetime
332 */
333 static u_int32_t get_soft_lifetime(private_policy_t *this)
334 {
335 if (this->jitter == 0)
336 {
337 return this->soft_lifetime ;
338 }
339 srandom(time(NULL)+getpid());
340 return this->soft_lifetime - (random() % this->jitter);
341 }
342
343 /**
344 * Implementation of policy_t.get_hard_lifetime
345 */
346 static u_int32_t get_hard_lifetime(private_policy_t *this)
347 {
348 return this->hard_lifetime;
349 }
350
351 /**
352 * Implements policy_t.clone.
353 */
354 static policy_t *clone(private_policy_t *this)
355 {
356 private_policy_t *clone = (private_policy_t*)policy_create(this->name,
357 this->my_id->clone(this->my_id),
358 this->other_id->clone(this->other_id),
359 this->hard_lifetime, this->soft_lifetime,
360 this->jitter);
361 iterator_t *iterator;
362 proposal_t *proposal;
363 traffic_selector_t *ts;
364
365 /* clone the certification authorities */
366 if (this->my_ca)
367 {
368 clone->my_ca = this->my_ca->clone(this->my_ca);
369 }
370 if (this->other_ca)
371 {
372 clone->other_ca = this->other_ca->clone(this->other_ca);
373 }
374
375 /* clone all proposals */
376 iterator = this->proposals->create_iterator(this->proposals, TRUE);
377 while (iterator->has_next(iterator))
378 {
379 iterator->current(iterator, (void**)&proposal);
380 proposal = proposal->clone(proposal);
381 clone->proposals->insert_last(clone->proposals, (void*)proposal);
382 }
383 iterator->destroy(iterator);
384
385 /* clone all local traffic selectors */
386 iterator = this->my_ts->create_iterator(this->my_ts, TRUE);
387 while (iterator->has_next(iterator))
388 {
389 iterator->current(iterator, (void**)&ts);
390 ts = ts->clone(ts);
391 clone->my_ts->insert_last(clone->my_ts, (void*)ts);
392 }
393 iterator->destroy(iterator);
394
395 /* clone all remote traffic selectors */
396 iterator = this->other_ts->create_iterator(this->other_ts, TRUE);
397 while (iterator->has_next(iterator))
398 {
399 iterator->current(iterator, (void**)&ts);
400 ts = ts->clone(ts);
401 clone->other_ts->insert_last(clone->other_ts, (void*)ts);
402 }
403 iterator->destroy(iterator);
404
405 return &clone->public;
406 }
407
408 /**
409 * Implements policy_t.destroy.
410 */
411 static status_t destroy(private_policy_t *this)
412 {
413 proposal_t *proposal;
414 traffic_selector_t *traffic_selector;
415
416
417 /* delete proposals */
418 while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
419 {
420 proposal->destroy(proposal);
421 }
422 this->proposals->destroy(this->proposals);
423
424 /* delete traffic selectors */
425 while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
426 {
427 traffic_selector->destroy(traffic_selector);
428 }
429 this->my_ts->destroy(this->my_ts);
430
431 /* delete traffic selectors */
432 while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
433 {
434 traffic_selector->destroy(traffic_selector);
435 }
436 this->other_ts->destroy(this->other_ts);
437
438 /* delete certification authorities */
439 if (this->my_ca)
440 {
441 this->my_ca->destroy(this->my_ca);
442 }
443 if (this->other_ca)
444 {
445 this->other_ca->destroy(this->other_ca);
446 }
447
448 /* delete ids */
449 this->my_id->destroy(this->my_id);
450 this->other_id->destroy(this->other_id);
451
452 free(this->name);
453 free(this);
454 return SUCCESS;
455 }
456
457 /*
458 * Described in header-file
459 */
460 policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
461 u_int32_t hard_lifetime, u_int32_t soft_lifetime,
462 u_int32_t jitter)
463 {
464 private_policy_t *this = malloc_thing(private_policy_t);
465
466 /* public functions */
467 this->public.get_name = (char *(*)(policy_t*))get_name;
468 this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id;
469 this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id;
470 this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id;
471 this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id;
472 this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts;
473 this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts;
474 this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors;
475 this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors;
476 this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors;
477 this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors;
478 this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals;
479 this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal;
480 this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
481 this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
482 this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
483 this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities;
484 this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
485 this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
486 this->public.clone = (policy_t*(*)(policy_t*))clone;
487 this->public.destroy = (void(*)(policy_t*))destroy;
488
489 /* apply init values */
490 this->name = strdup(name);
491 this->my_id = my_id;
492 this->other_id = other_id;
493 this->hard_lifetime = hard_lifetime;
494 this->soft_lifetime = soft_lifetime;
495 this->jitter = jitter;
496
497 /* initialize private members*/
498 this->my_ca = NULL;
499 this->other_ca = NULL;
500 this->select_traffic_selectors = select_traffic_selectors;
501 this->proposals = linked_list_create();
502 this->my_ts = linked_list_create();
503 this->other_ts = linked_list_create();
504
505 return (&this->public);
506 }