- changed config load strategy:
[strongswan.git] / src / charon / config / connections / connection.c
1 /**
2 * @file connection.c
3 *
4 * @brief Implementation of connection_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 <string.h>
24
25 #include "connection.h"
26
27 #include <utils/linked_list.h>
28 #include <utils/logger.h>
29
30 /**
31 * String mappings for auth_method_t.
32 */
33 mapping_t auth_method_m[] = {
34 {RSA_DIGITAL_SIGNATURE, "RSA"},
35 {SHARED_KEY_MESSAGE_INTEGRITY_CODE, "SHARED_KEY"},
36 {DSS_DIGITAL_SIGNATURE, "DSS"},
37 {MAPPING_END, NULL}
38 };
39
40
41 typedef struct private_connection_t private_connection_t;
42
43 /**
44 * Private data of an connection_t object
45 */
46 struct private_connection_t {
47
48 /**
49 * Public part
50 */
51 connection_t public;
52
53 /**
54 * Name of the connection
55 */
56 char *name;
57
58 /**
59 * Does charon handle this connection? Or can he ignore it?
60 */
61 bool ikev2;
62
63 /**
64 * ID of us
65 */
66 identification_t *my_id;
67
68 /**
69 * ID of remote peer
70 */
71 identification_t *other_id;
72
73 /**
74 * Host information of my host.
75 */
76 host_t *my_host;
77
78 /**
79 * Host information of other host.
80 */
81 host_t *other_host;
82
83 /**
84 * Method to use for own authentication data
85 */
86 auth_method_t auth_method;
87
88 /**
89 * Supported proposals
90 */
91 linked_list_t *proposals;
92 };
93
94 /**
95 * Implementation of connection_t.get_name.
96 */
97 static char *get_name (private_connection_t *this)
98 {
99 return this->name;
100 }
101
102 /**
103 * Implementation of connection_t.is_ikev2.
104 */
105 static bool is_ikev2 (private_connection_t *this)
106 {
107 return this->ikev2;
108 }
109
110 /**
111 * Implementation of connection_t.get_my_id.
112 */
113 static identification_t *get_my_id (private_connection_t *this)
114 {
115 return this->my_id;
116 }
117
118 /**
119 * Implementation of connection_t.get_other_id.
120 */
121 static identification_t *get_other_id(private_connection_t *this)
122 {
123 return this->other_id;
124 }
125
126 /**
127 * Implementation of connection_t.update_my_id
128 */
129 static void update_my_id(private_connection_t *this, identification_t *my_id)
130 {
131 this->my_id->destroy(this->my_id);
132 this->my_id = my_id;
133 }
134
135 /**
136 * Implementation of connection_t.update_other_id
137 */
138 static void update_other_id(private_connection_t *this, identification_t *other_id)
139 {
140 this->other_id->destroy(this->other_id);
141 this->other_id = other_id;
142 }
143
144 /**
145 * Implementation of connection_t.get_my_host.
146 */
147 static host_t * get_my_host (private_connection_t *this)
148 {
149 return this->my_host;
150 }
151
152 /**
153 * Implementation of connection_t.update_my_host.
154 */
155 static void update_my_host(private_connection_t *this, host_t *my_host)
156 {
157 this->my_host->destroy(this->my_host);
158 this->my_host = my_host;
159 }
160
161 /**
162 * Implementation of connection_t.update_other_host.
163 */
164 static void update_other_host(private_connection_t *this, host_t *other_host)
165 {
166 this->other_host->destroy(this->other_host);
167 this->other_host = other_host;
168 }
169
170 /**
171 * Implementation of connection_t.get_other_host.
172 */
173 static host_t * get_other_host (private_connection_t *this)
174 {
175 return this->other_host;
176 }
177
178 /**
179 * Implementation of connection_t.get_proposals.
180 */
181 static linked_list_t* get_proposals (private_connection_t *this)
182 {
183 return this->proposals;
184 }
185
186 /**
187 * Implementation of connection_t.select_proposal.
188 */
189 static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
190 {
191 iterator_t *stored_iter, *supplied_iter;
192 proposal_t *stored, *supplied, *selected;
193
194 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
195 supplied_iter = proposals->create_iterator(proposals, TRUE);
196
197 /* compare all stored proposals with all supplied. Stored ones are preferred. */
198 while (stored_iter->has_next(stored_iter))
199 {
200 supplied_iter->reset(supplied_iter);
201 stored_iter->current(stored_iter, (void**)&stored);
202
203 while (supplied_iter->has_next(supplied_iter))
204 {
205 supplied_iter->current(supplied_iter, (void**)&supplied);
206 selected = stored->select(stored, supplied);
207 if (selected)
208 {
209 /* they match, return */
210 stored_iter->destroy(stored_iter);
211 supplied_iter->destroy(supplied_iter);
212 return selected;
213 }
214 }
215 }
216
217 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
218 stored_iter->destroy(stored_iter);
219 supplied_iter->destroy(supplied_iter);
220
221 return NULL;
222 }
223
224 /**
225 * Implementation of connection_t.add_proposal.
226 */
227 static void add_proposal (private_connection_t *this, proposal_t *proposal)
228 {
229 this->proposals->insert_last(this->proposals, proposal);
230 }
231
232 /**
233 * Implementation of connection_t.auth_method_t.
234 */
235 static auth_method_t get_auth_method(private_connection_t *this)
236 {
237 return this->auth_method;
238 }
239
240 /**
241 * Implementation of connection_t.get_dh_group.
242 */
243 static diffie_hellman_group_t get_dh_group(private_connection_t *this)
244 {
245 iterator_t *iterator;
246 proposal_t *proposal;
247 algorithm_t *algo;
248
249 iterator = this->proposals->create_iterator(this->proposals, TRUE);
250 while (iterator->has_next(iterator))
251 {
252 iterator->current(iterator, (void**)&proposal);
253 proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo);
254 if (algo)
255 {
256 iterator->destroy(iterator);
257 return algo->algorithm;
258 }
259 }
260 iterator->destroy(iterator);
261 return MODP_UNDEFINED;
262 }
263
264 /**
265 * Implementation of connection_t.check_dh_group.
266 */
267 static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
268 {
269 iterator_t *prop_iter, *alg_iter;
270 proposal_t *proposal;
271 algorithm_t *algo;
272
273 prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
274 while (prop_iter->has_next(prop_iter))
275 {
276 prop_iter->current(prop_iter, (void**)&proposal);
277 alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP);
278 while (alg_iter->has_next(alg_iter))
279 {
280 alg_iter->current(alg_iter, (void**)&algo);
281 if (algo->algorithm == dh_group)
282 {
283 prop_iter->destroy(prop_iter);
284 alg_iter->destroy(alg_iter);
285 return TRUE;
286 }
287 }
288 }
289 prop_iter->destroy(prop_iter);
290 alg_iter->destroy(alg_iter);
291 return FALSE;
292 }
293
294 /**
295 * Implementation of connection_t.clone.
296 */
297 static connection_t *clone(private_connection_t *this)
298 {
299 iterator_t *iterator;
300 proposal_t *proposal;
301 private_connection_t *clone = (private_connection_t*)connection_create(
302 this->name,
303 this->ikev2,
304 this->my_host->clone(this->my_host),
305 this->other_host->clone(this->other_host),
306 this->my_id->clone(this->my_id),
307 this->other_id->clone(this->other_id),
308 this->auth_method);
309
310 /* clone all proposals */
311 iterator = this->proposals->create_iterator(this->proposals, TRUE);
312 while (iterator->has_next(iterator))
313 {
314 iterator->current(iterator, (void**)&proposal);
315 proposal = proposal->clone(proposal);
316 clone->proposals->insert_last(clone->proposals, (void*)proposal);
317 }
318 iterator->destroy(iterator);
319
320 return &clone->public;
321 }
322
323 /**
324 * Implementation of connection_t.destroy.
325 */
326 static void destroy(private_connection_t *this)
327 {
328 proposal_t *proposal;
329
330 while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
331 {
332 proposal->destroy(proposal);
333 }
334 this->proposals->destroy(this->proposals);
335
336 this->my_host->destroy(this->my_host);
337 this->other_host->destroy(this->other_host);
338 this->my_id->destroy(this->my_id);
339 this->other_id->destroy(this->other_id);
340 free(this->name);
341 free(this);
342 }
343
344 /**
345 * Described in header.
346 */
347 connection_t * connection_create(char *name, bool ikev2, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method)
348 {
349 private_connection_t *this = malloc_thing(private_connection_t);
350
351 /* public functions */
352 this->public.get_name = (char*(*)(connection_t*))get_name;
353 this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
354 this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id;
355 this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id;
356 this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
357 this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
358 this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
359 this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id;
360 this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id;
361 this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
362 this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
363 this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
364 this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
365 this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
366 this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
367 this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
368 this->public.clone = (connection_t*(*)(connection_t*))clone;
369 this->public.destroy = (void(*)(connection_t*))destroy;
370
371 /* private variables */
372 this->name = strdup(name);
373 this->ikev2 = ikev2;
374 this->my_host = my_host;
375 this->other_host = other_host;
376 this->my_id = my_id;
377 this->other_id = other_id;
378 this->auth_method = auth_method;
379
380 this->proposals = linked_list_create();
381
382 return (&this->public);
383 }