]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/charon/config/connections/connection.c
ffe508992c8a6d814db815ac9ce40c72949c25b7
[thirdparty/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-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <string.h>
25
26 #include <config/connections/connection.h>
27 #include <utils/linked_list.h>
28
29 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
30 "CERT_ALWAYS_SEND",
31 "CERT_SEND_IF_ASKED",
32 "CERT_NEVER_SEND"
33 );
34
35 typedef struct private_connection_t private_connection_t;
36
37 /**
38 * Private data of an connection_t object
39 */
40 struct private_connection_t {
41
42 /**
43 * Public part
44 */
45 connection_t public;
46
47 /**
48 * Number of references hold by others to this connection
49 */
50 refcount_t refcount;
51
52 /**
53 * Name of the connection
54 */
55 char *name;
56
57 /**
58 * Does charon handle this connection? Or can he ignore it?
59 */
60 bool ikev2;
61
62 /**
63 * should we send a certificate request?
64 */
65 cert_policy_t certreq_policy;
66
67 /**
68 * should we send a certificates?
69 */
70 cert_policy_t cert_policy;
71
72 /**
73 * ID of us
74 */
75 identification_t *my_id;
76
77 /**
78 * Host information of my host.
79 */
80 host_t *my_host;
81
82 /**
83 * Host information of other host.
84 */
85 host_t *other_host;
86
87 /**
88 * Interval to send DPD liveness checks on inactivity
89 */
90 u_int32_t dpd_delay;
91
92 /**
93 * Number of retransmission sequences to send bevore giving up
94 */
95 u_int32_t keyingtries;
96
97 /**
98 * Supported proposals
99 */
100 linked_list_t *proposals;
101
102 /**
103 * Time before an SA gets invalid
104 */
105 u_int32_t soft_lifetime;
106
107 /**
108 * Time before an SA gets rekeyed
109 */
110 u_int32_t hard_lifetime;
111
112 /**
113 * Use full reauthentication instead of rekeying
114 */
115 bool reauth;
116
117 /**
118 * Time, which specifies the range of a random value
119 * substracted from soft_lifetime.
120 */
121 u_int32_t jitter;
122 };
123
124 /**
125 * Implementation of connection_t.get_name.
126 */
127 static char *get_name (private_connection_t *this)
128 {
129 return this->name;
130 }
131
132 /**
133 * Implementation of connection_t.is_ikev2.
134 */
135 static bool is_ikev2 (private_connection_t *this)
136 {
137 return this->ikev2;
138 }
139
140 /**
141 * Implementation of connection_t.get_certreq_policy.
142 */
143 static cert_policy_t get_certreq_policy (private_connection_t *this)
144 {
145 return this->certreq_policy;
146 }
147
148 /**
149 * Implementation of connection_t.get_cert_policy.
150 */
151 static cert_policy_t get_cert_policy (private_connection_t *this)
152 {
153 return this->cert_policy;
154 }
155
156 /**
157 * Implementation of connection_t.get_my_host.
158 */
159 static host_t *get_my_host (private_connection_t *this)
160 {
161 return this->my_host;
162 }
163
164 /**
165 * Implementation of connection_t.get_other_host.
166 */
167 static host_t *get_other_host (private_connection_t *this)
168 {
169 return this->other_host;
170 }
171
172 /**
173 * Implementation of connection_t.get_proposals.
174 */
175 static linked_list_t* get_proposals(private_connection_t *this)
176 {
177 iterator_t *iterator;
178 proposal_t *current;
179 linked_list_t *proposals = linked_list_create();
180
181 iterator = this->proposals->create_iterator(this->proposals, TRUE);
182 while (iterator->iterate(iterator, (void**)&current))
183 {
184 current = current->clone(current);
185 proposals->insert_last(proposals, (void*)current);
186 }
187 iterator->destroy(iterator);
188
189 return proposals;
190 }
191
192 /**
193 * Implementation of connection_t.select_proposal.
194 */
195 static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
196 {
197 iterator_t *stored_iter, *supplied_iter;
198 proposal_t *stored, *supplied, *selected;
199
200 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
201 supplied_iter = proposals->create_iterator(proposals, TRUE);
202
203 /* compare all stored proposals with all supplied. Stored ones are preferred. */
204 while (stored_iter->iterate(stored_iter, (void**)&stored))
205 {
206 supplied_iter->reset(supplied_iter);
207
208 while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
209 {
210 selected = stored->select(stored, supplied);
211 if (selected)
212 {
213 /* they match, return */
214 stored_iter->destroy(stored_iter);
215 supplied_iter->destroy(supplied_iter);
216 return selected;
217 }
218 }
219 }
220 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
221 stored_iter->destroy(stored_iter);
222 supplied_iter->destroy(supplied_iter);
223
224 return NULL;
225 }
226
227 /**
228 * Implementation of connection_t.add_proposal.
229 */
230 static void add_proposal(private_connection_t *this, proposal_t *proposal)
231 {
232 this->proposals->insert_last(this->proposals, proposal);
233 }
234
235 /**
236 * Implementation of connection_t.get_dpd_delay.
237 */
238 static u_int32_t get_dpd_delay(private_connection_t *this)
239 {
240 return this->dpd_delay;
241 }
242
243 /**
244 * Implementation of connection_t.get_keyingtries.
245 */
246 static u_int32_t get_keyingtries(private_connection_t *this)
247 {
248 return this->keyingtries;
249 }
250
251 /**
252 * Implementation of connection_t.get_dh_group.
253 */
254 static diffie_hellman_group_t get_dh_group(private_connection_t *this)
255 {
256 iterator_t *iterator;
257 proposal_t *proposal;
258 algorithm_t *algo;
259 diffie_hellman_group_t dh_group = MODP_NONE;
260
261 iterator = this->proposals->create_iterator(this->proposals, TRUE);
262 while (iterator->iterate(iterator, (void**)&proposal))
263 {
264 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
265 {
266 dh_group = algo->algorithm;
267 break;
268 }
269 }
270 iterator->destroy(iterator);
271 return dh_group;
272 }
273
274 /**
275 * Implementation of connection_t.check_dh_group.
276 */
277 static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
278 {
279 iterator_t *prop_iter, *alg_iter;
280 proposal_t *proposal;
281 algorithm_t *algo;
282
283 prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
284 while (prop_iter->iterate(prop_iter, (void**)&proposal))
285 {
286 alg_iter = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP);
287 while (alg_iter->iterate(alg_iter, (void**)&algo))
288 {
289 if (algo->algorithm == dh_group)
290 {
291 prop_iter->destroy(prop_iter);
292 alg_iter->destroy(alg_iter);
293 return TRUE;
294 }
295 }
296 alg_iter->destroy(alg_iter);
297 }
298 prop_iter->destroy(prop_iter);
299 return FALSE;
300 }
301 /**
302 * Implementation of connection_t.get_soft_lifetime
303 */
304 static u_int32_t get_soft_lifetime(private_connection_t *this)
305 {
306 if (this->jitter == 0)
307 {
308 return this->soft_lifetime ;
309 }
310 return this->soft_lifetime - (random() % this->jitter);
311 }
312
313 /**
314 * Implementation of connection_t.get_hard_lifetime.
315 */
316 static u_int32_t get_hard_lifetime(private_connection_t *this)
317 {
318 return this->hard_lifetime;
319 }
320
321 /**
322 * Implementation of connection_t.get_reauth.
323 */
324 static bool get_reauth(private_connection_t *this)
325 {
326 return this->reauth;
327 }
328
329 /**
330 * Implementation of connection_t.get_ref.
331 */
332 static void get_ref(private_connection_t *this)
333 {
334 ref_get(&this->refcount);
335 }
336
337 /**
338 * Implementation of connection_t.destroy.
339 */
340 static void destroy(private_connection_t *this)
341 {
342 if (ref_put(&this->refcount))
343 {
344 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
345 this->my_host->destroy(this->my_host);
346 this->other_host->destroy(this->other_host);
347 free(this->name);
348 free(this);
349 }
350 }
351
352 /**
353 * Described in header.
354 */
355 connection_t * connection_create(char *name, bool ikev2,
356 cert_policy_t cert_policy,
357 cert_policy_t certreq_policy,
358 host_t *my_host, host_t *other_host,
359 u_int32_t dpd_delay, bool reauth,
360 u_int32_t keyingtries,
361 u_int32_t hard_lifetime,
362 u_int32_t soft_lifetime, u_int32_t jitter)
363 {
364 private_connection_t *this = malloc_thing(private_connection_t);
365
366 /* public functions */
367 this->public.get_name = (char*(*)(connection_t*))get_name;
368 this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
369 this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy;
370 this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy;
371 this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
372 this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
373 this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
374 this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
375 this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
376 this->public.get_dpd_delay = (u_int32_t(*)(connection_t*)) get_dpd_delay;
377 this->public.get_reauth = (bool(*)(connection_t*)) get_reauth;
378 this->public.get_keyingtries = (u_int32_t(*)(connection_t*)) get_keyingtries;
379 this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
380 this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
381 this->public.get_soft_lifetime = (u_int32_t (*) (connection_t *))get_soft_lifetime;
382 this->public.get_hard_lifetime = (u_int32_t (*) (connection_t *))get_hard_lifetime;
383 this->public.get_ref = (void(*)(connection_t*))get_ref;
384 this->public.destroy = (void(*)(connection_t*))destroy;
385
386 /* private variables */
387 this->refcount = 1;
388 this->name = strdup(name);
389 this->ikev2 = ikev2;
390 this->cert_policy = cert_policy;
391 this->certreq_policy = certreq_policy;
392 this->my_host = my_host;
393 this->other_host = other_host;
394 this->dpd_delay = dpd_delay;
395 this->reauth = reauth;
396 this->keyingtries = keyingtries;
397 this->hard_lifetime = hard_lifetime;
398 this->soft_lifetime = soft_lifetime;
399 this->jitter = jitter;
400
401 this->proposals = linked_list_create();
402
403 return &this->public;
404 }