- reworked usage of IDs in various states
[strongswan.git] / Source / 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 * ID of us
60 */
61 identification_t *my_id;
62
63 /**
64 * ID of remote peer
65 */
66 identification_t *other_id;
67
68 /**
69 * Host information of my host.
70 */
71 host_t *my_host;
72
73 /**
74 * Host information of other host.
75 */
76 host_t *other_host;
77
78 /**
79 * Method to use for own authentication data
80 */
81 auth_method_t auth_method;
82
83 /**
84 * Supported proposals
85 */
86 linked_list_t *proposals;
87 };
88
89 /**
90 * Implementation of connection_t.get_name.
91 */
92 static char *get_name (private_connection_t *this)
93 {
94 return this->name;
95 }
96
97 /**
98 * Implementation of connection_t.get_my_id.
99 */
100 static identification_t *get_my_id (private_connection_t *this)
101 {
102 return this->my_id;
103 }
104
105 /**
106 * Implementation of connection_t.get_other_id.
107 */
108 static identification_t *get_other_id(private_connection_t *this)
109 {
110 return this->other_id;
111 }
112
113 /**
114 * Implementation of connection_t.update_my_id
115 */
116 static void update_my_id(private_connection_t *this, identification_t *my_id)
117 {
118 this->my_id->destroy(this->my_id);
119 this->my_id = my_id;
120 }
121
122 /**
123 * Implementation of connection_t.update_other_id
124 */
125 static void update_other_id(private_connection_t *this, identification_t *other_id)
126 {
127 this->other_id->destroy(this->other_id);
128 this->other_id = other_id;
129 }
130
131 /**
132 * Implementation of connection_t.get_my_host.
133 */
134 static host_t * get_my_host (private_connection_t *this)
135 {
136 return this->my_host;
137 }
138
139 /**
140 * Implementation of connection_t.update_my_host.
141 */
142 static void update_my_host(private_connection_t *this, host_t *my_host)
143 {
144 this->my_host->destroy(this->my_host);
145 this->my_host = my_host;
146 }
147
148 /**
149 * Implementation of connection_t.update_other_host.
150 */
151 static void update_other_host(private_connection_t *this, host_t *other_host)
152 {
153 this->other_host->destroy(this->other_host);
154 this->other_host = other_host;
155 }
156
157 /**
158 * Implementation of connection_t.get_other_host.
159 */
160 static host_t * get_other_host (private_connection_t *this)
161 {
162 return this->other_host;
163 }
164
165 /**
166 * Implementation of connection_t.get_proposals.
167 */
168 static linked_list_t* get_proposals (private_connection_t *this)
169 {
170 return this->proposals;
171 }
172
173 /**
174 * Implementation of connection_t.select_proposal.
175 */
176 static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
177 {
178 iterator_t *stored_iter, *supplied_iter;
179 proposal_t *stored, *supplied, *selected;
180
181 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
182 supplied_iter = proposals->create_iterator(proposals, TRUE);
183
184 /* compare all stored proposals with all supplied. Stored ones are preferred. */
185 while (stored_iter->has_next(stored_iter))
186 {
187 supplied_iter->reset(supplied_iter);
188 stored_iter->current(stored_iter, (void**)&stored);
189
190 while (supplied_iter->has_next(supplied_iter))
191 {
192 supplied_iter->current(supplied_iter, (void**)&supplied);
193 selected = stored->select(stored, supplied);
194 if (selected)
195 {
196 /* they match, return */
197 stored_iter->destroy(stored_iter);
198 supplied_iter->destroy(supplied_iter);
199 return selected;
200 }
201 }
202 }
203
204 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
205 stored_iter->destroy(stored_iter);
206 supplied_iter->destroy(supplied_iter);
207
208 return NULL;
209 }
210
211 /**
212 * Implementation of connection_t.add_proposal.
213 */
214 static void add_proposal (private_connection_t *this, proposal_t *proposal)
215 {
216 this->proposals->insert_last(this->proposals, proposal);
217 }
218
219 /**
220 * Implementation of connection_t.auth_method_t.
221 */
222 static auth_method_t get_auth_method(private_connection_t *this)
223 {
224 return this->auth_method;
225 }
226
227 /**
228 * Implementation of connection_t.get_dh_group.
229 */
230 static diffie_hellman_group_t get_dh_group(private_connection_t *this)
231 {
232 iterator_t *iterator;
233 proposal_t *proposal;
234 algorithm_t *algo;
235
236 iterator = this->proposals->create_iterator(this->proposals, TRUE);
237 while (iterator->has_next(iterator))
238 {
239 iterator->current(iterator, (void**)&proposal);
240 proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo);
241 if (algo)
242 {
243 iterator->destroy(iterator);
244 return algo->algorithm;
245 }
246 }
247 iterator->destroy(iterator);
248 return MODP_UNDEFINED;
249 }
250
251 /**
252 * Implementation of connection_t.check_dh_group.
253 */
254 static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
255 {
256 iterator_t *prop_iter, *alg_iter;
257 proposal_t *proposal;
258 algorithm_t *algo;
259
260 prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
261 while (prop_iter->has_next(prop_iter))
262 {
263 prop_iter->current(prop_iter, (void**)&proposal);
264 alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP);
265 while (alg_iter->has_next(alg_iter))
266 {
267 alg_iter->current(alg_iter, (void**)&algo);
268 if (algo->algorithm == dh_group)
269 {
270 prop_iter->destroy(prop_iter);
271 alg_iter->destroy(alg_iter);
272 return TRUE;
273 }
274 }
275 }
276 prop_iter->destroy(prop_iter);
277 alg_iter->destroy(alg_iter);
278 return FALSE;
279 }
280
281 /**
282 * Implementation of connection_t.clone.
283 */
284 static connection_t *clone(private_connection_t *this)
285 {
286 iterator_t *iterator;
287 proposal_t *proposal;
288 private_connection_t *clone = (private_connection_t*)connection_create(
289 this->name,
290 this->my_host->clone(this->my_host),
291 this->other_host->clone(this->other_host),
292 this->my_id->clone(this->my_id),
293 this->other_id->clone(this->other_id),
294 this->auth_method);
295
296 /* clone all proposals */
297 iterator = this->proposals->create_iterator(this->proposals, TRUE);
298 while (iterator->has_next(iterator))
299 {
300 iterator->current(iterator, (void**)&proposal);
301 proposal = proposal->clone(proposal);
302 clone->proposals->insert_last(clone->proposals, (void*)proposal);
303 }
304 iterator->destroy(iterator);
305
306 return &clone->public;
307 }
308
309 /**
310 * Implementation of connection_t.destroy.
311 */
312 static void destroy (private_connection_t *this)
313 {
314 proposal_t *proposal;
315
316 while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
317 {
318 proposal->destroy(proposal);
319 }
320 this->proposals->destroy(this->proposals);
321
322 this->my_host->destroy(this->my_host);
323 this->other_host->destroy(this->other_host);
324 this->my_id->destroy(this->my_id);
325 this->other_id->destroy(this->other_id);
326 free(this->name);
327 free(this);
328 }
329
330 /**
331 * Described in header.
332 */
333 connection_t * connection_create(char *name, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method)
334 {
335 private_connection_t *this = malloc_thing(private_connection_t);
336
337 /* public functions */
338 this->public.get_name = (char*(*)(connection_t*))get_name;
339 this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id;
340 this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id;
341 this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
342 this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
343 this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
344 this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id;
345 this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id;
346 this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
347 this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
348 this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
349 this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
350 this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
351 this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
352 this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
353 this->public.clone = (connection_t*(*)(connection_t*))clone;
354 this->public.destroy = (void(*)(connection_t*))destroy;
355
356 /* private variables */
357 this->name = strdup(name);
358 this->my_host = my_host;
359 this->other_host = other_host;
360 this->my_id = my_id;
361 this->other_id = other_id;
362 this->auth_method = auth_method;
363
364 this->proposals = linked_list_create();
365
366 return (&this->public);
367 }