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