]>
Commit | Line | Data |
---|---|---|
7ba38761 JH |
1 | /** |
2 | * @file ike_sa.c | |
79538669 | 3 | * |
df3c59d0 | 4 | * @brief Implementation of ike_sa_t. |
79538669 | 5 | * |
7ba38761 JH |
6 | */ |
7 | ||
8 | /* | |
1396815a | 9 | * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger |
c71d53ba MW |
10 | * Copyright (C) 2005-2006 Martin Willi |
11 | * Copyright (C) 2005 Jan Hutter | |
7ba38761 JH |
12 | * Hochschule fuer Technik Rapperswil |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify it | |
15 | * under the terms of the GNU General Public License as published by the | |
16 | * Free Software Foundation; either version 2 of the License, or (at your | |
17 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, but | |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
22 | * for more details. | |
23 | */ | |
1396815a MW |
24 | |
25 | #include <sys/time.h> | |
5113680f | 26 | #include <string.h> |
60356f33 | 27 | #include <printf.h> |
c60c7694 | 28 | #include <sys/stat.h> |
7ba38761 | 29 | |
88878242 MW |
30 | #include "ike_sa.h" |
31 | ||
db7ef624 | 32 | #include <library.h> |
0e96f7d8 | 33 | #include <daemon.h> |
021c2322 | 34 | #include <utils/linked_list.h> |
c60c7694 | 35 | #include <utils/lexparser.h> |
68621281 MW |
36 | #include <crypto/diffie_hellman.h> |
37 | #include <crypto/prf_plus.h> | |
38 | #include <crypto/crypters/crypter.h> | |
1396815a | 39 | #include <crypto/hashers/hasher.h> |
4a962238 MW |
40 | #include <encoding/payloads/sa_payload.h> |
41 | #include <encoding/payloads/nonce_payload.h> | |
42 | #include <encoding/payloads/ke_payload.h> | |
e9c0ca15 | 43 | #include <encoding/payloads/delete_payload.h> |
4a962238 MW |
44 | #include <encoding/payloads/transform_substructure.h> |
45 | #include <encoding/payloads/transform_attribute.h> | |
8d77edde | 46 | #include <encoding/payloads/ts_payload.h> |
c60c7694 MW |
47 | #include <sa/task_manager.h> |
48 | #include <sa/tasks/ike_init.h> | |
49 | #include <sa/tasks/ike_natd.h> | |
50 | #include <sa/tasks/ike_auth.h> | |
51 | #include <sa/tasks/ike_config.h> | |
52 | #include <sa/tasks/ike_cert.h> | |
53 | #include <sa/tasks/ike_rekey.h> | |
54 | #include <sa/tasks/ike_delete.h> | |
55 | #include <sa/tasks/ike_dpd.h> | |
56 | #include <sa/tasks/child_create.h> | |
57 | #include <sa/tasks/child_delete.h> | |
58 | #include <sa/tasks/child_rekey.h> | |
e0fe7651 MW |
59 | #include <processing/jobs/retransmit_job.h> |
60 | #include <processing/jobs/delete_ike_sa_job.h> | |
61 | #include <processing/jobs/send_dpd_job.h> | |
62 | #include <processing/jobs/send_keepalive_job.h> | |
63 | #include <processing/jobs/rekey_ike_sa_job.h> | |
64 | #include <processing/jobs/route_job.h> | |
65 | #include <processing/jobs/initiate_job.h> | |
7ba38761 | 66 | |
c60c7694 MW |
67 | |
68 | #ifndef RESOLV_CONF | |
69 | #define RESOLV_CONF "/etc/resolv.conf" | |
70 | #endif | |
71 | ||
60356f33 MW |
72 | ENUM(ike_sa_state_names, IKE_CREATED, IKE_DELETING, |
73 | "CREATED", | |
74 | "CONNECTING", | |
75 | "ESTABLISHED", | |
76 | "REKEYING", | |
77 | "DELETING", | |
78 | ); | |
7ba38761 | 79 | |
aad398a7 JH |
80 | typedef struct private_ike_sa_t private_ike_sa_t; |
81 | ||
82 | /** | |
83 | * Private data of an ike_sa_t object. | |
84 | */ | |
85 | struct private_ike_sa_t { | |
86 | ||
87 | /** | |
3dd3c5f3 | 88 | * Public members |
2f89902d | 89 | */ |
3dd3c5f3 | 90 | ike_sa_t public; |
2f89902d | 91 | |
aad398a7 | 92 | /** |
a374d1ee | 93 | * Identifier for the current IKE_SA. |
aad398a7 JH |
94 | */ |
95 | ike_sa_id_t *ike_sa_id; | |
8d77edde | 96 | |
c60c7694 MW |
97 | /** |
98 | * unique numerical ID for this IKE_SA. | |
99 | */ | |
100 | u_int32_t unique_id; | |
101 | ||
aad398a7 | 102 | /** |
8dfbe71b | 103 | * Current state of the IKE_SA |
aad398a7 | 104 | */ |
c60c7694 | 105 | ike_sa_state_t state; |
a9428251 JH |
106 | |
107 | /** | |
e0fe7651 | 108 | * IKE configuration used to set up this IKE_SA |
a9428251 | 109 | */ |
e0fe7651 | 110 | ike_cfg_t *ike_cfg; |
c60c7694 MW |
111 | |
112 | /** | |
113 | * Peer and authentication information to establish IKE_SA. | |
114 | */ | |
e0fe7651 | 115 | peer_cfg_t *peer_cfg; |
c60c7694 MW |
116 | |
117 | /** | |
118 | * Juggles tasks to process messages | |
119 | */ | |
120 | task_manager_t *task_manager; | |
8dfbe71b MW |
121 | |
122 | /** | |
123 | * Address of local host | |
124 | */ | |
125 | host_t *my_host; | |
126 | ||
127 | /** | |
128 | * Address of remote host | |
129 | */ | |
130 | host_t *other_host; | |
131 | ||
132 | /** | |
133 | * Identification used for us | |
134 | */ | |
135 | identification_t *my_id; | |
a9428251 JH |
136 | |
137 | /** | |
8dfbe71b | 138 | * Identification used for other |
a9428251 | 139 | */ |
8dfbe71b | 140 | identification_t *other_id; |
a374d1ee | 141 | |
aad398a7 | 142 | /** |
8dfbe71b | 143 | * Linked List containing the child sa's of the current IKE_SA. |
aad398a7 | 144 | */ |
8dfbe71b | 145 | linked_list_t *child_sas; |
aad398a7 JH |
146 | |
147 | /** | |
3dd3c5f3 | 148 | * crypter for inbound traffic |
aad398a7 | 149 | */ |
3dd3c5f3 | 150 | crypter_t *crypter_in; |
aad398a7 JH |
151 | |
152 | /** | |
3dd3c5f3 | 153 | * crypter for outbound traffic |
aad398a7 | 154 | */ |
3dd3c5f3 | 155 | crypter_t *crypter_out; |
aad398a7 JH |
156 | |
157 | /** | |
3dd3c5f3 | 158 | * Signer for inbound traffic |
aad398a7 | 159 | */ |
3dd3c5f3 | 160 | signer_t *signer_in; |
aad398a7 JH |
161 | |
162 | /** | |
3dd3c5f3 | 163 | * Signer for outbound traffic |
aad398a7 | 164 | */ |
3dd3c5f3 | 165 | signer_t *signer_out; |
aad398a7 JH |
166 | |
167 | /** | |
ce461bbd | 168 | * Multi purpose prf, set key, use it, forget it |
aad398a7 JH |
169 | */ |
170 | prf_t *prf; | |
171 | ||
5b97779f MW |
172 | /** |
173 | * Prf function for derivating keymat child SAs | |
5b97779f MW |
174 | */ |
175 | prf_t *child_prf; | |
176 | ||
aad398a7 | 177 | /** |
382b4817 | 178 | * PRF to build outging authentication data |
aad398a7 | 179 | */ |
382b4817 | 180 | prf_t *auth_build; |
aad398a7 | 181 | |
ce461bbd | 182 | /** |
382b4817 | 183 | * PRF to verify incoming authentication data |
ce461bbd | 184 | */ |
382b4817 | 185 | prf_t *auth_verify; |
0df63d6b | 186 | |
1396815a MW |
187 | /** |
188 | * NAT status of local host. | |
189 | */ | |
190 | bool nat_here; | |
191 | ||
192 | /** | |
193 | * NAT status of remote host. | |
194 | */ | |
195 | bool nat_there; | |
3dd3c5f3 MW |
196 | |
197 | /** | |
c60c7694 | 198 | * Virtual IP on local host, if any |
3dd3c5f3 | 199 | */ |
c60c7694 MW |
200 | host_t *my_virtual_ip; |
201 | ||
202 | /** | |
203 | * Virtual IP on remote host, if any | |
204 | */ | |
205 | host_t *other_virtual_ip; | |
206 | ||
31e5d441 | 207 | /** |
c60c7694 | 208 | * List of DNS servers installed by us |
31e5d441 | 209 | */ |
c60c7694 | 210 | linked_list_t *dns_servers; |
31e5d441 | 211 | |
1396815a | 212 | /** |
fe04e93a | 213 | * Timestamps for this IKE_SA |
1396815a | 214 | */ |
fe04e93a MW |
215 | struct { |
216 | /** last IKE message received */ | |
217 | u_int32_t inbound; | |
218 | /** last IKE message sent */ | |
219 | u_int32_t outbound; | |
220 | /** when IKE_SA became established */ | |
221 | u_int32_t established; | |
222 | /** when IKE_SA gets rekeyed */ | |
223 | u_int32_t rekey; | |
224 | /** when IKE_SA gets deleted */ | |
225 | u_int32_t delete; | |
226 | } time; | |
fdb9b2bd MW |
227 | |
228 | /** | |
229 | * how many times we have retried so far (keyingtries) | |
230 | */ | |
231 | u_int32_t keyingtry; | |
aad398a7 JH |
232 | }; |
233 | ||
0b2abb8c | 234 | /** |
3dd3c5f3 | 235 | * get the time of the latest traffic processed by the kernel |
0b2abb8c | 236 | */ |
c60c7694 | 237 | static time_t get_use_time(private_ike_sa_t* this, bool inbound) |
3a8f9f44 | 238 | { |
3dd3c5f3 MW |
239 | iterator_t *iterator; |
240 | child_sa_t *child_sa; | |
241 | time_t latest = 0, use_time; | |
16b9a73c | 242 | |
3dd3c5f3 MW |
243 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); |
244 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
245 | { | |
246 | if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS) | |
247 | { | |
248 | latest = max(latest, use_time); | |
249 | } | |
250 | } | |
251 | iterator->destroy(iterator); | |
5534ee84 | 252 | |
c60c7694 MW |
253 | if (inbound) |
254 | { | |
255 | return max(this->time.inbound, latest); | |
256 | } | |
257 | else | |
258 | { | |
259 | return max(this->time.outbound, latest); | |
260 | } | |
a9428251 JH |
261 | } |
262 | ||
aad398a7 | 263 | /** |
c60c7694 | 264 | * Implementation of ike_sa_t.get_unique_id |
aad398a7 | 265 | */ |
c60c7694 | 266 | static u_int32_t get_unique_id(private_ike_sa_t *this) |
aad398a7 | 267 | { |
c60c7694 | 268 | return this->unique_id; |
aad398a7 JH |
269 | } |
270 | ||
0fdc3c7f | 271 | /** |
c60c7694 | 272 | * Implementation of ike_sa_t.get_name. |
0fdc3c7f | 273 | */ |
c60c7694 | 274 | static char *get_name(private_ike_sa_t *this) |
0fdc3c7f | 275 | { |
e0fe7651 | 276 | if (this->peer_cfg) |
c60c7694 | 277 | { |
e0fe7651 | 278 | return this->peer_cfg->get_name(this->peer_cfg); |
c60c7694 MW |
279 | } |
280 | return "(unnamed)"; | |
0fdc3c7f JH |
281 | } |
282 | ||
8dfbe71b | 283 | /** |
e0fe7651 | 284 | * Implementation of ike_sa_t.get_my_host. |
8dfbe71b | 285 | */ |
e0fe7651 | 286 | static host_t *get_my_host(private_ike_sa_t *this) |
8dfbe71b | 287 | { |
e0fe7651 | 288 | return this->my_host; |
8dfbe71b MW |
289 | } |
290 | ||
291 | /** | |
e0fe7651 | 292 | * Implementation of ike_sa_t.set_my_host. |
8dfbe71b | 293 | */ |
e0fe7651 | 294 | static void set_my_host(private_ike_sa_t *this, host_t *me) |
8dfbe71b | 295 | { |
e0fe7651 MW |
296 | DESTROY_IF(this->my_host); |
297 | this->my_host = me; | |
8dfbe71b MW |
298 | } |
299 | ||
397f3448 | 300 | /** |
e0fe7651 | 301 | * Implementation of ike_sa_t.get_other_host. |
397f3448 | 302 | */ |
e0fe7651 | 303 | static host_t *get_other_host(private_ike_sa_t *this) |
397f3448 | 304 | { |
e0fe7651 | 305 | return this->other_host; |
c60c7694 MW |
306 | } |
307 | ||
308 | /** | |
e0fe7651 | 309 | * Implementation of ike_sa_t.set_other_host. |
c60c7694 | 310 | */ |
e0fe7651 | 311 | static void set_other_host(private_ike_sa_t *this, host_t *other) |
c60c7694 | 312 | { |
e0fe7651 MW |
313 | DESTROY_IF(this->other_host); |
314 | this->other_host = other; | |
397f3448 MW |
315 | } |
316 | ||
8dfbe71b | 317 | /** |
e0fe7651 | 318 | * Implementation of ike_sa_t.get_peer_cfg |
8dfbe71b | 319 | */ |
e0fe7651 | 320 | static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this) |
8dfbe71b | 321 | { |
e0fe7651 | 322 | return this->peer_cfg; |
8dfbe71b MW |
323 | } |
324 | ||
fe04e93a | 325 | /** |
e0fe7651 | 326 | * Implementation of ike_sa_t.set_peer_cfg |
fe04e93a | 327 | */ |
e0fe7651 | 328 | static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) |
fe04e93a | 329 | { |
e0fe7651 MW |
330 | host_t *me, *other; |
331 | identification_t *my_id, *other_id; | |
332 | ||
333 | peer_cfg->get_ref(peer_cfg); | |
334 | this->peer_cfg = peer_cfg; | |
335 | if (this->ike_cfg == NULL) | |
336 | { | |
337 | this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); | |
338 | this->ike_cfg->get_ref(this->ike_cfg); | |
339 | } | |
340 | ||
341 | /* apply values, so we are ready to initate/acquire */ | |
342 | if (this->my_host->is_anyaddr(this->my_host)) | |
343 | { | |
344 | me = this->ike_cfg->get_my_host(this->ike_cfg); | |
345 | set_my_host(this, me->clone(me)); | |
346 | } | |
347 | if (this->other_host->is_anyaddr(this->other_host)) | |
348 | { | |
349 | other = this->ike_cfg->get_other_host(this->ike_cfg); | |
350 | set_other_host(this, other->clone(other)); | |
351 | } | |
352 | my_id = this->peer_cfg->get_my_id(this->peer_cfg); | |
353 | other_id = this->peer_cfg->get_other_id(this->peer_cfg); | |
354 | DESTROY_IF(this->my_id); | |
355 | DESTROY_IF(this->other_id); | |
356 | this->my_id = my_id->clone(my_id); | |
357 | this->other_id = other_id->clone(other_id); | |
fe04e93a MW |
358 | } |
359 | ||
8dfbe71b | 360 | /** |
e0fe7651 | 361 | * Implementation of ike_sa_t.get_ike_cfg |
8dfbe71b | 362 | */ |
e0fe7651 | 363 | static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this) |
8dfbe71b | 364 | { |
e0fe7651 | 365 | return this->ike_cfg; |
8dfbe71b | 366 | } |
5b97779f | 367 | |
fe04e93a | 368 | /** |
e0fe7651 | 369 | * Implementation of ike_sa_t.set_ike_cfg |
fe04e93a | 370 | */ |
e0fe7651 | 371 | static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg) |
fe04e93a | 372 | { |
e0fe7651 MW |
373 | ike_cfg->get_ref(ike_cfg); |
374 | this->ike_cfg = ike_cfg; | |
fe04e93a MW |
375 | } |
376 | ||
fdb9b2bd MW |
377 | /** |
378 | * Implementation of ike_sa_t.send_dpd | |
379 | */ | |
380 | static status_t send_dpd(private_ike_sa_t *this) | |
381 | { | |
382 | send_dpd_job_t *job; | |
383 | time_t diff, delay; | |
384 | ||
e0fe7651 | 385 | delay = this->peer_cfg->get_dpd_delay(this->peer_cfg); |
fdb9b2bd MW |
386 | |
387 | if (delay == 0) | |
388 | { | |
389 | /* DPD disabled */ | |
390 | return SUCCESS; | |
391 | } | |
392 | ||
393 | if (this->task_manager->busy(this->task_manager)) | |
394 | { | |
395 | /* an exchange is in the air, no need to start a DPD check */ | |
396 | diff = 0; | |
397 | } | |
398 | else | |
399 | { | |
400 | /* check if there was any inbound traffic */ | |
401 | time_t last_in, now; | |
402 | last_in = get_use_time(this, TRUE); | |
403 | now = time(NULL); | |
404 | diff = now - last_in; | |
405 | if (diff >= delay) | |
406 | { | |
407 | /* to long ago, initiate dead peer detection */ | |
408 | task_t *task; | |
409 | ||
410 | task = (task_t*)ike_dpd_create(TRUE); | |
411 | diff = 0; | |
412 | DBG1(DBG_IKE, "sending DPD request"); | |
413 | ||
414 | this->task_manager->queue_task(this->task_manager, task); | |
415 | this->task_manager->initiate(this->task_manager); | |
416 | } | |
417 | } | |
418 | /* recheck in "interval" seconds */ | |
419 | job = send_dpd_job_create(this->ike_sa_id); | |
420 | charon->event_queue->add_relative(charon->event_queue, (job_t*)job, | |
421 | (delay - diff) * 1000); | |
422 | return SUCCESS; | |
423 | } | |
424 | ||
425 | /** | |
426 | * Implementation of ike_sa_t.send_keepalive | |
427 | */ | |
428 | static void send_keepalive(private_ike_sa_t *this) | |
429 | { | |
430 | send_keepalive_job_t *job; | |
431 | time_t last_out, now, diff, interval; | |
432 | ||
433 | last_out = get_use_time(this, FALSE); | |
434 | now = time(NULL); | |
435 | ||
436 | diff = now - last_out; | |
437 | interval = charon->configuration->get_keepalive_interval(charon->configuration); | |
438 | ||
439 | if (diff >= interval) | |
440 | { | |
441 | packet_t *packet; | |
442 | chunk_t data; | |
443 | ||
444 | packet = packet_create(); | |
445 | packet->set_source(packet, this->my_host->clone(this->my_host)); | |
446 | packet->set_destination(packet, this->other_host->clone(this->other_host)); | |
447 | data.ptr = malloc(1); | |
448 | data.ptr[0] = 0xFF; | |
449 | data.len = 1; | |
450 | packet->set_data(packet, data); | |
4deb8948 | 451 | charon->sender->send(charon->sender, packet); |
fdb9b2bd MW |
452 | DBG1(DBG_IKE, "sending keep alive"); |
453 | diff = 0; | |
454 | } | |
455 | job = send_keepalive_job_create(this->ike_sa_id); | |
456 | charon->event_queue->add_relative(charon->event_queue, (job_t*)job, | |
457 | (interval - diff) * 1000); | |
458 | } | |
459 | ||
460 | /** | |
461 | * Implementation of ike_sa_t.get_state. | |
462 | */ | |
463 | static ike_sa_state_t get_state(private_ike_sa_t *this) | |
464 | { | |
465 | return this->state; | |
466 | } | |
467 | ||
468 | /** | |
469 | * Implementation of ike_sa_t.set_state. | |
470 | */ | |
471 | static void set_state(private_ike_sa_t *this, ike_sa_state_t state) | |
472 | { | |
473 | DBG1(DBG_IKE, "IKE_SA state change: %N => %N", | |
474 | ike_sa_state_names, this->state, | |
475 | ike_sa_state_names, state); | |
476 | ||
0f33e826 | 477 | switch (state) |
fdb9b2bd | 478 | { |
0f33e826 | 479 | case IKE_ESTABLISHED: |
fdb9b2bd | 480 | { |
0f33e826 MW |
481 | if (this->state == IKE_CONNECTING) |
482 | { | |
483 | job_t *job; | |
484 | u_int32_t now = time(NULL); | |
485 | u_int32_t soft, hard; | |
486 | bool reauth; | |
487 | ||
488 | this->time.established = now; | |
489 | /* start DPD checks */ | |
490 | send_dpd(this); | |
491 | ||
492 | /* schedule rekeying/reauthentication */ | |
e0fe7651 MW |
493 | soft = this->peer_cfg->get_lifetime(this->peer_cfg, TRUE); |
494 | hard = this->peer_cfg->get_lifetime(this->peer_cfg, FALSE); | |
495 | reauth = this->peer_cfg->use_reauth(this->peer_cfg); | |
0f33e826 MW |
496 | DBG1(DBG_IKE, "scheduling %s in %ds, maximum lifetime %ds", |
497 | reauth ? "reauthentication": "rekeying", soft, hard); | |
498 | ||
499 | if (soft) | |
500 | { | |
501 | this->time.rekey = now + soft; | |
502 | job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, reauth); | |
503 | charon->event_queue->add_relative(charon->event_queue, job, | |
504 | soft * 1000); | |
505 | } | |
506 | ||
507 | if (hard) | |
508 | { | |
509 | this->time.delete = now + hard; | |
510 | job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE); | |
511 | charon->event_queue->add_relative(charon->event_queue, job, | |
512 | hard * 1000); | |
513 | } | |
514 | } | |
515 | break; | |
fdb9b2bd | 516 | } |
0f33e826 | 517 | case IKE_DELETING: |
fdb9b2bd | 518 | { |
0f33e826 MW |
519 | /* delete may fail if a packet gets lost, so set a timeout */ |
520 | job_t *job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE); | |
fdb9b2bd | 521 | charon->event_queue->add_relative(charon->event_queue, job, |
0f33e826 MW |
522 | charon->configuration->get_half_open_ike_sa_timeout( |
523 | charon->configuration)); | |
524 | break; | |
fdb9b2bd | 525 | } |
0f33e826 MW |
526 | default: |
527 | break; | |
fdb9b2bd MW |
528 | } |
529 | ||
530 | this->state = state; | |
531 | } | |
532 | ||
533 | /** | |
534 | * Implementation of ike_sa_t.reset | |
535 | */ | |
536 | static void reset(private_ike_sa_t *this) | |
537 | { | |
538 | /* the responder ID is reset, as peer may choose another one */ | |
539 | if (this->ike_sa_id->is_initiator(this->ike_sa_id)) | |
540 | { | |
541 | this->ike_sa_id->set_responder_spi(this->ike_sa_id, 0); | |
542 | } | |
543 | ||
544 | set_state(this, IKE_CREATED); | |
545 | ||
546 | this->task_manager->reset(this->task_manager); | |
547 | } | |
548 | ||
0fdc3c7f | 549 | /** |
e0fe7651 | 550 | * Update hosts, as addresses may change (NAT) |
0fdc3c7f | 551 | */ |
3dd3c5f3 | 552 | static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) |
0fdc3c7f | 553 | { |
3dd3c5f3 MW |
554 | iterator_t *iterator = NULL; |
555 | child_sa_t *child_sa = NULL; | |
8dfbe71b MW |
556 | host_diff_t my_diff, other_diff; |
557 | ||
45f76a7d MW |
558 | if (this->my_host->is_anyaddr(this->my_host) || |
559 | this->other_host->is_anyaddr(this->other_host)) | |
8dfbe71b MW |
560 | { |
561 | /* on first received message */ | |
45f76a7d | 562 | this->my_host->destroy(this->my_host); |
8dfbe71b | 563 | this->my_host = me->clone(me); |
45f76a7d | 564 | this->other_host->destroy(this->other_host); |
8dfbe71b MW |
565 | this->other_host = other->clone(other); |
566 | return; | |
567 | } | |
568 | ||
569 | my_diff = me->get_differences(me, this->my_host); | |
570 | other_diff = other->get_differences(other, this->other_host); | |
571 | ||
572 | if (!my_diff && !other_diff) | |
3dd3c5f3 MW |
573 | { |
574 | return; | |
575 | } | |
576 | ||
8dfbe71b | 577 | if (my_diff) |
3dd3c5f3 | 578 | { |
8dfbe71b MW |
579 | this->my_host->destroy(this->my_host); |
580 | this->my_host = me->clone(me); | |
3dd3c5f3 MW |
581 | } |
582 | ||
583 | if (!this->nat_here) | |
584 | { | |
585 | /* update without restrictions if we are not NATted */ | |
8dfbe71b | 586 | if (other_diff) |
3dd3c5f3 | 587 | { |
8dfbe71b MW |
588 | this->other_host->destroy(this->other_host); |
589 | this->other_host = other->clone(other); | |
3dd3c5f3 MW |
590 | } |
591 | } | |
592 | else | |
593 | { | |
594 | /* if we are natted, only port may change */ | |
8dfbe71b | 595 | if (other_diff & HOST_DIFF_ADDR) |
3dd3c5f3 MW |
596 | { |
597 | return; | |
598 | } | |
8dfbe71b | 599 | else if (other_diff & HOST_DIFF_PORT) |
3dd3c5f3 | 600 | { |
8dfbe71b | 601 | this->other_host->set_port(this->other_host, other->get_port(other)); |
3dd3c5f3 MW |
602 | } |
603 | } | |
604 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); | |
605 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
606 | { | |
8dfbe71b MW |
607 | child_sa->update_hosts(child_sa, this->my_host, this->other_host, |
608 | my_diff, other_diff); | |
3dd3c5f3 MW |
609 | } |
610 | iterator->destroy(iterator); | |
8d77edde MW |
611 | } |
612 | ||
8d77edde | 613 | /** |
c60c7694 | 614 | * Implementation of ike_sa_t.generate |
8d77edde | 615 | */ |
c60c7694 MW |
616 | static status_t generate_message(private_ike_sa_t *this, message_t *message, |
617 | packet_t **packet) | |
8d77edde | 618 | { |
fe04e93a | 619 | this->time.outbound = time(NULL); |
c60c7694 MW |
620 | message->set_ike_sa_id(message, this->ike_sa_id); |
621 | message->set_destination(message, this->other_host->clone(this->other_host)); | |
622 | message->set_source(message, this->my_host->clone(this->my_host)); | |
623 | return message->generate(message, this->crypter_out, this->signer_out, packet); | |
3dd3c5f3 MW |
624 | } |
625 | ||
626 | /** | |
627 | * send a notify back to the sender | |
628 | */ | |
c60c7694 | 629 | static void send_notify_response(private_ike_sa_t *this, message_t *request, |
3dd3c5f3 MW |
630 | notify_type_t type) |
631 | { | |
3dd3c5f3 | 632 | message_t *response; |
3dd3c5f3 MW |
633 | packet_t *packet; |
634 | ||
635 | response = message_create(); | |
3dd3c5f3 MW |
636 | response->set_exchange_type(response, request->get_exchange_type(request)); |
637 | response->set_request(response, FALSE); | |
638 | response->set_message_id(response, request->get_message_id(request)); | |
c60c7694 MW |
639 | response->add_notify(response, FALSE, type, chunk_empty); |
640 | if (this->my_host->is_anyaddr(this->my_host)) | |
b9d9f188 | 641 | { |
c60c7694 MW |
642 | this->my_host->destroy(this->my_host); |
643 | this->my_host = request->get_destination(request); | |
644 | this->my_host = this->my_host->clone(this->my_host); | |
645 | } | |
646 | if (this->other_host->is_anyaddr(this->other_host)) | |
647 | { | |
648 | this->other_host->destroy(this->other_host); | |
649 | this->other_host = request->get_source(request); | |
650 | this->other_host = this->other_host->clone(this->other_host); | |
651 | } | |
652 | if (generate_message(this, response, &packet) == SUCCESS) | |
653 | { | |
4deb8948 | 654 | charon->sender->send(charon->sender, packet); |
b9d9f188 | 655 | } |
3dd3c5f3 | 656 | response->destroy(response); |
3dd3c5f3 MW |
657 | } |
658 | ||
3dd3c5f3 MW |
659 | /** |
660 | * Implementation of ike_sa_t.process_message. | |
661 | */ | |
662 | static status_t process_message(private_ike_sa_t *this, message_t *message) | |
663 | { | |
664 | status_t status; | |
665 | bool is_request; | |
ce461bbd | 666 | |
3dd3c5f3 | 667 | is_request = message->get_request(message); |
ce461bbd | 668 | |
3dd3c5f3 MW |
669 | status = message->parse_body(message, this->crypter_in, this->signer_in); |
670 | if (status != SUCCESS) | |
b9d9f188 | 671 | { |
60356f33 | 672 | |
fe04e93a | 673 | if (is_request) |
3dd3c5f3 | 674 | { |
fe04e93a MW |
675 | switch (status) |
676 | { | |
677 | case NOT_SUPPORTED: | |
b83806d8 | 678 | DBG1(DBG_IKE, "ciritcal unknown payloads found"); |
fe04e93a MW |
679 | if (is_request) |
680 | { | |
681 | send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD); | |
682 | } | |
683 | break; | |
684 | case PARSE_ERROR: | |
b83806d8 | 685 | DBG1(DBG_IKE, "message parsing failed"); |
fe04e93a MW |
686 | if (is_request) |
687 | { | |
688 | send_notify_response(this, message, INVALID_SYNTAX); | |
689 | } | |
690 | break; | |
691 | case VERIFY_ERROR: | |
b83806d8 | 692 | DBG1(DBG_IKE, "message verification failed"); |
fe04e93a MW |
693 | if (is_request) |
694 | { | |
695 | send_notify_response(this, message, INVALID_SYNTAX); | |
696 | } | |
697 | break; | |
698 | case FAILED: | |
b83806d8 | 699 | DBG1(DBG_IKE, "integrity check failed"); |
fe04e93a MW |
700 | /* ignored */ |
701 | break; | |
702 | case INVALID_STATE: | |
b83806d8 | 703 | DBG1(DBG_IKE, "found encrypted message, but no keys available"); |
fe04e93a MW |
704 | if (is_request) |
705 | { | |
706 | send_notify_response(this, message, INVALID_SYNTAX); | |
707 | } | |
708 | default: | |
709 | break; | |
710 | } | |
3dd3c5f3 | 711 | } |
b83806d8 | 712 | DBG1(DBG_IKE, "%N %s with message ID %d processing failed", |
60356f33 MW |
713 | exchange_type_names, message->get_exchange_type(message), |
714 | message->get_request(message) ? "request" : "response", | |
715 | message->get_message_id(message)); | |
c60c7694 | 716 | return status; |
b9d9f188 | 717 | } |
3dd3c5f3 | 718 | else |
ce461bbd | 719 | { |
c60c7694 MW |
720 | host_t *me, *other; |
721 | ||
722 | me = message->get_destination(message); | |
723 | other = message->get_source(message); | |
724 | ||
e0fe7651 MW |
725 | /* if this IKE_SA is virgin, we check for a config */ |
726 | if (this->ike_cfg == NULL) | |
c60c7694 | 727 | { |
0f33e826 | 728 | job_t *job; |
e0fe7651 MW |
729 | this->ike_cfg = charon->cfg_store->get_ike_cfg(charon->cfg_store, |
730 | me, other); | |
731 | if (this->ike_cfg == NULL) | |
c60c7694 | 732 | { |
e0fe7651 MW |
733 | /* no config found for these hosts, destroy */ |
734 | DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N", | |
ea235d38 | 735 | me, other, notify_type_names, NO_PROPOSAL_CHOSEN); |
c60c7694 MW |
736 | send_notify_response(this, message, NO_PROPOSAL_CHOSEN); |
737 | return DESTROY_ME; | |
738 | } | |
0f33e826 MW |
739 | /* add a timeout if peer does not establish it completely */ |
740 | job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE); | |
741 | charon->event_queue->add_relative(charon->event_queue, job, | |
742 | charon->configuration->get_half_open_ike_sa_timeout( | |
743 | charon->configuration)); | |
c60c7694 MW |
744 | } |
745 | ||
e0fe7651 | 746 | /* check if message is trustworthy, and update host information */ |
8dfbe71b | 747 | if (this->state == IKE_CREATED || |
3dd3c5f3 MW |
748 | message->get_exchange_type(message) != IKE_SA_INIT) |
749 | { | |
c60c7694 | 750 | update_hosts(this, me, other); |
fe04e93a | 751 | this->time.inbound = time(NULL); |
3dd3c5f3 | 752 | } |
c60c7694 MW |
753 | return this->task_manager->process_message(this->task_manager, message); |
754 | } | |
755 | } | |
756 | ||
aad398a7 | 757 | /** |
3dd3c5f3 | 758 | * Implementation of ike_sa_t.initiate. |
aad398a7 | 759 | */ |
e0fe7651 | 760 | static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) |
aad398a7 | 761 | { |
c60c7694 MW |
762 | task_t *task; |
763 | ||
764 | if (this->state == IKE_CREATED) | |
c0593835 | 765 | { |
c60c7694 | 766 | |
128ca073 MW |
767 | if (this->other_host->is_anyaddr(this->other_host)) |
768 | { | |
769 | SIG(IKE_UP_START, "initiating IKE_SA"); | |
770 | SIG(IKE_UP_FAILED, "unable to initiate to %%any"); | |
771 | return DESTROY_ME; | |
772 | } | |
773 | ||
c60c7694 MW |
774 | task = (task_t*)ike_init_create(&this->public, TRUE, NULL); |
775 | this->task_manager->queue_task(this->task_manager, task); | |
776 | task = (task_t*)ike_natd_create(&this->public, TRUE); | |
777 | this->task_manager->queue_task(this->task_manager, task); | |
778 | task = (task_t*)ike_cert_create(&this->public, TRUE); | |
779 | this->task_manager->queue_task(this->task_manager, task); | |
c60c7694 MW |
780 | task = (task_t*)ike_auth_create(&this->public, TRUE); |
781 | this->task_manager->queue_task(this->task_manager, task); | |
e0fe7651 | 782 | task = (task_t*)ike_config_create(&this->public, TRUE); |
5744d3e7 | 783 | this->task_manager->queue_task(this->task_manager, task); |
c60c7694 MW |
784 | } |
785 | ||
e0fe7651 | 786 | task = (task_t*)child_create_create(&this->public, child_cfg); |
c60c7694 MW |
787 | this->task_manager->queue_task(this->task_manager, task); |
788 | ||
789 | return this->task_manager->initiate(this->task_manager); | |
aad398a7 JH |
790 | } |
791 | ||
8dfbe71b MW |
792 | /** |
793 | * Implementation of ike_sa_t.acquire. | |
794 | */ | |
795 | static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) | |
796 | { | |
e0fe7651 | 797 | child_cfg_t *child_cfg; |
45f76a7d MW |
798 | iterator_t *iterator; |
799 | child_sa_t *current, *child_sa = NULL; | |
c60c7694 MW |
800 | task_t *task; |
801 | child_create_t *child_create; | |
45f76a7d MW |
802 | |
803 | if (this->state == IKE_DELETING) | |
804 | { | |
b83806d8 MW |
805 | SIG(CHILD_UP_START, "acquiring CHILD_SA on kernel request"); |
806 | SIG(CHILD_UP_FAILED, "acquiring CHILD_SA (reqid %d) failed: " | |
60356f33 | 807 | "IKE_SA is deleting", reqid); |
45f76a7d MW |
808 | return FAILED; |
809 | } | |
810 | ||
45f76a7d MW |
811 | /* find CHILD_SA */ |
812 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); | |
813 | while (iterator->iterate(iterator, (void**)¤t)) | |
814 | { | |
815 | if (current->get_reqid(current) == reqid) | |
c60c7694 MW |
816 | { |
817 | child_sa = current; | |
45f76a7d | 818 | break; |
c60c7694 | 819 | } |
45f76a7d | 820 | } |
c60c7694 MW |
821 | iterator->destroy(iterator); |
822 | if (!child_sa) | |
823 | { | |
824 | SIG(CHILD_UP_START, "acquiring CHILD_SA on kernel request"); | |
825 | SIG(CHILD_UP_FAILED, "acquiring CHILD_SA (reqid %d) failed: " | |
826 | "CHILD_SA not found", reqid); | |
827 | return FAILED; | |
828 | } | |
829 | ||
c60c7694 MW |
830 | |
831 | if (this->state == IKE_CREATED) | |
832 | { | |
833 | task = (task_t*)ike_init_create(&this->public, TRUE, NULL); | |
834 | this->task_manager->queue_task(this->task_manager, task); | |
835 | task = (task_t*)ike_natd_create(&this->public, TRUE); | |
836 | this->task_manager->queue_task(this->task_manager, task); | |
837 | task = (task_t*)ike_cert_create(&this->public, TRUE); | |
838 | this->task_manager->queue_task(this->task_manager, task); | |
c60c7694 MW |
839 | task = (task_t*)ike_auth_create(&this->public, TRUE); |
840 | this->task_manager->queue_task(this->task_manager, task); | |
e0fe7651 | 841 | task = (task_t*)ike_config_create(&this->public, TRUE); |
5744d3e7 | 842 | this->task_manager->queue_task(this->task_manager, task); |
c60c7694 MW |
843 | } |
844 | ||
e0fe7651 MW |
845 | child_cfg = child_sa->get_config(child_sa); |
846 | child_create = child_create_create(&this->public, child_cfg); | |
c60c7694 MW |
847 | child_create->use_reqid(child_create, reqid); |
848 | this->task_manager->queue_task(this->task_manager, (task_t*)child_create); | |
849 | ||
850 | return this->task_manager->initiate(this->task_manager); | |
45f76a7d MW |
851 | } |
852 | ||
45f76a7d MW |
853 | /** |
854 | * Implementation of ike_sa_t.route. | |
855 | */ | |
e0fe7651 | 856 | static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg) |
45f76a7d | 857 | { |
e0fe7651 | 858 | child_sa_t *child_sa; |
45f76a7d MW |
859 | iterator_t *iterator; |
860 | linked_list_t *my_ts, *other_ts; | |
861 | status_t status; | |
862 | ||
b83806d8 MW |
863 | SIG(CHILD_ROUTE_START, "routing CHILD_SA"); |
864 | ||
45f76a7d MW |
865 | /* check if not already routed*/ |
866 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); | |
867 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
868 | { | |
e0fe7651 MW |
869 | if (child_sa->get_state(child_sa) == CHILD_ROUTED && |
870 | streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg))) | |
45f76a7d | 871 | { |
e0fe7651 MW |
872 | iterator->destroy(iterator); |
873 | SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config already routed"); | |
874 | return FAILED; | |
45f76a7d | 875 | } |
45f76a7d MW |
876 | } |
877 | iterator->destroy(iterator); | |
878 | ||
879 | switch (this->state) | |
880 | { | |
c60c7694 MW |
881 | case IKE_DELETING: |
882 | case IKE_REKEYING: | |
883 | SIG(CHILD_ROUTE_FAILED, | |
884 | "unable to route CHILD_SA, as its IKE_SA gets deleted"); | |
885 | return FAILED; | |
45f76a7d | 886 | case IKE_CREATED: |
c60c7694 | 887 | case IKE_CONNECTING: |
8dfbe71b | 888 | case IKE_ESTABLISHED: |
c60c7694 | 889 | default: |
8dfbe71b | 890 | break; |
8dfbe71b | 891 | } |
d756cd1b | 892 | |
c60c7694 | 893 | /* install kernel policies */ |
e0fe7651 MW |
894 | child_sa = child_sa_create(this->my_host, this->other_host, this->my_id, |
895 | this->other_id, child_cfg, FALSE, 0); | |
c60c7694 | 896 | |
e0fe7651 MW |
897 | my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, |
898 | this->my_host); | |
899 | other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, | |
900 | this->other_host); | |
7652be89 | 901 | status = child_sa->add_policies(child_sa, my_ts, other_ts, |
e0fe7651 | 902 | child_cfg->get_mode(child_cfg)); |
55bbff11 MW |
903 | my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); |
904 | other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); | |
e0fe7651 MW |
905 | if (status == SUCCESS) |
906 | { | |
907 | this->child_sas->insert_last(this->child_sas, child_sa); | |
908 | SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed"); | |
909 | } | |
910 | else | |
911 | { | |
912 | SIG(CHILD_ROUTE_FAILED, "routing CHILD_SA failed"); | |
913 | } | |
45f76a7d | 914 | return status; |
8dfbe71b MW |
915 | } |
916 | ||
917 | /** | |
45f76a7d | 918 | * Implementation of ike_sa_t.unroute. |
8dfbe71b | 919 | */ |
e0fe7651 | 920 | static status_t unroute(private_ike_sa_t *this, child_cfg_t *child_cfg) |
8dfbe71b | 921 | { |
45f76a7d | 922 | iterator_t *iterator; |
e0fe7651 | 923 | child_sa_t *child_sa; |
b83806d8 | 924 | bool found = FALSE; |
45f76a7d | 925 | |
b83806d8 MW |
926 | SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA"); |
927 | ||
45f76a7d MW |
928 | /* find CHILD_SA in ROUTED state */ |
929 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); | |
930 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
931 | { | |
e0fe7651 MW |
932 | if (child_sa->get_state(child_sa) == CHILD_ROUTED && |
933 | streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg))) | |
45f76a7d | 934 | { |
e0fe7651 MW |
935 | iterator->remove(iterator); |
936 | SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted"); | |
937 | child_sa->destroy(child_sa); | |
938 | found = TRUE; | |
939 | break; | |
45f76a7d MW |
940 | } |
941 | } | |
942 | iterator->destroy(iterator); | |
b83806d8 MW |
943 | |
944 | if (!found) | |
945 | { | |
946 | SIG(CHILD_UNROUTE_FAILED, "CHILD_SA to unroute not found"); | |
947 | return FAILED; | |
948 | } | |
45f76a7d MW |
949 | /* if we are not established, and we have no more routed childs, remove whole SA */ |
950 | if (this->state == IKE_CREATED && | |
951 | this->child_sas->get_count(this->child_sas) == 0) | |
952 | { | |
953 | return DESTROY_ME; | |
954 | } | |
955 | return SUCCESS; | |
8dfbe71b MW |
956 | } |
957 | ||
edfabed0 MW |
958 | /** |
959 | * Implementation of ike_sa_t.retransmit. | |
960 | */ | |
961 | static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) | |
962 | { | |
963 | this->time.outbound = time(NULL); | |
964 | if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) | |
965 | { | |
e0fe7651 | 966 | child_cfg_t *child_cfg; |
edfabed0 MW |
967 | child_sa_t* child_sa; |
968 | linked_list_t *to_route, *to_restart; | |
969 | iterator_t *iterator; | |
970 | ||
971 | /* send a proper signal to brief interested bus listeners */ | |
972 | switch (this->state) | |
973 | { | |
974 | case IKE_CONNECTING: | |
fdb9b2bd MW |
975 | { |
976 | /* retry IKE_SA_INIT if we have multiple keyingtries */ | |
e0fe7651 | 977 | u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg); |
fdb9b2bd MW |
978 | this->keyingtry++; |
979 | if (tries == 0 || tries > this->keyingtry) | |
980 | { | |
981 | SIG(IKE_UP_FAILED, "peer not responding, trying again " | |
982 | "(%d/%d) in background ", this->keyingtry + 1, tries); | |
983 | reset(this); | |
984 | return this->task_manager->initiate(this->task_manager); | |
985 | } | |
edfabed0 MW |
986 | SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding"); |
987 | break; | |
fdb9b2bd | 988 | } |
edfabed0 MW |
989 | case IKE_REKEYING: |
990 | SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding"); | |
991 | break; | |
992 | case IKE_DELETING: | |
993 | SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding"); | |
994 | break; | |
995 | default: | |
996 | break; | |
997 | } | |
998 | ||
999 | /* summarize how we have to handle each child */ | |
1000 | to_route = linked_list_create(); | |
1001 | to_restart = linked_list_create(); | |
1002 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); | |
1003 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
1004 | { | |
e0fe7651 | 1005 | child_cfg = child_sa->get_config(child_sa); |
edfabed0 MW |
1006 | |
1007 | if (child_sa->get_state(child_sa) == CHILD_ROUTED) | |
1008 | { | |
1009 | /* reroute routed CHILD_SAs */ | |
e0fe7651 | 1010 | to_route->insert_last(to_route, child_cfg); |
edfabed0 MW |
1011 | } |
1012 | else | |
1013 | { | |
1014 | /* use DPD action for established CHILD_SAs */ | |
e0fe7651 | 1015 | switch (this->peer_cfg->get_dpd_action(this->peer_cfg)) |
edfabed0 MW |
1016 | { |
1017 | case DPD_ROUTE: | |
e0fe7651 | 1018 | to_route->insert_last(to_route, child_cfg); |
edfabed0 MW |
1019 | break; |
1020 | case DPD_RESTART: | |
e0fe7651 | 1021 | to_restart->insert_last(to_restart, child_cfg); |
edfabed0 MW |
1022 | break; |
1023 | default: | |
1024 | break; | |
1025 | } | |
1026 | } | |
1027 | } | |
1028 | iterator->destroy(iterator); | |
1029 | ||
1030 | /* create a new IKE_SA if we have to route or to restart */ | |
1031 | if (to_route->get_count(to_route) || to_restart->get_count(to_restart)) | |
1032 | { | |
edfabed0 MW |
1033 | private_ike_sa_t *new; |
1034 | task_t *task; | |
1035 | ||
b9e363f8 MW |
1036 | new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new( |
1037 | charon->ike_sa_manager, TRUE); | |
edfabed0 | 1038 | |
e0fe7651 MW |
1039 | set_peer_cfg(new, this->peer_cfg); |
1040 | /* use actual used host, not the wildcarded one in config */ | |
edfabed0 MW |
1041 | new->other_host->destroy(new->other_host); |
1042 | new->other_host = this->other_host->clone(this->other_host); | |
1043 | ||
1044 | /* install routes */ | |
e0fe7651 | 1045 | while (to_route->remove_last(to_route, (void**)&child_cfg) == SUCCESS) |
edfabed0 | 1046 | { |
e0fe7651 | 1047 | route(new, child_cfg); |
edfabed0 MW |
1048 | } |
1049 | ||
1050 | /* restart children */ | |
1051 | if (to_restart->get_count(to_restart)) | |
1052 | { | |
1053 | task = (task_t*)ike_init_create(&new->public, TRUE, NULL); | |
1054 | new->task_manager->queue_task(new->task_manager, task); | |
1055 | task = (task_t*)ike_natd_create(&new->public, TRUE); | |
1056 | new->task_manager->queue_task(new->task_manager, task); | |
1057 | task = (task_t*)ike_cert_create(&new->public, TRUE); | |
1058 | new->task_manager->queue_task(new->task_manager, task); | |
e0fe7651 | 1059 | task = (task_t*)ike_config_create(&new->public, TRUE); |
edfabed0 MW |
1060 | new->task_manager->queue_task(new->task_manager, task); |
1061 | task = (task_t*)ike_auth_create(&new->public, TRUE); | |
1062 | new->task_manager->queue_task(new->task_manager, task); | |
1063 | ||
e0fe7651 | 1064 | while (to_restart->remove_last(to_restart, (void**)&child_cfg) == SUCCESS) |
edfabed0 | 1065 | { |
e0fe7651 | 1066 | task = (task_t*)child_create_create(&new->public, child_cfg); |
edfabed0 MW |
1067 | new->task_manager->queue_task(new->task_manager, task); |
1068 | } | |
1069 | new->task_manager->initiate(new->task_manager); | |
1070 | } | |
1071 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public); | |
1072 | } | |
1073 | to_route->destroy(to_route); | |
1074 | to_restart->destroy(to_restart); | |
1075 | return DESTROY_ME; | |
1076 | } | |
1077 | return SUCCESS; | |
1078 | } | |
1079 | ||
2f89902d | 1080 | /** |
fe04e93a | 1081 | * Implementation of ike_sa_t.get_prf. |
2f89902d | 1082 | */ |
8dfbe71b | 1083 | static prf_t *get_prf(private_ike_sa_t *this) |
2f89902d | 1084 | { |
8dfbe71b | 1085 | return this->prf; |
2f89902d MW |
1086 | } |
1087 | ||
aad398a7 | 1088 | /** |
fe04e93a | 1089 | * Implementation of ike_sa_t.get_prf. |
aad398a7 | 1090 | */ |
8dfbe71b | 1091 | static prf_t *get_child_prf(private_ike_sa_t *this) |
aad398a7 | 1092 | { |
8dfbe71b | 1093 | return this->child_prf; |
aad398a7 JH |
1094 | } |
1095 | ||
aad398a7 | 1096 | /** |
382b4817 | 1097 | * Implementation of ike_sa_t.get_auth_bild |
aad398a7 | 1098 | */ |
382b4817 | 1099 | static prf_t *get_auth_build(private_ike_sa_t *this) |
aad398a7 | 1100 | { |
382b4817 | 1101 | return this->auth_build; |
aad398a7 JH |
1102 | } |
1103 | ||
283dbcc5 | 1104 | /** |
382b4817 | 1105 | * Implementation of ike_sa_t.get_auth_verify |
283dbcc5 | 1106 | */ |
382b4817 | 1107 | static prf_t *get_auth_verify(private_ike_sa_t *this) |
283dbcc5 | 1108 | { |
382b4817 | 1109 | return this->auth_verify; |
283dbcc5 MW |
1110 | } |
1111 | ||
ae3012a0 | 1112 | /** |
8dfbe71b | 1113 | * Implementation of ike_sa_t.get_id. |
0df63d6b | 1114 | */ |
8dfbe71b | 1115 | static ike_sa_id_t* get_id(private_ike_sa_t *this) |
0df63d6b | 1116 | { |
8dfbe71b | 1117 | return this->ike_sa_id; |
0df63d6b JH |
1118 | } |
1119 | ||
0fdc3c7f | 1120 | /** |
8dfbe71b | 1121 | * Implementation of ike_sa_t.get_my_id. |
0fdc3c7f | 1122 | */ |
8dfbe71b | 1123 | static identification_t* get_my_id(private_ike_sa_t *this) |
0fdc3c7f | 1124 | { |
8dfbe71b | 1125 | return this->my_id; |
8d68033e JH |
1126 | } |
1127 | ||
1128 | /** | |
8dfbe71b | 1129 | * Implementation of ike_sa_t.set_my_id. |
8d68033e | 1130 | */ |
8dfbe71b | 1131 | static void set_my_id(private_ike_sa_t *this, identification_t *me) |
8d68033e | 1132 | { |
c0593835 | 1133 | DESTROY_IF(this->my_id); |
8dfbe71b | 1134 | this->my_id = me; |
0fdc3c7f JH |
1135 | } |
1136 | ||
30b5b412 | 1137 | /** |
8dfbe71b | 1138 | * Implementation of ike_sa_t.get_other_id. |
30b5b412 | 1139 | */ |
8dfbe71b | 1140 | static identification_t* get_other_id(private_ike_sa_t *this) |
30b5b412 | 1141 | { |
8dfbe71b | 1142 | return this->other_id; |
3dd3c5f3 | 1143 | } |
8dfbe71b | 1144 | |
3dd3c5f3 | 1145 | /** |
8dfbe71b | 1146 | * Implementation of ike_sa_t.set_other_id. |
3dd3c5f3 | 1147 | */ |
8dfbe71b | 1148 | static void set_other_id(private_ike_sa_t *this, identification_t *other) |
3dd3c5f3 | 1149 | { |
c0593835 | 1150 | DESTROY_IF(this->other_id); |
8dfbe71b | 1151 | this->other_id = other; |
30b5b412 MW |
1152 | } |
1153 | ||
8d77edde | 1154 | /** |
fe04e93a | 1155 | * Implementation of ike_sa_t.derive_keys. |
8d77edde | 1156 | */ |
fe04e93a | 1157 | static status_t derive_keys(private_ike_sa_t *this, |
c60c7694 | 1158 | proposal_t *proposal, chunk_t secret, |
fe04e93a | 1159 | chunk_t nonce_i, chunk_t nonce_r, |
3183006d | 1160 | bool initiator, prf_t *child_prf, prf_t *old_prf) |
8d77edde | 1161 | { |
3dd3c5f3 | 1162 | prf_plus_t *prf_plus; |
c60c7694 | 1163 | chunk_t skeyseed, key, nonces, prf_plus_seed; |
3dd3c5f3 MW |
1164 | algorithm_t *algo; |
1165 | size_t key_size; | |
1166 | crypter_t *crypter_i, *crypter_r; | |
1167 | signer_t *signer_i, *signer_r; | |
382b4817 | 1168 | prf_t *prf_i, *prf_r; |
fe04e93a MW |
1169 | u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)]; |
1170 | chunk_t spi_i = chunk_from_buf(spi_i_buf); | |
1171 | chunk_t spi_r = chunk_from_buf(spi_r_buf); | |
8d77edde | 1172 | |
fe04e93a | 1173 | /* Create SAs general purpose PRF first, we may use it here */ |
3dd3c5f3 | 1174 | if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo)) |
8d77edde | 1175 | { |
b83806d8 | 1176 | DBG1(DBG_IKE, "key derivation failed: no PSEUDO_RANDOM_FUNCTION");; |
3dd3c5f3 | 1177 | return FAILED; |
8d77edde | 1178 | } |
3dd3c5f3 MW |
1179 | this->prf = prf_create(algo->algorithm); |
1180 | if (this->prf == NULL) | |
8d77edde | 1181 | { |
b83806d8 | 1182 | DBG1(DBG_IKE, "key derivation failed: PSEUDO_RANDOM_FUNCTION " |
60356f33 | 1183 | "%N not supported!", pseudo_random_function_names, algo->algorithm); |
3dd3c5f3 | 1184 | return FAILED; |
8d77edde MW |
1185 | } |
1186 | ||
b83806d8 | 1187 | DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret); |
fe04e93a MW |
1188 | nonces = chunk_cat("cc", nonce_i, nonce_r); |
1189 | *((u_int64_t*)spi_i.ptr) = this->ike_sa_id->get_initiator_spi(this->ike_sa_id); | |
1190 | *((u_int64_t*)spi_r.ptr) = this->ike_sa_id->get_responder_spi(this->ike_sa_id); | |
1191 | prf_plus_seed = chunk_cat("ccc", nonces, spi_i, spi_r); | |
8d77edde | 1192 | |
fe04e93a MW |
1193 | /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) |
1194 | * | |
b83806d8 | 1195 | * if we are rekeying, SKEYSEED is built on another way |
fe04e93a | 1196 | */ |
3183006d | 1197 | if (child_prf == NULL) /* not rekeying */ |
60356f33 | 1198 | { |
fe04e93a MW |
1199 | /* SKEYSEED = prf(Ni | Nr, g^ir) */ |
1200 | this->prf->set_key(this->prf, nonces); | |
1201 | this->prf->allocate_bytes(this->prf, secret, &skeyseed); | |
b83806d8 | 1202 | DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); |
fe04e93a MW |
1203 | this->prf->set_key(this->prf, skeyseed); |
1204 | chunk_free(&skeyseed); | |
1205 | chunk_free(&secret); | |
1206 | prf_plus = prf_plus_create(this->prf, prf_plus_seed); | |
1207 | } | |
1208 | else | |
1209 | { | |
3183006d MW |
1210 | /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) |
1211 | * use OLD SAs PRF functions for both prf_plus and prf */ | |
fe04e93a | 1212 | secret = chunk_cat("mc", secret, nonces); |
3183006d | 1213 | child_prf->allocate_bytes(child_prf, secret, &skeyseed); |
b83806d8 | 1214 | DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); |
3183006d | 1215 | old_prf->set_key(old_prf, skeyseed); |
fe04e93a MW |
1216 | chunk_free(&skeyseed); |
1217 | chunk_free(&secret); | |
3183006d | 1218 | prf_plus = prf_plus_create(old_prf, prf_plus_seed); |
fe04e93a | 1219 | } |
3dd3c5f3 | 1220 | chunk_free(&nonces); |
fe04e93a MW |
1221 | chunk_free(&prf_plus_seed); |
1222 | ||
1223 | /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */ | |
3dd3c5f3 | 1224 | |
fe04e93a MW |
1225 | /* SK_d is used for generating CHILD_SA key mat => child_prf */ |
1226 | proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); | |
3dd3c5f3 MW |
1227 | this->child_prf = prf_create(algo->algorithm); |
1228 | key_size = this->child_prf->get_key_size(this->child_prf); | |
1229 | prf_plus->allocate_bytes(prf_plus, key_size, &key); | |
b83806d8 | 1230 | DBG4(DBG_IKE, "Sk_d secret %B", &key); |
3dd3c5f3 MW |
1231 | this->child_prf->set_key(this->child_prf, key); |
1232 | chunk_free(&key); | |
1233 | ||
fe04e93a | 1234 | /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */ |
3dd3c5f3 | 1235 | if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo)) |
8d77edde | 1236 | { |
b83806d8 | 1237 | DBG1(DBG_IKE, "key derivation failed: no INTEGRITY_ALGORITHM"); |
8d77edde MW |
1238 | return FAILED; |
1239 | } | |
3dd3c5f3 MW |
1240 | signer_i = signer_create(algo->algorithm); |
1241 | signer_r = signer_create(algo->algorithm); | |
1242 | if (signer_i == NULL || signer_r == NULL) | |
1396815a | 1243 | { |
b83806d8 | 1244 | DBG1(DBG_IKE, "key derivation failed: INTEGRITY_ALGORITHM " |
60356f33 | 1245 | "%N not supported!", integrity_algorithm_names ,algo->algorithm); |
3dd3c5f3 | 1246 | return FAILED; |
1396815a | 1247 | } |
3dd3c5f3 MW |
1248 | key_size = signer_i->get_key_size(signer_i); |
1249 | ||
1250 | prf_plus->allocate_bytes(prf_plus, key_size, &key); | |
b83806d8 | 1251 | DBG4(DBG_IKE, "Sk_ai secret %B", &key); |
3dd3c5f3 MW |
1252 | signer_i->set_key(signer_i, key); |
1253 | chunk_free(&key); | |
fe04e93a | 1254 | |
3dd3c5f3 | 1255 | prf_plus->allocate_bytes(prf_plus, key_size, &key); |
b83806d8 | 1256 | DBG4(DBG_IKE, "Sk_ar secret %B", &key); |
3dd3c5f3 MW |
1257 | signer_r->set_key(signer_r, key); |
1258 | chunk_free(&key); | |
1396815a | 1259 | |
3dd3c5f3 | 1260 | if (initiator) |
1396815a | 1261 | { |
0d379627 MW |
1262 | this->signer_in = signer_r; |
1263 | this->signer_out = signer_i; | |
1396815a MW |
1264 | } |
1265 | else | |
1266 | { | |
0d379627 MW |
1267 | this->signer_in = signer_i; |
1268 | this->signer_out = signer_r; | |
1396815a | 1269 | } |
3dd3c5f3 | 1270 | |
fe04e93a | 1271 | /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */ |
3dd3c5f3 | 1272 | if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo)) |
1396815a | 1273 | { |
b83806d8 | 1274 | DBG1(DBG_IKE, "key derivation failed: no ENCRYPTION_ALGORITHM"); |
3dd3c5f3 | 1275 | return FAILED; |
fe04e93a | 1276 | } |
3dd3c5f3 MW |
1277 | crypter_i = crypter_create(algo->algorithm, algo->key_size / 8); |
1278 | crypter_r = crypter_create(algo->algorithm, algo->key_size / 8); | |
1279 | if (crypter_i == NULL || crypter_r == NULL) | |
1280 | { | |
b83806d8 | 1281 | DBG1(DBG_IKE, "key derivation failed: ENCRYPTION_ALGORITHM " |
60356f33 MW |
1282 | "%N (key size %d) not supported!", |
1283 | encryption_algorithm_names, algo->algorithm, algo->key_size); | |
3dd3c5f3 | 1284 | return FAILED; |
1396815a | 1285 | } |
3dd3c5f3 | 1286 | key_size = crypter_i->get_key_size(crypter_i); |
1396815a | 1287 | |
3dd3c5f3 | 1288 | prf_plus->allocate_bytes(prf_plus, key_size, &key); |
b83806d8 | 1289 | DBG4(DBG_IKE, "Sk_ei secret %B", &key); |
3dd3c5f3 MW |
1290 | crypter_i->set_key(crypter_i, key); |
1291 | chunk_free(&key); | |
1292 | ||
1293 | prf_plus->allocate_bytes(prf_plus, key_size, &key); | |
b83806d8 | 1294 | DBG4(DBG_IKE, "Sk_er secret %B", &key); |
3dd3c5f3 MW |
1295 | crypter_r->set_key(crypter_r, key); |
1296 | chunk_free(&key); | |
1297 | ||
1298 | if (initiator) | |
1396815a | 1299 | { |
0d379627 MW |
1300 | this->crypter_in = crypter_r; |
1301 | this->crypter_out = crypter_i; | |
1396815a | 1302 | } |
3dd3c5f3 MW |
1303 | else |
1304 | { | |
0d379627 MW |
1305 | this->crypter_in = crypter_i; |
1306 | this->crypter_out = crypter_r; | |
3dd3c5f3 MW |
1307 | } |
1308 | ||
fe04e93a | 1309 | /* SK_pi/SK_pr used for authentication => prf_auth_i, prf_auth_r */ |
3dd3c5f3 | 1310 | proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); |
382b4817 MW |
1311 | prf_i = prf_create(algo->algorithm); |
1312 | prf_r = prf_create(algo->algorithm); | |
3dd3c5f3 | 1313 | |
382b4817 | 1314 | key_size = prf_i->get_key_size(prf_i); |
3dd3c5f3 | 1315 | prf_plus->allocate_bytes(prf_plus, key_size, &key); |
b83806d8 | 1316 | DBG4(DBG_IKE, "Sk_pi secret %B", &key); |
382b4817 | 1317 | prf_i->set_key(prf_i, key); |
3dd3c5f3 MW |
1318 | chunk_free(&key); |
1319 | ||
1320 | prf_plus->allocate_bytes(prf_plus, key_size, &key); | |
b83806d8 | 1321 | DBG4(DBG_IKE, "Sk_pr secret %B", &key); |
382b4817 | 1322 | prf_r->set_key(prf_r, key); |
3dd3c5f3 MW |
1323 | chunk_free(&key); |
1324 | ||
382b4817 MW |
1325 | if (initiator) |
1326 | { | |
1327 | this->auth_verify = prf_r; | |
1328 | this->auth_build = prf_i; | |
1329 | } | |
1330 | else | |
1331 | { | |
1332 | this->auth_verify = prf_i; | |
1333 | this->auth_build = prf_r; | |
1334 | } | |
1335 | ||
3dd3c5f3 MW |
1336 | /* all done, prf_plus not needed anymore */ |
1337 | prf_plus->destroy(prf_plus); | |
1338 | ||
1339 | return SUCCESS; | |
1396815a MW |
1340 | } |
1341 | ||
32b6500f | 1342 | /** |
fe04e93a | 1343 | * Implementation of ike_sa_t.add_child_sa. |
32b6500f | 1344 | */ |
3dd3c5f3 | 1345 | static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa) |
32b6500f | 1346 | { |
3dd3c5f3 | 1347 | this->child_sas->insert_last(this->child_sas, child_sa); |
32b6500f MW |
1348 | } |
1349 | ||
695723d4 | 1350 | /** |
fe04e93a | 1351 | * Implementation of ike_sa_t.get_child_sa. |
695723d4 | 1352 | */ |
698d7749 MW |
1353 | static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol, |
1354 | u_int32_t spi, bool inbound) | |
695723d4 MW |
1355 | { |
1356 | iterator_t *iterator; | |
1357 | child_sa_t *current, *found = NULL; | |
1358 | ||
45f76a7d | 1359 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); |
191a26a6 | 1360 | while (iterator->iterate(iterator, (void**)¤t)) |
c60c7694 | 1361 | { |
698d7749 | 1362 | if (current->get_spi(current, inbound) == spi && |
191a26a6 | 1363 | current->get_protocol(current) == protocol) |
695723d4 MW |
1364 | { |
1365 | found = current; | |
1366 | } | |
1367 | } | |
1368 | iterator->destroy(iterator); | |
1369 | return found; | |
8d77edde MW |
1370 | } |
1371 | ||
3183006d MW |
1372 | /** |
1373 | * Implementation of ike_sa_t.create_child_sa_iterator. | |
1374 | */ | |
1375 | static iterator_t* create_child_sa_iterator(private_ike_sa_t *this) | |
1376 | { | |
1377 | return this->child_sas->create_iterator(this->child_sas, TRUE); | |
1378 | } | |
1379 | ||
8d77edde MW |
1380 | /** |
1381 | * Implementation of ike_sa_t.rekey_child_sa. | |
1382 | */ | |
698d7749 | 1383 | static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) |
8d77edde | 1384 | { |
8d77edde | 1385 | child_sa_t *child_sa; |
c60c7694 | 1386 | child_rekey_t *child_rekey; |
8d77edde | 1387 | |
698d7749 | 1388 | child_sa = get_child_sa(this, protocol, spi, TRUE); |
c60c7694 | 1389 | if (child_sa) |
8d77edde | 1390 | { |
c60c7694 MW |
1391 | child_rekey = child_rekey_create(&this->public, child_sa); |
1392 | this->task_manager->queue_task(this->task_manager, &child_rekey->task); | |
1393 | return this->task_manager->initiate(this->task_manager); | |
8d77edde | 1394 | } |
c60c7694 | 1395 | return FAILED; |
698d7749 MW |
1396 | } |
1397 | ||
1398 | /** | |
1399 | * Implementation of ike_sa_t.delete_child_sa. | |
1400 | */ | |
1401 | static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) | |
1402 | { | |
698d7749 | 1403 | child_sa_t *child_sa; |
c60c7694 | 1404 | child_delete_t *child_delete; |
698d7749 MW |
1405 | |
1406 | child_sa = get_child_sa(this, protocol, spi, TRUE); | |
c60c7694 | 1407 | if (child_sa) |
8d77edde | 1408 | { |
c60c7694 MW |
1409 | child_delete = child_delete_create(&this->public, child_sa); |
1410 | this->task_manager->queue_task(this->task_manager, &child_delete->task); | |
1411 | return this->task_manager->initiate(this->task_manager); | |
8d77edde | 1412 | } |
c60c7694 | 1413 | return FAILED; |
698d7749 MW |
1414 | } |
1415 | ||
1416 | /** | |
fe04e93a | 1417 | * Implementation of ike_sa_t.destroy_child_sa. |
698d7749 | 1418 | */ |
c60c7694 MW |
1419 | static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol, |
1420 | u_int32_t spi) | |
698d7749 MW |
1421 | { |
1422 | iterator_t *iterator; | |
1423 | child_sa_t *child_sa; | |
1424 | status_t status = NOT_FOUND; | |
8d77edde | 1425 | |
698d7749 MW |
1426 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); |
1427 | while (iterator->iterate(iterator, (void**)&child_sa)) | |
1428 | { | |
1429 | if (child_sa->get_protocol(child_sa) == protocol && | |
1430 | child_sa->get_spi(child_sa, TRUE) == spi) | |
1431 | { | |
1432 | child_sa->destroy(child_sa); | |
1433 | iterator->remove(iterator); | |
1434 | status = SUCCESS; | |
1435 | break; | |
1436 | } | |
8d77edde | 1437 | } |
698d7749 MW |
1438 | iterator->destroy(iterator); |
1439 | return status; | |
8d77edde MW |
1440 | } |
1441 | ||
6fe03b0a MW |
1442 | /** |
1443 | * Implementation of public_ike_sa_t.delete. | |
1444 | */ | |
1445 | static status_t delete_(private_ike_sa_t *this) | |
1446 | { | |
c60c7694 MW |
1447 | ike_delete_t *ike_delete; |
1448 | ||
6fe03b0a MW |
1449 | switch (this->state) |
1450 | { | |
6fe03b0a | 1451 | case IKE_ESTABLISHED: |
c60c7694 MW |
1452 | DBG1(DBG_IKE, "deleting IKE_SA"); |
1453 | /* do not log when rekeyed */ | |
1454 | case IKE_REKEYING: | |
1455 | ike_delete = ike_delete_create(&this->public, TRUE); | |
1456 | this->task_manager->queue_task(this->task_manager, &ike_delete->task); | |
1457 | return this->task_manager->initiate(this->task_manager); | |
6fe03b0a | 1458 | default: |
c60c7694 MW |
1459 | DBG1(DBG_IKE, "destroying IKE_SA in state %N without notification", |
1460 | ike_sa_state_names, this->state); | |
1461 | break; | |
6fe03b0a | 1462 | } |
c60c7694 | 1463 | return DESTROY_ME; |
6fe03b0a MW |
1464 | } |
1465 | ||
b92eef28 | 1466 | /** |
fe04e93a MW |
1467 | * Implementation of ike_sa_t.rekey. |
1468 | */ | |
1469 | static status_t rekey(private_ike_sa_t *this) | |
1470 | { | |
c60c7694 | 1471 | ike_rekey_t *ike_rekey; |
fe04e93a | 1472 | |
c60c7694 | 1473 | ike_rekey = ike_rekey_create(&this->public, TRUE); |
fe04e93a | 1474 | |
c60c7694 MW |
1475 | this->task_manager->queue_task(this->task_manager, &ike_rekey->task); |
1476 | return this->task_manager->initiate(this->task_manager); | |
fe04e93a MW |
1477 | } |
1478 | ||
6fe03b0a | 1479 | /** |
c60c7694 | 1480 | * Implementation of ike_sa_t.reestablish |
6fe03b0a | 1481 | */ |
c60c7694 | 1482 | static void reestablish(private_ike_sa_t *this) |
6fe03b0a | 1483 | { |
c60c7694 | 1484 | private_ike_sa_t *other; |
6fe03b0a | 1485 | iterator_t *iterator; |
c60c7694 | 1486 | child_sa_t *child_sa; |
e0fe7651 | 1487 | child_cfg_t *child_cfg; |
c60c7694 MW |
1488 | task_t *task; |
1489 | job_t *job; | |
6fe03b0a | 1490 | |
b9e363f8 MW |
1491 | other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new( |
1492 | charon->ike_sa_manager, TRUE); | |
6fe03b0a | 1493 | |
e0fe7651 | 1494 | set_peer_cfg(other, this->peer_cfg); |
9362e063 MW |
1495 | other->other_host->destroy(other->other_host); |
1496 | other->other_host = this->other_host->clone(this->other_host); | |
c60c7694 MW |
1497 | |
1498 | if (this->state == IKE_ESTABLISHED) | |
6fe03b0a | 1499 | { |
c60c7694 MW |
1500 | task = (task_t*)ike_init_create(&other->public, TRUE, NULL); |
1501 | other->task_manager->queue_task(other->task_manager, task); | |
1502 | task = (task_t*)ike_natd_create(&other->public, TRUE); | |
1503 | other->task_manager->queue_task(other->task_manager, task); | |
1504 | task = (task_t*)ike_cert_create(&other->public, TRUE); | |
1505 | other->task_manager->queue_task(other->task_manager, task); | |
e0fe7651 | 1506 | task = (task_t*)ike_config_create(&other->public, TRUE); |
c60c7694 MW |
1507 | other->task_manager->queue_task(other->task_manager, task); |
1508 | task = (task_t*)ike_auth_create(&other->public, TRUE); | |
1509 | other->task_manager->queue_task(other->task_manager, task); | |
6fe03b0a MW |
1510 | } |
1511 | ||
c60c7694 MW |
1512 | other->task_manager->adopt_tasks(other->task_manager, this->task_manager); |
1513 | ||
1514 | /* Create task for established children, adopt routed children directly */ | |
6fe03b0a | 1515 | iterator = this->child_sas->create_iterator(this->child_sas, TRUE); |
c60c7694 | 1516 | while(iterator->iterate(iterator, (void**)&child_sa)) |
6fe03b0a | 1517 | { |
c60c7694 | 1518 | switch (child_sa->get_state(child_sa)) |
6fe03b0a | 1519 | { |
c60c7694 MW |
1520 | case CHILD_ROUTED: |
1521 | { | |
1522 | iterator->remove(iterator); | |
1523 | other->child_sas->insert_first(other->child_sas, child_sa); | |
1524 | break; | |
1525 | } | |
1526 | default: | |
1527 | { | |
e0fe7651 MW |
1528 | child_cfg = child_sa->get_config(child_sa); |
1529 | task = (task_t*)child_create_create(&other->public, child_cfg); | |
c60c7694 MW |
1530 | other->task_manager->queue_task(other->task_manager, task); |
1531 | break; | |
1532 | } | |
6fe03b0a | 1533 | } |
6fe03b0a MW |
1534 | } |
1535 | iterator->destroy(iterator); | |
6fe03b0a | 1536 | |
c60c7694 MW |
1537 | other->task_manager->initiate(other->task_manager); |
1538 | ||
1539 | charon->ike_sa_manager->checkin(charon->ike_sa_manager, &other->public); | |
1540 | ||
1541 | job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE); | |
1542 | charon->job_queue->add(charon->job_queue, job); | |
6fe03b0a MW |
1543 | } |
1544 | ||
3183006d | 1545 | /** |
c60c7694 | 1546 | * Implementation of ike_sa_t.inherit. |
3183006d | 1547 | */ |
e23a59f6 | 1548 | static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) |
3183006d | 1549 | { |
c60c7694 MW |
1550 | child_sa_t *child_sa; |
1551 | host_t *ip; | |
1552 | ||
1553 | /* apply hosts and ids */ | |
1554 | this->my_host->destroy(this->my_host); | |
1555 | this->other_host->destroy(this->other_host); | |
1556 | this->my_id->destroy(this->my_id); | |
1557 | this->other_id->destroy(this->other_id); | |
1558 | this->my_host = other->my_host->clone(other->my_host); | |
1559 | this->other_host = other->other_host->clone(other->other_host); | |
1560 | this->my_id = other->my_id->clone(other->my_id); | |
1561 | this->other_id = other->other_id->clone(other->other_id); | |
1562 | ||
1563 | /* apply virtual assigned IPs... */ | |
1564 | if (other->my_virtual_ip) | |
1565 | { | |
1566 | this->my_virtual_ip = other->my_virtual_ip; | |
1567 | other->my_virtual_ip = NULL; | |
1568 | } | |
1569 | if (other->other_virtual_ip) | |
1570 | { | |
1571 | this->other_virtual_ip = other->other_virtual_ip; | |
1572 | other->other_virtual_ip = NULL; | |
1573 | } | |
1574 | ||
1575 | /* ... and DNS servers */ | |
1576 | while (other->dns_servers->remove_last(other->dns_servers, | |
1577 | (void**)&ip) == SUCCESS) | |
1578 | { | |
1579 | this->dns_servers->insert_first(this->dns_servers, ip); | |
1580 | } | |
1581 | ||
1582 | /* adopt all children */ | |
1583 | while (other->child_sas->remove_last(other->child_sas, | |
1584 | (void**)&child_sa) == SUCCESS) | |
1585 | { | |
1586 | this->child_sas->insert_first(this->child_sas, (void*)child_sa); | |
1587 | } | |
e23a59f6 MW |
1588 | |
1589 | /* move pending tasks to the new IKE_SA */ | |
1590 | this->task_manager->adopt_tasks(this->task_manager, other->task_manager); | |
1591 | ||
1592 | /* we have to initate here, there may be new tasks to handle */ | |
1593 | return this->task_manager->initiate(this->task_manager); | |
3183006d MW |
1594 | } |
1595 | ||
1596 | /** | |
c60c7694 | 1597 | * Implementation of ike_sa_t.is_natt_enabled. |
3183006d | 1598 | */ |
c60c7694 | 1599 | static bool is_natt_enabled(private_ike_sa_t *this) |
3183006d | 1600 | { |
c60c7694 | 1601 | return this->nat_here || this->nat_there; |
3183006d MW |
1602 | } |
1603 | ||
fe04e93a | 1604 | /** |
c60c7694 | 1605 | * Implementation of ike_sa_t.enable_natt. |
fe04e93a | 1606 | */ |
c60c7694 | 1607 | static void enable_natt(private_ike_sa_t *this, bool local) |
fe04e93a | 1608 | { |
c60c7694 | 1609 | if (local) |
fe04e93a | 1610 | { |
c60c7694 MW |
1611 | DBG1(DBG_IKE, "local host is behind NAT, scheduling keep alives"); |
1612 | this->nat_here = TRUE; | |
1613 | send_keepalive(this); | |
1614 | } | |
1615 | else | |
1616 | { | |
1617 | DBG1(DBG_IKE, "remote host is behind NAT"); | |
1618 | this->nat_there = TRUE; | |
fe04e93a MW |
1619 | } |
1620 | } | |
1621 | ||
1396815a | 1622 | /** |
c60c7694 | 1623 | * Implementation of ike_sa_t.set_virtual_ip |
1396815a | 1624 | */ |
c60c7694 | 1625 | static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip) |
1396815a | 1626 | { |
c60c7694 MW |
1627 | if (local) |
1628 | { | |
1629 | DBG1(DBG_IKE, "installing new virtual IP %H", ip); | |
1630 | if (this->my_virtual_ip) | |
1631 | { | |
1632 | DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip); | |
1633 | charon->kernel_interface->del_ip(charon->kernel_interface, | |
1634 | this->my_virtual_ip, | |
1d51abb7 | 1635 | this->my_host); |
c60c7694 MW |
1636 | this->my_virtual_ip->destroy(this->my_virtual_ip); |
1637 | } | |
1638 | if (charon->kernel_interface->add_ip(charon->kernel_interface, ip, | |
1d51abb7 | 1639 | this->my_host) == SUCCESS) |
c60c7694 MW |
1640 | { |
1641 | this->my_virtual_ip = ip->clone(ip); | |
1642 | } | |
1643 | else | |
1644 | { | |
1645 | DBG1(DBG_IKE, "installing virtual IP %H failed", ip); | |
1646 | this->my_virtual_ip = NULL; | |
1647 | } | |
1648 | } | |
1649 | else | |
1650 | { | |
1651 | DESTROY_IF(this->other_virtual_ip); | |
1652 | this->other_virtual_ip = ip->clone(ip); | |
1653 | } | |
1396815a MW |
1654 | } |
1655 | ||
1656 | /** | |
c60c7694 | 1657 | * Implementation of ike_sa_t.get_virtual_ip |
1396815a | 1658 | */ |
c60c7694 | 1659 | static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) |
1396815a | 1660 | { |
3dd3c5f3 | 1661 | if (local) |
2f89902d | 1662 | { |
c60c7694 | 1663 | return this->my_virtual_ip; |
3dd3c5f3 MW |
1664 | } |
1665 | else | |
1666 | { | |
c60c7694 MW |
1667 | return this->other_virtual_ip; |
1668 | } | |
1669 | } | |
1670 | ||
1671 | /** | |
1672 | * Implementation of ike_sa_t.remove_dns_server | |
1673 | */ | |
1674 | static void remove_dns_servers(private_ike_sa_t *this) | |
1675 | { | |
1676 | FILE *file; | |
1677 | struct stat stats; | |
1678 | chunk_t contents, line, orig_line, token; | |
1679 | char string[INET6_ADDRSTRLEN]; | |
1680 | host_t *ip; | |
1681 | iterator_t *iterator; | |
1682 | ||
1683 | if (this->dns_servers->get_count(this->dns_servers) == 0) | |
1684 | { | |
1685 | /* don't touch anything if we have no nameservers installed */ | |
1686 | return; | |
1687 | } | |
1688 | ||
1689 | file = fopen(RESOLV_CONF, "r"); | |
1690 | if (file == NULL || stat(RESOLV_CONF, &stats) != 0) | |
1691 | { | |
1692 | DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); | |
1693 | return; | |
1694 | } | |
1695 | ||
1696 | contents = chunk_alloca((size_t)stats.st_size); | |
1697 | ||
1698 | if (fread(contents.ptr, 1, contents.len, file) != contents.len) | |
1699 | { | |
1700 | DBG1(DBG_IKE, "unable to read DNS configuration file: %m"); | |
1701 | fclose(file); | |
1702 | return; | |
1703 | } | |
1704 | ||
1705 | fclose(file); | |
1706 | file = fopen(RESOLV_CONF, "w"); | |
1707 | if (file == NULL) | |
1708 | { | |
1709 | DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); | |
1710 | return; | |
1711 | } | |
1712 | ||
1713 | iterator = this->dns_servers->create_iterator(this->dns_servers, TRUE); | |
1714 | while (fetchline(&contents, &line)) | |
1715 | { | |
1716 | bool found = FALSE; | |
1717 | orig_line = line; | |
1718 | if (extract_token(&token, ' ', &line) && | |
1719 | strncasecmp(token.ptr, "nameserver", token.len) == 0) | |
1720 | { | |
1721 | if (!extract_token(&token, ' ', &line)) | |
1722 | { | |
1723 | token = line; | |
1724 | } | |
1725 | iterator->reset(iterator); | |
1726 | while (iterator->iterate(iterator, (void**)&ip)) | |
1727 | { | |
1728 | snprintf(string, sizeof(string), "%H", ip); | |
1729 | if (strlen(string) == token.len && | |
1730 | strncmp(token.ptr, string, token.len) == 0) | |
1731 | { | |
1732 | iterator->remove(iterator); | |
1733 | ip->destroy(ip); | |
1734 | found = TRUE; | |
1735 | break; | |
1736 | } | |
1737 | } | |
1738 | } | |
1739 | ||
1740 | if (!found) | |
1741 | { | |
1742 | /* write line untouched back to file */ | |
1743 | fwrite(orig_line.ptr, orig_line.len, 1, file); | |
1744 | fprintf(file, "\n"); | |
1745 | } | |
1746 | } | |
1747 | iterator->destroy(iterator); | |
1748 | fclose(file); | |
1749 | } | |
1750 | ||
1751 | /** | |
1752 | * Implementation of ike_sa_t.add_dns_server | |
1753 | */ | |
1754 | static void add_dns_server(private_ike_sa_t *this, host_t *dns) | |
1755 | { | |
1756 | FILE *file; | |
1757 | struct stat stats; | |
1758 | chunk_t contents; | |
1759 | ||
1760 | DBG1(DBG_IKE, "installing DNS server %H", dns); | |
1761 | ||
1762 | file = fopen(RESOLV_CONF, "a+"); | |
1763 | if (file == NULL || stat(RESOLV_CONF, &stats) != 0) | |
1764 | { | |
1765 | DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); | |
1766 | return; | |
1767 | } | |
1768 | ||
1769 | contents = chunk_alloca(stats.st_size); | |
1770 | ||
1771 | if (fread(contents.ptr, 1, contents.len, file) != contents.len) | |
1772 | { | |
1773 | DBG1(DBG_IKE, "unable to read DNS configuration file: %m"); | |
1774 | fclose(file); | |
1775 | return; | |
1776 | } | |
1777 | ||
1778 | fclose(file); | |
1779 | file = fopen(RESOLV_CONF, "w"); | |
1780 | if (file == NULL) | |
1781 | { | |
1782 | DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); | |
1783 | return; | |
1784 | } | |
1785 | ||
1786 | if (fprintf(file, "nameserver %H # added by strongSwan, assigned by %D\n", | |
1787 | dns, this->other_id) < 0) | |
1788 | { | |
1789 | DBG1(DBG_IKE, "unable to write DNS configuration: %m"); | |
2f89902d | 1790 | } |
c60c7694 MW |
1791 | else |
1792 | { | |
1793 | this->dns_servers->insert_last(this->dns_servers, dns->clone(dns)); | |
1794 | } | |
1795 | fwrite(contents.ptr, contents.len, 1, file); | |
1796 | ||
1797 | fclose(file); | |
1396815a MW |
1798 | } |
1799 | ||
60a6167a | 1800 | /** |
60356f33 | 1801 | * output handler in printf() |
60a6167a | 1802 | */ |
60356f33 MW |
1803 | static int print(FILE *stream, const struct printf_info *info, |
1804 | const void *const *args) | |
60a6167a | 1805 | { |
efa0ed68 | 1806 | int written = 0; |
c60c7694 | 1807 | bool reauth = FALSE; |
60356f33 | 1808 | private_ike_sa_t *this = *((private_ike_sa_t**)(args[0])); |
30b5b412 | 1809 | |
e0fe7651 | 1810 | if (this->peer_cfg) |
c60c7694 | 1811 | { |
e0fe7651 | 1812 | reauth = this->peer_cfg->use_reauth(this->peer_cfg); |
c60c7694 MW |
1813 | } |
1814 | ||
60356f33 MW |
1815 | if (this == NULL) |
1816 | { | |
1817 | return fprintf(stream, "(null)"); | |
1818 | } | |
4a5bba25 | 1819 | |
c60c7694 MW |
1820 | written = fprintf(stream, "%12s[%d]: %N, %H[%D]...%H[%D]", get_name(this), |
1821 | this->unique_id, ike_sa_state_names, this->state, | |
1822 | this->my_host, this->my_id, this->other_host, | |
1823 | this->other_id); | |
e0fe7651 | 1824 | if (this->time.rekey) |
efa0ed68 | 1825 | { |
e0fe7651 MW |
1826 | written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds", |
1827 | get_name(this), this->unique_id, this->ike_sa_id, | |
1828 | reauth ? "reauthentication" : "rekeying", | |
1829 | this->time.rekey - time(NULL)); | |
1830 | } | |
1831 | else | |
1832 | { | |
1833 | written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, rekeying disabled", | |
1834 | get_name(this), this->unique_id, this->ike_sa_id); | |
efa0ed68 | 1835 | } |
e0fe7651 | 1836 | |
efa0ed68 | 1837 | return written; |
60356f33 MW |
1838 | } |
1839 | ||
60356f33 MW |
1840 | /** |
1841 | * register printf() handlers | |
1842 | */ | |
1843 | static void __attribute__ ((constructor))print_register() | |
1844 | { | |
db7ef624 | 1845 | register_printf_function(PRINTF_IKE_SA, print, arginfo_ptr); |
60356f33 | 1846 | } |
8323a9c1 | 1847 | |
60356f33 MW |
1848 | /** |
1849 | * Implementation of ike_sa_t.destroy. | |
1850 | */ | |
1851 | static void destroy(private_ike_sa_t *this) | |
1852 | { | |
55bbff11 | 1853 | this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy)); |
8dfbe71b | 1854 | |
8dfbe71b MW |
1855 | DESTROY_IF(this->crypter_in); |
1856 | DESTROY_IF(this->crypter_out); | |
1857 | DESTROY_IF(this->signer_in); | |
1858 | DESTROY_IF(this->signer_out); | |
1859 | DESTROY_IF(this->prf); | |
1860 | DESTROY_IF(this->child_prf); | |
382b4817 MW |
1861 | DESTROY_IF(this->auth_verify); |
1862 | DESTROY_IF(this->auth_build); | |
8dfbe71b | 1863 | |
c60c7694 MW |
1864 | if (this->my_virtual_ip) |
1865 | { | |
1866 | charon->kernel_interface->del_ip(charon->kernel_interface, | |
1d51abb7 | 1867 | this->my_virtual_ip, this->my_host); |
c60c7694 MW |
1868 | this->my_virtual_ip->destroy(this->my_virtual_ip); |
1869 | } | |
1870 | DESTROY_IF(this->other_virtual_ip); | |
1871 | ||
1872 | remove_dns_servers(this); | |
1873 | this->dns_servers->destroy_offset(this->dns_servers, offsetof(host_t, destroy)); | |
1874 | ||
8dfbe71b MW |
1875 | DESTROY_IF(this->my_host); |
1876 | DESTROY_IF(this->other_host); | |
1877 | DESTROY_IF(this->my_id); | |
1878 | DESTROY_IF(this->other_id); | |
1879 | ||
e0fe7651 MW |
1880 | DESTROY_IF(this->ike_cfg); |
1881 | DESTROY_IF(this->peer_cfg); | |
c60c7694 | 1882 | |
87a217f9 | 1883 | this->ike_sa_id->destroy(this->ike_sa_id); |
c60c7694 | 1884 | this->task_manager->destroy(this->task_manager); |
5113680f | 1885 | free(this); |
7ba38761 JH |
1886 | } |
1887 | ||
1888 | /* | |
39b2903f | 1889 | * Described in header. |
7ba38761 JH |
1890 | */ |
1891 | ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) | |
1892 | { | |
5113680f | 1893 | private_ike_sa_t *this = malloc_thing(private_ike_sa_t); |
c60c7694 | 1894 | static u_int32_t unique_id = 0; |
8d77edde | 1895 | |
7ba38761 | 1896 | /* Public functions */ |
3dd3c5f3 MW |
1897 | this->public.get_state = (ike_sa_state_t(*)(ike_sa_t*)) get_state; |
1898 | this->public.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state; | |
8dfbe71b | 1899 | this->public.get_name = (char*(*)(ike_sa_t*))get_name; |
3dd3c5f3 | 1900 | this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; |
e0fe7651 MW |
1901 | this->public.initiate = (status_t(*)(ike_sa_t*,child_cfg_t*)) initiate; |
1902 | this->public.route = (status_t(*)(ike_sa_t*,child_cfg_t*)) route; | |
1903 | this->public.unroute = (status_t(*)(ike_sa_t*,child_cfg_t*)) unroute; | |
8dfbe71b | 1904 | this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire; |
e0fe7651 MW |
1905 | this->public.get_ike_cfg = (ike_cfg_t*(*)(ike_sa_t*))get_ike_cfg; |
1906 | this->public.set_ike_cfg = (void(*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg; | |
1907 | this->public.get_peer_cfg = (peer_cfg_t*(*)(ike_sa_t*))get_peer_cfg; | |
1908 | this->public.set_peer_cfg = (void(*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg; | |
3dd3c5f3 | 1909 | this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; |
8dfbe71b | 1910 | this->public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host; |
fe04e93a | 1911 | this->public.set_my_host = (void(*)(ike_sa_t*,host_t*)) set_my_host; |
8dfbe71b | 1912 | this->public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host; |
fe04e93a | 1913 | this->public.set_other_host = (void(*)(ike_sa_t*,host_t*)) set_other_host; |
8dfbe71b MW |
1914 | this->public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id; |
1915 | this->public.set_my_id = (void(*)(ike_sa_t*,identification_t*)) set_my_id; | |
1916 | this->public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id; | |
1917 | this->public.set_other_id = (void(*)(ike_sa_t*,identification_t*)) set_other_id; | |
c60c7694 | 1918 | this->public.retransmit = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit; |
3dd3c5f3 MW |
1919 | this->public.delete = (status_t(*)(ike_sa_t*))delete_; |
1920 | this->public.destroy = (void(*)(ike_sa_t*))destroy; | |
1921 | this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd; | |
1922 | this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive; | |
1923 | this->public.get_prf = (prf_t *(*) (ike_sa_t *)) get_prf; | |
1924 | this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf; | |
382b4817 MW |
1925 | this->public.get_auth_verify = (prf_t *(*) (ike_sa_t *)) get_auth_verify; |
1926 | this->public.get_auth_build = (prf_t *(*) (ike_sa_t *)) get_auth_build; | |
c60c7694 | 1927 | this->public.derive_keys = (status_t (*) (ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys; |
698d7749 MW |
1928 | this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa; |
1929 | this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa; | |
3183006d | 1930 | this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator; |
698d7749 MW |
1931 | this->public.rekey_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa; |
1932 | this->public.delete_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa; | |
1933 | this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa; | |
3dd3c5f3 MW |
1934 | this->public.enable_natt = (void(*)(ike_sa_t*, bool)) enable_natt; |
1935 | this->public.is_natt_enabled = (bool(*)(ike_sa_t*)) is_natt_enabled; | |
fe04e93a | 1936 | this->public.rekey = (status_t(*)(ike_sa_t*))rekey; |
c60c7694 | 1937 | this->public.reestablish = (void(*)(ike_sa_t*))reestablish; |
e23a59f6 | 1938 | this->public.inherit = (status_t(*)(ike_sa_t*,ike_sa_t*))inherit; |
c60c7694 MW |
1939 | this->public.generate_message = (status_t(*)(ike_sa_t*,message_t*,packet_t**))generate_message; |
1940 | this->public.reset = (void(*)(ike_sa_t*))reset; | |
1941 | this->public.get_unique_id = (u_int32_t(*)(ike_sa_t*))get_unique_id; | |
1942 | this->public.set_virtual_ip = (void(*)(ike_sa_t*,bool,host_t*))set_virtual_ip; | |
1943 | this->public.get_virtual_ip = (host_t*(*)(ike_sa_t*,bool))get_virtual_ip; | |
1944 | this->public.add_dns_server = (void(*)(ike_sa_t*,host_t*))add_dns_server; | |
3dd3c5f3 | 1945 | |
7ba38761 | 1946 | /* initialize private fields */ |
d048df5c | 1947 | this->ike_sa_id = ike_sa_id->clone(ike_sa_id); |
7ba38761 | 1948 | this->child_sas = linked_list_create(); |
c60c7694 MW |
1949 | this->my_host = host_create_any(AF_INET); |
1950 | this->other_host = host_create_any(AF_INET); | |
db7ef624 MW |
1951 | this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty); |
1952 | this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty); | |
3dd3c5f3 MW |
1953 | this->crypter_in = NULL; |
1954 | this->crypter_out = NULL; | |
1955 | this->signer_in = NULL; | |
1956 | this->signer_out = NULL; | |
b4e3d1dd | 1957 | this->prf = NULL; |
382b4817 MW |
1958 | this->auth_verify = NULL; |
1959 | this->auth_build = NULL; | |
971218c3 | 1960 | this->child_prf = NULL; |
1396815a MW |
1961 | this->nat_here = FALSE; |
1962 | this->nat_there = FALSE; | |
bcb95ced | 1963 | this->state = IKE_CREATED; |
fe04e93a MW |
1964 | this->time.inbound = this->time.outbound = time(NULL); |
1965 | this->time.established = 0; | |
1966 | this->time.rekey = 0; | |
1967 | this->time.delete = 0; | |
e0fe7651 MW |
1968 | this->ike_cfg = NULL; |
1969 | this->peer_cfg = NULL; | |
c60c7694 MW |
1970 | this->task_manager = task_manager_create(&this->public); |
1971 | this->unique_id = ++unique_id; | |
1972 | this->my_virtual_ip = NULL; | |
1973 | this->other_virtual_ip = NULL; | |
1974 | this->dns_servers = linked_list_create(); | |
fdb9b2bd | 1975 | this->keyingtry = 0; |
3dd3c5f3 MW |
1976 | |
1977 | return &this->public; | |
7ba38761 | 1978 | } |