2ce544cc9b02cd088eaa84ed58610df5e46b2619
[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.get_my_host.
115 */
116 static host_t * get_my_host (private_connection_t *this)
117 {
118 return this->my_host;
119 }
120
121 /**
122 * Implementation of connection_t.update_my_host.
123 */
124 static void update_my_host(private_connection_t *this, host_t *my_host)
125 {
126 this->my_host->destroy(this->my_host);
127 this->my_host = my_host;
128 }
129
130 /**
131 * Implementation of connection_t.update_other_host.
132 */
133 static void update_other_host(private_connection_t *this, host_t *other_host)
134 {
135 this->other_host->destroy(this->other_host);
136 this->other_host = other_host;
137 }
138
139 /**
140 * Implementation of connection_t.get_other_host.
141 */
142 static host_t * get_other_host (private_connection_t *this)
143 {
144 return this->other_host;
145 }
146
147 /**
148 * Implementation of connection_t.get_proposals.
149 */
150 static linked_list_t* get_proposals (private_connection_t *this)
151 {
152 return this->proposals;
153 }
154
155 /**
156 * Implementation of connection_t.select_proposal.
157 */
158 static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
159 {
160 iterator_t *stored_iter, *supplied_iter;
161 proposal_t *stored, *supplied, *selected;
162
163 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
164 supplied_iter = proposals->create_iterator(proposals, TRUE);
165
166 /* compare all stored proposals with all supplied. Stored ones are preferred. */
167 while (stored_iter->has_next(stored_iter))
168 {
169 supplied_iter->reset(supplied_iter);
170 stored_iter->current(stored_iter, (void**)&stored);
171
172 while (supplied_iter->has_next(supplied_iter))
173 {
174 supplied_iter->current(supplied_iter, (void**)&supplied);
175 selected = stored->select(stored, supplied);
176 if (selected)
177 {
178 /* they match, return */
179 stored_iter->destroy(stored_iter);
180 supplied_iter->destroy(supplied_iter);
181 return selected;
182 }
183 }
184 }
185
186 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
187 stored_iter->destroy(stored_iter);
188 supplied_iter->destroy(supplied_iter);
189
190 return NULL;
191 }
192
193 /**
194 * Implementation of connection_t.add_proposal.
195 */
196 static void add_proposal (private_connection_t *this, proposal_t *proposal)
197 {
198 this->proposals->insert_last(this->proposals, proposal);
199 }
200
201 /**
202 * Implementation of connection_t.auth_method_t.
203 */
204 static auth_method_t get_auth_method(private_connection_t *this)
205 {
206 return this->auth_method;
207 }
208
209 /**
210 * Implementation of connection_t.get_dh_group.
211 */
212 static diffie_hellman_group_t get_dh_group(private_connection_t *this)
213 {
214 iterator_t *iterator;
215 proposal_t *proposal;
216 algorithm_t *algo;
217
218 iterator = this->proposals->create_iterator(this->proposals, TRUE);
219 while (iterator->has_next(iterator))
220 {
221 iterator->current(iterator, (void**)&proposal);
222 proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo);
223 if (algo)
224 {
225 iterator->destroy(iterator);
226 return algo->algorithm;
227 }
228 }
229 iterator->destroy(iterator);
230 return MODP_UNDEFINED;
231 }
232
233 /**
234 * Implementation of connection_t.check_dh_group.
235 */
236 static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
237 {
238 iterator_t *prop_iter, *alg_iter;
239 proposal_t *proposal;
240 algorithm_t *algo;
241
242 prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
243 while (prop_iter->has_next(prop_iter))
244 {
245 prop_iter->current(prop_iter, (void**)&proposal);
246 alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP);
247 while (alg_iter->has_next(alg_iter))
248 {
249 alg_iter->current(alg_iter, (void**)&algo);
250 if (algo->algorithm == dh_group)
251 {
252 prop_iter->destroy(prop_iter);
253 alg_iter->destroy(alg_iter);
254 return TRUE;
255 }
256 }
257 }
258 prop_iter->destroy(prop_iter);
259 alg_iter->destroy(alg_iter);
260 return FALSE;
261 }
262
263 /**
264 * Implementation of connection_t.clone.
265 */
266 static connection_t *clone(private_connection_t *this)
267 {
268 iterator_t *iterator;
269 proposal_t *proposal;
270 private_connection_t *clone = (private_connection_t*)connection_create(
271 this->name,
272 this->my_host->clone(this->my_host),
273 this->other_host->clone(this->other_host),
274 this->my_id->clone(this->my_id),
275 this->other_id->clone(this->other_id),
276 this->auth_method);
277
278 /* clone all proposals */
279 iterator = this->proposals->create_iterator(this->proposals, TRUE);
280 while (iterator->has_next(iterator))
281 {
282 iterator->current(iterator, (void**)&proposal);
283 proposal = proposal->clone(proposal);
284 clone->proposals->insert_last(clone->proposals, (void*)proposal);
285 }
286 iterator->destroy(iterator);
287
288 return &clone->public;
289 }
290
291 /**
292 * Implementation of connection_t.destroy.
293 */
294 static void destroy (private_connection_t *this)
295 {
296 proposal_t *proposal;
297
298 while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
299 {
300 proposal->destroy(proposal);
301 }
302 this->proposals->destroy(this->proposals);
303
304 this->my_host->destroy(this->my_host);
305 this->other_host->destroy(this->other_host);
306 this->my_id->destroy(this->my_id);
307 this->other_id->destroy(this->other_id);
308 free(this);
309 }
310
311 /**
312 * Described in header.
313 */
314 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)
315 {
316 private_connection_t *this = malloc_thing(private_connection_t);
317
318 /* public functions */
319 this->public.get_name = (char*(*)(connection_t*))get_name;
320 this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id;
321 this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id;
322 this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
323 this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
324 this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
325 this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
326 this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
327 this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
328 this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
329 this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
330 this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
331 this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
332 this->public.clone = (connection_t*(*)(connection_t*))clone;
333 this->public.destroy = (void(*)(connection_t*))destroy;
334
335 /* private variables */
336 this->name = strdup(name);
337 this->my_host = my_host;
338 this->other_host = other_host;
339 this->my_id = my_id;
340 this->other_id = other_id;
341 this->auth_method = auth_method;
342
343 this->proposals = linked_list_create();
344
345 return (&this->public);
346 }