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