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