- fixed equals for new struct definition
[strongswan.git] / Source / charon / config / sa_config.c
1 /**
2 * @file sa_config.c
3 *
4 * @brief Implementation of sa_config_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 "sa_config.h"
24
25 #include <utils/linked_list.h>
26 #include <utils/allocator.h>
27 #include <utils/identification.h>
28
29 typedef struct private_sa_config_t private_sa_config_t;
30
31 /**
32 * Private data of an sa_config_t object
33 */
34 struct private_sa_config_t {
35
36 /**
37 * Public part
38 */
39 sa_config_t public;
40
41 /**
42 * id to use to identify us
43 */
44 identification_t *my_id;
45
46 /**
47 * allowed id for other
48 */
49 identification_t *other_id;
50
51 /**
52 * authentification method to use
53 */
54 auth_method_t auth_method;
55
56 /**
57 * list for all proposals
58 */
59 linked_list_t *proposals;
60
61 /**
62 * list for traffic selectors
63 */
64 linked_list_t *ts;
65
66 /**
67 * compare two traffic_selectors for equality
68 */
69 bool (*traffic_selector_equals) (private_sa_config_t *this, traffic_selector_t *first, traffic_selector_t *second);
70
71 /**
72 * compare two proposals for equality
73 */
74 bool (*proposal_equals) (private_sa_config_t *this, child_proposal_t *first, child_proposal_t *second);
75 };
76
77 /**
78 * implements sa_config_t.get_my_id
79 */
80 static identification_t *get_my_id(private_sa_config_t *this)
81 {
82 return this->my_id;
83 }
84
85 /**
86 * implements sa_config_t.get_other_id
87 */
88 static identification_t *get_other_id(private_sa_config_t *this)
89 {
90 return this->other_id;
91 }
92
93 /**
94 * implements sa_config_t.get_auth_method
95 */
96 static auth_method_t get_auth_method(private_sa_config_t *this)
97 {
98 return this->auth_method;
99 }
100
101 /**
102 * implements sa_config_t.get_traffic_selectors
103 */
104 static size_t get_traffic_selectors(private_sa_config_t *this, traffic_selector_t **traffic_selectors)
105 {
106 iterator_t *iterator;
107 traffic_selector_t *current_ts;
108 int counter = 0;
109 *traffic_selectors = allocator_alloc(sizeof(traffic_selector_t) * this->ts->get_count(this->ts));
110
111 /* copy all ts from the list in an array */
112 iterator = this->ts->create_iterator(this->ts, TRUE);
113 while (iterator->has_next(iterator))
114 {
115 iterator->current(iterator, (void**)&current_ts);
116 memcpy((*traffic_selectors) + counter, current_ts, sizeof(traffic_selector_t));
117 counter++;
118 }
119 iterator->destroy(iterator);
120 return counter;
121 }
122
123 /**
124 * implements sa_config_t.select_traffic_selectors
125 */
126 static size_t select_traffic_selectors(private_sa_config_t *this, traffic_selector_t *supplied, size_t count, traffic_selector_t **selected)
127 {
128 iterator_t *iterator;
129 traffic_selector_t *current_ts;
130 int i, counter = 0;
131 *selected = allocator_alloc(sizeof(traffic_selector_t) * this->ts->get_count(this->ts));
132
133 /* iterate over all stored proposals */
134 iterator = this->ts->create_iterator(this->ts, TRUE);
135 while (iterator->has_next(iterator))
136 {
137 iterator->current(iterator, (void**)&current_ts);
138 for (i = 0; i < count; i++)
139 {
140 /* copy if a supplied one is equal to ours */
141 if (this->traffic_selector_equals(this, &(supplied[i]), current_ts))
142 {
143 memcpy((*selected) + counter, current_ts, sizeof(traffic_selector_t));
144 counter++;
145 }
146 }
147 }
148 iterator->destroy(iterator);
149
150 /* free unused space */
151 *selected = allocator_realloc(*selected, sizeof(traffic_selector_t) * counter);
152 return counter;
153 }
154
155 /**
156 * implements sa_config_t.get_proposals
157 */
158 static size_t get_proposals(private_sa_config_t *this, child_proposal_t **proposals)
159 {
160 iterator_t *iterator;
161 child_proposal_t *current_proposal;
162 int counter = 0;
163 *proposals = allocator_alloc(sizeof(child_proposal_t) * this->proposals->get_count(this->proposals));
164
165 /* copy all proposals from the list in an array */
166 iterator = this->proposals->create_iterator(this->proposals, TRUE);
167 while (iterator->has_next(iterator))
168 {
169 iterator->current(iterator, (void**)&current_proposal);
170 memcpy((*proposals) + counter, current_proposal, sizeof(child_proposal_t));
171 counter++;
172 }
173 iterator->destroy(iterator);
174 return counter;
175 }
176
177 /**
178 * implements sa_config_t.select_proposal
179 */
180 static child_proposal_t *select_proposal(private_sa_config_t *this, child_proposal_t *supplied, size_t count)
181 {
182 iterator_t *iterator;
183 child_proposal_t *current_proposal, *selected_proposal = NULL;
184 int i;
185
186 /* iterate over all stored proposals */
187 iterator = this->proposals->create_iterator(this->proposals, TRUE);
188 while (iterator->has_next(iterator))
189 {
190 iterator->current(iterator, (void**)&current_proposal);
191 /* copy and break if a proposal matches */
192 for (i = 0; i < count; i++)
193 {
194 if (this->proposal_equals(this, &(supplied[i]), current_proposal))
195 {
196 selected_proposal = allocator_alloc(sizeof(child_proposal_t));
197 memcpy(selected_proposal, current_proposal, sizeof(child_proposal_t));
198 break;
199 }
200 }
201 }
202 iterator->destroy(iterator);
203
204 return selected_proposal;
205 }
206
207 /**
208 * implements private_sa_config_t.traffic_selector_equals
209 */
210 static bool traffic_selector_equals(private_sa_config_t *this, traffic_selector_t *first, traffic_selector_t *second)
211 {
212 if (first->protocol == second->protocol)
213 {
214 if (first->begin->equals(first->begin, second->begin) &&
215 first->end->equals(first->end, second->end))
216 {
217 return TRUE;
218
219 }
220 }
221 return FALSE;
222 }
223
224 /**
225 * implements private_sa_config_t.proposal_equals
226 */
227 static bool proposal_equals(private_sa_config_t *this, child_proposal_t *first, child_proposal_t *second)
228 {
229 bool equal = FALSE;
230
231 if (first->ah.is_set && second->ah.is_set)
232 {
233 if ((first->ah.integrity_algorithm != second->ah.integrity_algorithm) ||
234 (first->ah.integrity_algorithm_key_size != second->ah.integrity_algorithm_key_size) ||
235 (first->ah.diffie_hellman_group != second->ah.diffie_hellman_group) ||
236 (first->ah.extended_sequence_numbers != second->ah.extended_sequence_numbers))
237 {
238 return FALSE;
239 }
240 equal = TRUE;
241 }
242 if (first->esp.is_set && second->esp.is_set)
243 {
244 if ((first->esp.encryption_algorithm != second->esp.encryption_algorithm) ||
245 (first->esp.encryption_algorithm_key_size != second->esp.encryption_algorithm_key_size) ||
246 (first->esp.integrity_algorithm != second->esp.integrity_algorithm) ||
247 (first->esp.integrity_algorithm_key_size != second->esp.integrity_algorithm_key_size) ||
248 (first->esp.diffie_hellman_group != second->esp.diffie_hellman_group) ||
249 (first->esp.extended_sequence_numbers != second->esp.extended_sequence_numbers))
250 {
251 return FALSE;
252 }
253 equal = TRUE;
254 }
255 return equal;
256 }
257
258 /**
259 * implements sa_config_t.add_traffic_selector
260 */
261 static void add_traffic_selector(private_sa_config_t *this, traffic_selector_t *traffic_selector)
262 {
263 /* clone ts, and add*/
264 traffic_selector_t *new_ts = allocator_alloc_thing(traffic_selector_t);
265 *new_ts = *traffic_selector;
266 this->ts->insert_last(this->ts, (void*)new_ts);
267 }
268
269 /**
270 * implements sa_config_t.add_proposal
271 */
272 static void add_proposal(private_sa_config_t *this, child_proposal_t *proposal)
273 {
274 /* clone proposal, and add*/
275 child_proposal_t *new_proposal = allocator_alloc_thing(child_proposal_t);
276 *new_proposal = *proposal;
277 this->proposals->insert_last(this->proposals, (void*)new_proposal);
278 }
279
280 /**
281 * Implements sa_config_t.destroy.
282 */
283 static status_t destroy(private_sa_config_t *this)
284 {
285 child_proposal_t *proposal;
286 traffic_selector_t *traffic_selector;
287
288
289 /* delete proposals */
290 while(this->proposals->get_count(this->proposals) > 0)
291 {
292 this->proposals->remove_last(this->proposals, (void**)&proposal);
293 allocator_free(proposal);
294 }
295 this->proposals->destroy(this->proposals);
296
297 /* delete traffic selectors */
298 while(this->ts->get_count(this->ts) > 0)
299 {
300 this->ts->remove_last(this->ts, (void**)&traffic_selector);
301 allocator_free(traffic_selector);
302 }
303 this->ts->destroy(this->ts);
304
305 /* delete ids */
306 this->my_id->destroy(this->my_id);
307 this->other_id->destroy(this->other_id);
308
309 allocator_free(this);
310 return SUCCESS;
311 }
312
313 /*
314 * Described in header-file
315 */
316 sa_config_t *sa_config_create(id_type_t my_id_type, char *my_id, id_type_t other_id_type, char *other_id, auth_method_t auth_method)
317 {
318 private_sa_config_t *this = allocator_alloc_thing(private_sa_config_t);
319
320 /* public functions */
321 this->public.get_my_id = (identification_t(*)(sa_config_t*))get_my_id;
322 this->public.get_other_id = (identification_t(*)(sa_config_t*))get_other_id;
323 this->public.get_auth_method = (auth_method_t(*)(sa_config_t*))get_auth_method;
324 this->public.get_traffic_selectors = (size_t(*)(sa_config_t*,traffic_selector_t**))get_traffic_selectors;
325 this->public.select_traffic_selectors = (size_t(*)(sa_config_t*,traffic_selector_t*,size_t,traffic_selector_t**))select_traffic_selectors;
326 this->public.get_proposals = (size_t(*)(sa_config_t*,child_proposal_t**))get_proposals;
327 this->public.select_proposal = (child_proposal_t*(*)(sa_config_t*,child_proposal_t*,size_t))select_proposal;
328 this->public.add_traffic_selector = (void(*)(sa_config_t*,traffic_selector_t*))add_traffic_selector;
329 this->public.add_proposal = (void(*)(sa_config_t*,child_proposal_t*))add_proposal;
330 this->public.destroy = (void(*)(sa_config_t*))destroy;
331
332
333 /* apply init values */
334 this->my_id = identification_create_from_string(my_id_type, my_id);
335 if (this->my_id == NULL)
336 {
337 allocator_free(this);
338 return NULL;
339 }
340 this->other_id = identification_create_from_string(other_id_type, other_id);
341 if (this->my_id == NULL)
342 {
343 this->other_id->destroy(this->other_id);
344 allocator_free(this);
345 return NULL;
346 }
347
348 /* init private members*/
349 this->proposal_equals = proposal_equals;
350 this->traffic_selector_equals = traffic_selector_equals;
351 this->proposals = linked_list_create();
352 this->ts = linked_list_create();
353
354 return (&this->public);
355 }