]>
Commit | Line | Data |
---|---|---|
2b04aa46 | 1 | /* |
8ab33628 | 2 | * Copyright (C) 2012-2019 Tobias Brunner |
1b671669 | 3 | * HSR Hochschule fuer Technik Rapperswil |
47b448b8 | 4 | * |
2b04aa46 MW |
5 | * Copyright (C) 2011 Martin Willi |
6 | * Copyright (C) 2011 revosec AG | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | * for more details. | |
17 | */ | |
18 | ||
0ff8d20a VR |
19 | /* |
20 | * Copyright (C) 2012 Volker RĂ¼melin | |
21 | * | |
22 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
23 | * of this software and associated documentation files (the "Software"), to deal | |
24 | * in the Software without restriction, including without limitation the rights | |
25 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
26 | * copies of the Software, and to permit persons to whom the Software is | |
27 | * furnished to do so, subject to the following conditions: | |
28 | * | |
29 | * The above copyright notice and this permission notice shall be included in | |
30 | * all copies or substantial portions of the Software. | |
31 | * | |
32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
33 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
34 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
35 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
36 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
37 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
38 | * THE SOFTWARE. | |
39 | */ | |
40 | ||
2b04aa46 MW |
41 | #include "quick_mode.h" |
42 | ||
43 | #include <string.h> | |
44 | ||
45 | #include <daemon.h> | |
15a682f4 | 46 | #include <sa/ikev1/keymat_v1.h> |
21b7db99 MW |
47 | #include <encoding/payloads/sa_payload.h> |
48 | #include <encoding/payloads/nonce_payload.h> | |
5adf855e | 49 | #include <encoding/payloads/ke_payload.h> |
21b7db99 | 50 | #include <encoding/payloads/id_payload.h> |
07abb470 | 51 | #include <encoding/payloads/payload.h> |
15a682f4 MW |
52 | #include <sa/ikev1/tasks/informational.h> |
53 | #include <sa/ikev1/tasks/quick_delete.h> | |
c60246a6 | 54 | #include <processing/jobs/inactivity_job.h> |
2b04aa46 MW |
55 | |
56 | typedef struct private_quick_mode_t private_quick_mode_t; | |
57 | ||
58 | /** | |
59 | * Private members of a quick_mode_t task. | |
60 | */ | |
61 | struct private_quick_mode_t { | |
62 | ||
63 | /** | |
64 | * Public methods and task_t interface. | |
65 | */ | |
66 | quick_mode_t public; | |
67 | ||
68 | /** | |
69 | * Assigned IKE_SA. | |
70 | */ | |
71 | ike_sa_t *ike_sa; | |
72 | ||
5351d63c MW |
73 | /** |
74 | * TRUE if we are initiating quick mode | |
75 | */ | |
76 | bool initiator; | |
77 | ||
2b04aa46 MW |
78 | /** |
79 | * Traffic selector of initiator | |
80 | */ | |
81 | traffic_selector_t *tsi; | |
82 | ||
83 | /** | |
84 | * Traffic selector of responder | |
85 | */ | |
86 | traffic_selector_t *tsr; | |
87 | ||
88 | /** | |
89 | * Initiators nonce | |
90 | */ | |
91 | chunk_t nonce_i; | |
92 | ||
93 | /** | |
94 | * Responder nonce | |
95 | */ | |
96 | chunk_t nonce_r; | |
97 | ||
5351d63c MW |
98 | /** |
99 | * Initiators ESP SPI | |
100 | */ | |
b12c53ce | 101 | uint32_t spi_i; |
5351d63c MW |
102 | |
103 | /** | |
104 | * Responder ESP SPI | |
105 | */ | |
b12c53ce | 106 | uint32_t spi_r; |
5351d63c | 107 | |
47b448b8 TB |
108 | /** |
109 | * Initiators IPComp CPI | |
110 | */ | |
b12c53ce | 111 | uint16_t cpi_i; |
47b448b8 TB |
112 | |
113 | /** | |
114 | * Responders IPComp CPI | |
115 | */ | |
b12c53ce | 116 | uint16_t cpi_r; |
47b448b8 | 117 | |
2b04aa46 MW |
118 | /** |
119 | * selected CHILD_SA proposal | |
120 | */ | |
121 | proposal_t *proposal; | |
122 | ||
123 | /** | |
124 | * Config of CHILD_SA to establish | |
125 | */ | |
126 | child_cfg_t *config; | |
127 | ||
128 | /** | |
129 | * CHILD_SA we are about to establish | |
130 | */ | |
131 | child_sa_t *child_sa; | |
132 | ||
5351d63c MW |
133 | /** |
134 | * IKEv1 keymat | |
135 | */ | |
136 | keymat_v1_t *keymat; | |
137 | ||
5adf855e MW |
138 | /** |
139 | * DH exchange, when PFS is in use | |
140 | */ | |
141 | diffie_hellman_t *dh; | |
142 | ||
cd0017d4 MW |
143 | /** |
144 | * Negotiated lifetime of new SA | |
145 | */ | |
b12c53ce | 146 | uint32_t lifetime; |
cd0017d4 MW |
147 | |
148 | /** | |
9e01d7ca | 149 | * Negotiated lifebytes of new SA |
cd0017d4 | 150 | */ |
b12c53ce | 151 | uint64_t lifebytes; |
cd0017d4 | 152 | |
14dc7941 | 153 | /** |
fafa7698 | 154 | * Data collected to create the CHILD_SA |
14dc7941 | 155 | */ |
fafa7698 | 156 | child_sa_create_t child; |
85b23888 | 157 | |
669d8bde MW |
158 | /** |
159 | * SPI of SA we rekey | |
160 | */ | |
b12c53ce | 161 | uint32_t rekey; |
669d8bde | 162 | |
2f3c08d2 TB |
163 | /** |
164 | * Delete old child after successful rekey | |
165 | */ | |
166 | bool delete; | |
167 | ||
90731f38 MW |
168 | /** |
169 | * Negotiated mode, tunnel or transport | |
170 | */ | |
171 | ipsec_mode_t mode; | |
172 | ||
908fe163 MW |
173 | /* |
174 | * SA protocol (ESP|AH) negotiated | |
175 | */ | |
176 | protocol_id_t proto; | |
177 | ||
4de361d9 TB |
178 | /** |
179 | * Message ID of handled quick mode exchange | |
180 | */ | |
b12c53ce | 181 | uint32_t mid; |
4de361d9 | 182 | |
2b04aa46 MW |
183 | /** states of quick mode */ |
184 | enum { | |
185 | QM_INIT, | |
21b7db99 | 186 | QM_NEGOTIATED, |
2b04aa46 MW |
187 | } state; |
188 | }; | |
189 | ||
c60246a6 MW |
190 | /** |
191 | * Schedule inactivity timeout for CHILD_SA with reqid, if enabled | |
192 | */ | |
193 | static void schedule_inactivity_timeout(private_quick_mode_t *this) | |
194 | { | |
b12c53ce | 195 | uint32_t timeout; |
c60246a6 MW |
196 | bool close_ike; |
197 | ||
198 | timeout = this->config->get_inactivity(this->config); | |
199 | if (timeout) | |
200 | { | |
201 | close_ike = lib->settings->get_bool(lib->settings, | |
d223fe80 | 202 | "%s.inactivity_close_ike", FALSE, lib->ns); |
c60246a6 | 203 | lib->scheduler->schedule_job(lib->scheduler, (job_t*) |
85ace154 MW |
204 | inactivity_job_create(this->child_sa->get_unique_id(this->child_sa), |
205 | timeout, close_ike), timeout); | |
c60246a6 MW |
206 | } |
207 | } | |
208 | ||
c4acf375 MW |
209 | /** |
210 | * Check if we have a an address pool configured | |
211 | */ | |
212 | static bool have_pool(ike_sa_t *ike_sa) | |
213 | { | |
214 | enumerator_t *enumerator; | |
215 | peer_cfg_t *peer_cfg; | |
216 | char *pool; | |
217 | bool found = FALSE; | |
218 | ||
219 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); | |
220 | if (peer_cfg) | |
221 | { | |
222 | enumerator = peer_cfg->create_pool_enumerator(peer_cfg); | |
223 | if (enumerator->enumerate(enumerator, &pool)) | |
224 | { | |
225 | found = TRUE; | |
226 | } | |
227 | enumerator->destroy(enumerator); | |
228 | } | |
229 | return found; | |
230 | } | |
231 | ||
232 | /** | |
7ee37114 | 233 | * Get hosts to use for dynamic traffic selectors |
c4acf375 | 234 | */ |
7ee37114 | 235 | static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local) |
c4acf375 MW |
236 | { |
237 | enumerator_t *enumerator; | |
7ee37114 | 238 | linked_list_t *list; |
c4acf375 MW |
239 | host_t *host; |
240 | ||
7ee37114 | 241 | list = linked_list_create(); |
c4acf375 | 242 | enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local); |
7ee37114 | 243 | while (enumerator->enumerate(enumerator, &host)) |
c4acf375 | 244 | { |
7ee37114 MW |
245 | list->insert_last(list, host); |
246 | } | |
247 | enumerator->destroy(enumerator); | |
248 | ||
249 | if (list->get_count(list) == 0) | |
250 | { /* no virtual IPs assigned */ | |
c4acf375 MW |
251 | if (local) |
252 | { | |
253 | host = ike_sa->get_my_host(ike_sa); | |
7ee37114 | 254 | list->insert_last(list, host); |
c4acf375 | 255 | } |
7ee37114 MW |
256 | else if (!have_pool(ike_sa)) |
257 | { /* use host only if we don't have a pool configured */ | |
258 | host = ike_sa->get_other_host(ike_sa); | |
259 | list->insert_last(list, host); | |
c4acf375 MW |
260 | } |
261 | } | |
7ee37114 | 262 | return list; |
c4acf375 MW |
263 | } |
264 | ||
5351d63c MW |
265 | /** |
266 | * Install negotiated CHILD_SA | |
267 | */ | |
268 | static bool install(private_quick_mode_t *this) | |
269 | { | |
270 | status_t status, status_i, status_o; | |
271 | chunk_t encr_i, encr_r, integ_i, integ_r; | |
553bb787 | 272 | linked_list_t *tsi, *tsr, *my_ts, *other_ts; |
669d8bde | 273 | child_sa_t *old = NULL; |
5351d63c MW |
274 | |
275 | this->child_sa->set_proposal(this->child_sa, this->proposal); | |
276 | this->child_sa->set_state(this->child_sa, CHILD_INSTALLING); | |
90731f38 | 277 | this->child_sa->set_mode(this->child_sa, this->mode); |
47b448b8 TB |
278 | |
279 | if (this->cpi_i && this->cpi_r) | |
280 | { /* DEFLATE is the only transform we currently support */ | |
281 | this->child_sa->set_ipcomp(this->child_sa, IPCOMP_DEFLATE); | |
282 | } | |
283 | else | |
284 | { | |
285 | this->cpi_i = this->cpi_r = 0; | |
286 | } | |
287 | ||
5351d63c MW |
288 | this->child_sa->set_protocol(this->child_sa, |
289 | this->proposal->get_protocol(this->proposal)); | |
290 | ||
291 | status_i = status_o = FAILED; | |
292 | encr_i = encr_r = integ_i = integ_r = chunk_empty; | |
abdb82fc MW |
293 | tsi = linked_list_create_with_items(this->tsi->clone(this->tsi), NULL); |
294 | tsr = linked_list_create_with_items(this->tsr->clone(this->tsr), NULL); | |
696fa8e0 MW |
295 | if (this->initiator) |
296 | { | |
297 | charon->bus->narrow(charon->bus, this->child_sa, | |
298 | NARROW_INITIATOR_POST_AUTH, tsi, tsr); | |
299 | } | |
300 | else | |
301 | { | |
302 | charon->bus->narrow(charon->bus, this->child_sa, | |
f942588f | 303 | NARROW_RESPONDER_POST, tsr, tsi); |
696fa8e0 MW |
304 | } |
305 | if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0) | |
306 | { | |
307 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
308 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
309 | DBG1(DBG_IKE, "no acceptable traffic selectors found"); | |
310 | return FALSE; | |
311 | } | |
312 | ||
4989aba8 TB |
313 | if (this->initiator) |
314 | { | |
315 | this->child_sa->set_policies(this->child_sa, tsi, tsr); | |
316 | } | |
317 | else | |
318 | { | |
319 | this->child_sa->set_policies(this->child_sa, tsr, tsi); | |
320 | } | |
321 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
322 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
323 | ||
5adf855e | 324 | if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh, |
a7910b1c MW |
325 | this->spi_i, this->spi_r, this->nonce_i, this->nonce_r, |
326 | &encr_i, &integ_i, &encr_r, &integ_r)) | |
5351d63c MW |
327 | { |
328 | if (this->initiator) | |
329 | { | |
a8c94544 MW |
330 | status_i = this->child_sa->install(this->child_sa, |
331 | encr_r, integ_r, this->spi_i, this->cpi_i, | |
4989aba8 | 332 | this->initiator, TRUE, FALSE); |
a8c94544 MW |
333 | status_o = this->child_sa->install(this->child_sa, |
334 | encr_i, integ_i, this->spi_r, this->cpi_r, | |
4989aba8 | 335 | this->initiator, FALSE, FALSE); |
5351d63c MW |
336 | } |
337 | else | |
338 | { | |
a8c94544 MW |
339 | status_i = this->child_sa->install(this->child_sa, |
340 | encr_i, integ_i, this->spi_r, this->cpi_r, | |
4989aba8 | 341 | this->initiator, TRUE, FALSE); |
a8c94544 MW |
342 | status_o = this->child_sa->install(this->child_sa, |
343 | encr_r, integ_r, this->spi_i, this->cpi_i, | |
4989aba8 | 344 | this->initiator, FALSE, FALSE); |
5351d63c MW |
345 | } |
346 | } | |
5351d63c MW |
347 | |
348 | if (status_i != SUCCESS || status_o != SUCCESS) | |
349 | { | |
350 | DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel", | |
351 | (status_i != SUCCESS) ? "inbound " : "", | |
352 | (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "", | |
353 | (status_o != SUCCESS) ? "outbound " : ""); | |
c4a286c8 | 354 | status = FAILED; |
5351d63c MW |
355 | } |
356 | else | |
357 | { | |
4989aba8 TB |
358 | status = this->child_sa->install_policies(this->child_sa); |
359 | ||
c4a286c8 TB |
360 | if (status != SUCCESS) |
361 | { | |
362 | DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); | |
363 | } | |
364 | else | |
365 | { | |
366 | charon->bus->child_derived_keys(charon->bus, this->child_sa, | |
367 | this->initiator, encr_i, encr_r, | |
368 | integ_i, integ_r); | |
369 | } | |
5351d63c | 370 | } |
c4a286c8 TB |
371 | chunk_clear(&integ_i); |
372 | chunk_clear(&integ_r); | |
373 | chunk_clear(&encr_i); | |
374 | chunk_clear(&encr_r); | |
375 | ||
5351d63c MW |
376 | if (status != SUCCESS) |
377 | { | |
5351d63c MW |
378 | return FALSE; |
379 | } | |
380 | ||
381 | charon->bus->child_keys(charon->bus, this->child_sa, this->initiator, | |
5adf855e | 382 | this->dh, this->nonce_i, this->nonce_r); |
5351d63c | 383 | |
553bb787 MW |
384 | my_ts = linked_list_create_from_enumerator( |
385 | this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); | |
386 | other_ts = linked_list_create_from_enumerator( | |
387 | this->child_sa->create_ts_enumerator(this->child_sa, FALSE)); | |
388 | ||
5351d63c | 389 | DBG0(DBG_IKE, "CHILD_SA %s{%d} established " |
ebeb8c87 | 390 | "with SPIs %.8x_i %.8x_o and TS %#R === %#R", |
5351d63c | 391 | this->child_sa->get_name(this->child_sa), |
246c969d | 392 | this->child_sa->get_unique_id(this->child_sa), |
5351d63c | 393 | ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), |
553bb787 MW |
394 | ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); |
395 | ||
396 | my_ts->destroy(my_ts); | |
397 | other_ts->destroy(other_ts); | |
5351d63c | 398 | |
a0cde769 TB |
399 | this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); |
400 | this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); | |
401 | ||
669d8bde MW |
402 | if (this->rekey) |
403 | { | |
404 | old = this->ike_sa->get_child_sa(this->ike_sa, | |
405 | this->proposal->get_protocol(this->proposal), | |
406 | this->rekey, TRUE); | |
407 | } | |
408 | if (old) | |
409 | { | |
410 | charon->bus->child_rekey(charon->bus, old, this->child_sa); | |
2f3c08d2 TB |
411 | /* rekeyed CHILD_SAs stay installed until they expire or are deleted |
412 | * by the other peer */ | |
70728eb1 | 413 | old->set_state(old, CHILD_REKEYED); |
2f3c08d2 TB |
414 | /* as initiator we delete the CHILD_SA if configured to do so */ |
415 | if (this->initiator && this->delete) | |
416 | { | |
417 | this->ike_sa->queue_task(this->ike_sa, | |
418 | (task_t*)quick_delete_create(this->ike_sa, | |
419 | this->proposal->get_protocol(this->proposal), | |
420 | this->rekey, TRUE, FALSE)); | |
421 | } | |
669d8bde MW |
422 | } |
423 | else | |
424 | { | |
425 | charon->bus->child_updown(charon->bus, this->child_sa, TRUE); | |
426 | } | |
85ace154 | 427 | schedule_inactivity_timeout(this); |
5351d63c | 428 | this->child_sa = NULL; |
5351d63c MW |
429 | return TRUE; |
430 | } | |
431 | ||
818330aa MW |
432 | /** |
433 | * Generate and add NONCE | |
434 | */ | |
435 | static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce, | |
436 | message_t *message) | |
437 | { | |
438 | nonce_payload_t *nonce_payload; | |
afaf1bdf | 439 | nonce_gen_t *nonceg; |
818330aa | 440 | |
afaf1bdf AKR |
441 | nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat); |
442 | if (!nonceg) | |
818330aa | 443 | { |
afaf1bdf | 444 | DBG1(DBG_IKE, "no nonce generator found to create nonce"); |
818330aa MW |
445 | return FALSE; |
446 | } | |
605985d1 RB |
447 | if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce)) |
448 | { | |
449 | DBG1(DBG_IKE, "nonce allocation failed"); | |
450 | nonceg->destroy(nonceg); | |
451 | return FALSE; | |
452 | } | |
afaf1bdf | 453 | nonceg->destroy(nonceg); |
818330aa | 454 | |
3ecfc83c | 455 | nonce_payload = nonce_payload_create(PLV1_NONCE); |
818330aa MW |
456 | nonce_payload->set_nonce(nonce_payload, *nonce); |
457 | message->add_payload(message, &nonce_payload->payload_interface); | |
458 | ||
459 | return TRUE; | |
460 | } | |
461 | ||
462 | /** | |
463 | * Extract nonce from NONCE payload | |
464 | */ | |
465 | static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce, | |
466 | message_t *message) | |
467 | { | |
468 | nonce_payload_t *nonce_payload; | |
469 | ||
3ecfc83c | 470 | nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE); |
818330aa MW |
471 | if (!nonce_payload) |
472 | { | |
473 | DBG1(DBG_IKE, "NONCE payload missing in message"); | |
474 | return FALSE; | |
475 | } | |
476 | *nonce = nonce_payload->get_nonce(nonce_payload); | |
477 | ||
478 | return TRUE; | |
479 | } | |
480 | ||
5adf855e MW |
481 | /** |
482 | * Add KE payload to message | |
483 | */ | |
520d58e0 | 484 | static bool add_ke(private_quick_mode_t *this, message_t *message) |
5adf855e MW |
485 | { |
486 | ke_payload_t *ke_payload; | |
487 | ||
520d58e0 MW |
488 | ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, |
489 | this->dh); | |
490 | if (!ke_payload) | |
491 | { | |
492 | DBG1(DBG_IKE, "creating KE payload failed"); | |
493 | return FALSE; | |
494 | } | |
5adf855e | 495 | message->add_payload(message, &ke_payload->payload_interface); |
520d58e0 | 496 | return TRUE; |
5adf855e MW |
497 | } |
498 | ||
499 | /** | |
500 | * Get DH value from a KE payload | |
501 | */ | |
502 | static bool get_ke(private_quick_mode_t *this, message_t *message) | |
503 | { | |
504 | ke_payload_t *ke_payload; | |
505 | ||
3ecfc83c | 506 | ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE); |
5adf855e MW |
507 | if (!ke_payload) |
508 | { | |
509 | DBG1(DBG_IKE, "KE payload missing"); | |
510 | return FALSE; | |
511 | } | |
66147ef6 | 512 | if (!this->dh->set_other_public_value(this->dh, |
a777155f MW |
513 | ke_payload->get_key_exchange_data(ke_payload))) |
514 | { | |
515 | DBG1(DBG_IKE, "unable to apply received KE value"); | |
516 | return FALSE; | |
517 | } | |
5adf855e MW |
518 | return TRUE; |
519 | } | |
520 | ||
c4b8539f MW |
521 | /** |
522 | * Select a traffic selector from configuration | |
523 | */ | |
36431795 MW |
524 | static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local, |
525 | linked_list_t *supplied) | |
c4b8539f MW |
526 | { |
527 | traffic_selector_t *ts; | |
7ee37114 | 528 | linked_list_t *list, *hosts; |
c4b8539f | 529 | |
7ee37114 MW |
530 | hosts = get_dynamic_hosts(this->ike_sa, local); |
531 | list = this->config->get_traffic_selectors(this->config, | |
84cdfbc9 | 532 | local, supplied, hosts, TRUE); |
7ee37114 | 533 | hosts->destroy(hosts); |
c4b8539f MW |
534 | if (list->get_first(list, (void**)&ts) == SUCCESS) |
535 | { | |
c4b8539f MW |
536 | ts = ts->clone(ts); |
537 | } | |
538 | else | |
539 | { | |
540 | DBG1(DBG_IKE, "%s traffic selector missing in configuration", | |
cdc42256 | 541 | local ? "local" : "remote"); |
c4b8539f MW |
542 | ts = NULL; |
543 | } | |
544 | list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); | |
545 | return ts; | |
546 | } | |
547 | ||
548 | /** | |
549 | * Add selected traffic selectors to message | |
550 | */ | |
9cc38c8e | 551 | static void add_ts(private_quick_mode_t *this, message_t *message) |
c4b8539f MW |
552 | { |
553 | id_payload_t *id_payload; | |
554 | ||
77ccff82 TB |
555 | id_payload = id_payload_create_from_ts(this->tsi); |
556 | message->add_payload(message, &id_payload->payload_interface); | |
557 | id_payload = id_payload_create_from_ts(this->tsr); | |
558 | message->add_payload(message, &id_payload->payload_interface); | |
c4b8539f MW |
559 | } |
560 | ||
561 | /** | |
562 | * Get traffic selectors from received message | |
563 | */ | |
9cc38c8e | 564 | static bool get_ts(private_quick_mode_t *this, message_t *message) |
c4b8539f MW |
565 | { |
566 | traffic_selector_t *tsi = NULL, *tsr = NULL; | |
567 | enumerator_t *enumerator; | |
568 | id_payload_t *id_payload; | |
569 | payload_t *payload; | |
570 | host_t *hsi, *hsr; | |
571 | bool first = TRUE; | |
572 | ||
573 | enumerator = message->create_payload_enumerator(message); | |
574 | while (enumerator->enumerate(enumerator, &payload)) | |
575 | { | |
3ecfc83c | 576 | if (payload->get_type(payload) == PLV1_ID) |
c4b8539f MW |
577 | { |
578 | id_payload = (id_payload_t*)payload; | |
579 | ||
580 | if (first) | |
581 | { | |
582 | tsi = id_payload->get_ts(id_payload); | |
583 | first = FALSE; | |
584 | } | |
585 | else | |
586 | { | |
587 | tsr = id_payload->get_ts(id_payload); | |
588 | break; | |
589 | } | |
590 | } | |
591 | } | |
592 | enumerator->destroy(enumerator); | |
593 | ||
594 | /* create host2host selectors if ID payloads missing */ | |
9cc38c8e | 595 | if (this->initiator) |
c4b8539f MW |
596 | { |
597 | hsi = this->ike_sa->get_my_host(this->ike_sa); | |
598 | hsr = this->ike_sa->get_other_host(this->ike_sa); | |
599 | } | |
600 | else | |
601 | { | |
602 | hsr = this->ike_sa->get_my_host(this->ike_sa); | |
603 | hsi = this->ike_sa->get_other_host(this->ike_sa); | |
604 | } | |
605 | if (!tsi) | |
606 | { | |
607 | tsi = traffic_selector_create_from_subnet(hsi->clone(hsi), | |
a1db77de | 608 | hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535); |
c4b8539f MW |
609 | } |
610 | if (!tsr) | |
611 | { | |
612 | tsr = traffic_selector_create_from_subnet(hsr->clone(hsr), | |
a1db77de | 613 | hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535); |
c4b8539f | 614 | } |
fafa7698 | 615 | if (this->mode == MODE_TRANSPORT && this->child.encap && |
a889cfe5 TB |
616 | (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr))) |
617 | { /* change TS in case of a NAT in transport mode */ | |
618 | DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT", | |
619 | tsi, tsr); | |
620 | tsi->set_address(tsi, hsi); | |
621 | tsr->set_address(tsr, hsr); | |
622 | } | |
623 | ||
9cc38c8e | 624 | if (this->initiator) |
c4b8539f | 625 | { |
9d9042d6 MW |
626 | traffic_selector_t *tsisub, *tsrsub; |
627 | ||
29906717 | 628 | /* check if peer selection is valid */ |
9d9042d6 MW |
629 | tsisub = this->tsi->get_subset(this->tsi, tsi); |
630 | tsrsub = this->tsr->get_subset(this->tsr, tsr); | |
631 | if (!tsisub || !tsrsub) | |
c4b8539f | 632 | { |
29906717 | 633 | DBG1(DBG_IKE, "peer selected invalid traffic selectors: " |
c4b8539f | 634 | "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr); |
9d9042d6 MW |
635 | DESTROY_IF(tsisub); |
636 | DESTROY_IF(tsrsub); | |
c4b8539f MW |
637 | tsi->destroy(tsi); |
638 | tsr->destroy(tsr); | |
639 | return FALSE; | |
640 | } | |
9d9042d6 MW |
641 | tsi->destroy(tsi); |
642 | tsr->destroy(tsr); | |
c4b8539f MW |
643 | this->tsi->destroy(this->tsi); |
644 | this->tsr->destroy(this->tsr); | |
9d9042d6 MW |
645 | this->tsi = tsisub; |
646 | this->tsr = tsrsub; | |
c4b8539f MW |
647 | } |
648 | else | |
649 | { | |
650 | this->tsi = tsi; | |
651 | this->tsr = tsr; | |
652 | } | |
653 | return TRUE; | |
654 | } | |
655 | ||
0ff8d20a VR |
656 | /** |
657 | * Get encap | |
658 | */ | |
659 | static encap_t get_encap(ike_sa_t* ike_sa, bool udp) | |
660 | { | |
661 | if (!udp) | |
662 | { | |
663 | return ENCAP_NONE; | |
664 | } | |
665 | if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03)) | |
666 | { | |
667 | return ENCAP_UDP_DRAFT_00_03; | |
668 | } | |
669 | return ENCAP_UDP; | |
670 | } | |
671 | ||
672 | /** | |
673 | * Get NAT-OA payload type (RFC 3947 or RFC 3947 drafts). | |
674 | */ | |
675 | static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa) | |
676 | { | |
677 | if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03)) | |
678 | { | |
3ecfc83c | 679 | return PLV1_NAT_OA_DRAFT_00_03; |
0ff8d20a | 680 | } |
3ecfc83c | 681 | return PLV1_NAT_OA; |
0ff8d20a VR |
682 | } |
683 | ||
3bf0be6b TB |
684 | /** |
685 | * Add NAT-OA payloads | |
686 | */ | |
687 | static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message) | |
688 | { | |
689 | identification_t *id; | |
690 | id_payload_t *nat_oa; | |
d8f0d9c2 | 691 | host_t *init, *resp; |
0ff8d20a | 692 | payload_type_t nat_oa_payload_type; |
3bf0be6b | 693 | |
d8f0d9c2 TB |
694 | if (this->initiator) |
695 | { | |
696 | init = message->get_source(message); | |
697 | resp = message->get_destination(message); | |
698 | } | |
699 | else | |
700 | { | |
701 | init = message->get_destination(message); | |
702 | resp = message->get_source(message); | |
703 | } | |
3bf0be6b | 704 | |
0ff8d20a VR |
705 | nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa); |
706 | ||
3bf0be6b | 707 | /* first NAT-OA is the initiator's address */ |
d8f0d9c2 | 708 | id = identification_create_from_sockaddr(init->get_sockaddr(init)); |
0ff8d20a | 709 | nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id); |
3bf0be6b TB |
710 | message->add_payload(message, (payload_t*)nat_oa); |
711 | id->destroy(id); | |
712 | ||
713 | /* second NAT-OA is that of the responder */ | |
d8f0d9c2 | 714 | id = identification_create_from_sockaddr(resp->get_sockaddr(resp)); |
0ff8d20a | 715 | nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id); |
3bf0be6b TB |
716 | message->add_payload(message, (payload_t*)nat_oa); |
717 | id->destroy(id); | |
718 | } | |
719 | ||
cd0017d4 MW |
720 | /** |
721 | * Look up lifetimes | |
722 | */ | |
723 | static void get_lifetimes(private_quick_mode_t *this) | |
724 | { | |
725 | lifetime_cfg_t *lft; | |
726 | ||
b1df6312 | 727 | lft = this->config->get_lifetime(this->config, TRUE); |
cd0017d4 MW |
728 | if (lft->time.life) |
729 | { | |
730 | this->lifetime = lft->time.life; | |
731 | } | |
9e01d7ca | 732 | if (lft->bytes.life) |
cd0017d4 MW |
733 | { |
734 | this->lifebytes = lft->bytes.life; | |
735 | } | |
736 | free(lft); | |
737 | } | |
738 | ||
739 | /** | |
740 | * Check and apply lifetimes | |
741 | */ | |
742 | static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload) | |
743 | { | |
b12c53ce AS |
744 | uint32_t lifetime; |
745 | uint64_t lifebytes; | |
cd0017d4 | 746 | |
e0dd36c9 TB |
747 | lifetime = sa_payload->get_lifetime(sa_payload, this->proposal); |
748 | lifebytes = sa_payload->get_lifebytes(sa_payload, this->proposal); | |
cd0017d4 MW |
749 | if (this->lifetime != lifetime) |
750 | { | |
31bd5c8c | 751 | DBG1(DBG_IKE, "received %us lifetime, configured %us", |
cd0017d4 | 752 | lifetime, this->lifetime); |
31bd5c8c | 753 | this->lifetime = lifetime; |
cd0017d4 MW |
754 | } |
755 | if (this->lifebytes != lifebytes) | |
756 | { | |
31bd5c8c | 757 | DBG1(DBG_IKE, "received %llu lifebytes, configured %llu", |
cd0017d4 | 758 | lifebytes, this->lifebytes); |
31bd5c8c | 759 | this->lifebytes = lifebytes; |
cd0017d4 MW |
760 | } |
761 | } | |
762 | ||
e7ae90c1 MW |
763 | /** |
764 | * Set the task ready to build notify error message | |
765 | */ | |
766 | static status_t send_notify(private_quick_mode_t *this, notify_type_t type) | |
5c6abd28 CO |
767 | { |
768 | notify_payload_t *notify; | |
769 | ||
3ecfc83c | 770 | notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY, |
908fe163 | 771 | this->proto, type); |
5c6abd28 CO |
772 | notify->set_spi(notify, this->spi_i); |
773 | ||
e7ae90c1 | 774 | this->ike_sa->queue_task(this->ike_sa, |
2ddd45c9 | 775 | (task_t*)informational_create(this->ike_sa, notify)); |
e7ae90c1 | 776 | /* cancel all active/passive tasks in favour of informational */ |
7ce504e1 MW |
777 | this->ike_sa->flush_queue(this->ike_sa, |
778 | this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE); | |
e7ae90c1 | 779 | return ALREADY_DONE; |
5c6abd28 CO |
780 | } |
781 | ||
7d938be9 TE |
782 | /** |
783 | * Prepare a list of proposals from child_config containing only the specified | |
784 | * DH group, unless it is set to MODP_NONE. | |
785 | */ | |
786 | static linked_list_t *get_proposals(private_quick_mode_t *this, | |
787 | diffie_hellman_group_t group) | |
788 | { | |
789 | linked_list_t *list; | |
790 | proposal_t *proposal; | |
791 | enumerator_t *enumerator; | |
792 | ||
793 | list = this->config->get_proposals(this->config, FALSE); | |
794 | enumerator = list->create_enumerator(list); | |
795 | while (enumerator->enumerate(enumerator, &proposal)) | |
796 | { | |
797 | if (group != MODP_NONE) | |
798 | { | |
799 | if (!proposal->has_dh_group(proposal, group)) | |
800 | { | |
801 | list->remove_at(list, enumerator); | |
802 | proposal->destroy(proposal); | |
803 | continue; | |
804 | } | |
3187293e | 805 | proposal->promote_dh_group(proposal, group); |
7d938be9 TE |
806 | } |
807 | proposal->set_spi(proposal, this->spi_i); | |
808 | } | |
809 | enumerator->destroy(enumerator); | |
810 | ||
811 | return list; | |
812 | } | |
813 | ||
2b04aa46 MW |
814 | METHOD(task_t, build_i, status_t, |
815 | private_quick_mode_t *this, message_t *message) | |
816 | { | |
21b7db99 MW |
817 | switch (this->state) |
818 | { | |
819 | case QM_INIT: | |
820 | { | |
821 | sa_payload_t *sa_payload; | |
696fa8e0 | 822 | linked_list_t *list, *tsi, *tsr; |
908fe163 | 823 | proposal_t *proposal; |
5adf855e | 824 | diffie_hellman_group_t group; |
0ff8d20a | 825 | encap_t encap; |
21b7db99 | 826 | |
47b448b8 | 827 | this->mode = this->config->get_mode(this->config); |
fafa7698 TB |
828 | this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, |
829 | TRUE); | |
830 | this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa, | |
831 | FALSE); | |
832 | this->child.encap = this->ike_sa->has_condition(this->ike_sa, | |
833 | COND_NAT_ANY); | |
5351d63c MW |
834 | this->child_sa = child_sa_create( |
835 | this->ike_sa->get_my_host(this->ike_sa), | |
836 | this->ike_sa->get_other_host(this->ike_sa), | |
fafa7698 | 837 | this->config, &this->child); |
5351d63c | 838 | |
fafa7698 | 839 | if (this->child.encap && this->mode == MODE_TRANSPORT) |
00e11bce TB |
840 | { |
841 | /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */ | |
842 | add_nat_oa_payloads(this, message); | |
843 | } | |
5351d63c | 844 | |
749ac175 | 845 | if (this->config->has_option(this->config, OPT_IPCOMP)) |
47b448b8 | 846 | { |
44d9970f MW |
847 | this->cpi_i = this->child_sa->alloc_cpi(this->child_sa); |
848 | if (!this->cpi_i) | |
47b448b8 | 849 | { |
44d9970f MW |
850 | DBG1(DBG_IKE, "unable to allocate a CPI from kernel, " |
851 | "IPComp disabled"); | |
47b448b8 TB |
852 | } |
853 | } | |
854 | ||
f930b732 | 855 | list = this->config->get_proposals(this->config, FALSE); |
908fe163 MW |
856 | if (list->get_first(list, (void**)&proposal) == SUCCESS) |
857 | { | |
858 | this->proto = proposal->get_protocol(proposal); | |
859 | } | |
860 | list->destroy_offset(list, offsetof(proposal_t, destroy)); | |
861 | this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto); | |
5351d63c MW |
862 | if (!this->spi_i) |
863 | { | |
864 | DBG1(DBG_IKE, "allocating SPI from kernel failed"); | |
865 | return FAILED; | |
866 | } | |
908fe163 | 867 | |
f48e7272 TB |
868 | group = this->config->get_dh_group(this->config); |
869 | if (group != MODP_NONE) | |
870 | { | |
7d938be9 | 871 | proposal_t *proposal; |
b12c53ce | 872 | uint16_t preferred_group; |
7d938be9 TE |
873 | |
874 | proposal = this->ike_sa->get_proposal(this->ike_sa); | |
875 | proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, | |
876 | &preferred_group, NULL); | |
877 | /* try the negotiated DH group from IKE_SA */ | |
878 | list = get_proposals(this, preferred_group); | |
879 | if (list->get_count(list)) | |
880 | { | |
881 | group = preferred_group; | |
882 | } | |
883 | else | |
884 | { | |
885 | /* fall back to the first configured DH group */ | |
886 | list->destroy(list); | |
887 | list = get_proposals(this, group); | |
888 | } | |
889 | ||
f48e7272 TB |
890 | this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, |
891 | group); | |
892 | if (!this->dh) | |
893 | { | |
894 | DBG1(DBG_IKE, "configured DH group %N not supported", | |
895 | diffie_hellman_group_names, group); | |
7d938be9 | 896 | list->destroy_offset(list, offsetof(proposal_t, destroy)); |
f48e7272 TB |
897 | return FAILED; |
898 | } | |
899 | } | |
7d938be9 | 900 | else |
5351d63c | 901 | { |
7d938be9 | 902 | list = get_proposals(this, MODP_NONE); |
5351d63c | 903 | } |
5351d63c | 904 | |
cd0017d4 | 905 | get_lifetimes(this); |
fafa7698 | 906 | encap = get_encap(this->ike_sa, this->child.encap); |
e174e0d4 | 907 | sa_payload = sa_payload_create_from_proposals_v1(list, |
cd0017d4 | 908 | this->lifetime, this->lifebytes, AUTH_NONE, |
0ff8d20a | 909 | this->mode, encap, this->cpi_i); |
21b7db99 MW |
910 | list->destroy_offset(list, offsetof(proposal_t, destroy)); |
911 | message->add_payload(message, &sa_payload->payload_interface); | |
912 | ||
818330aa | 913 | if (!add_nonce(this, &this->nonce_i, message)) |
21b7db99 | 914 | { |
21b7db99 MW |
915 | return FAILED; |
916 | } | |
5adf855e MW |
917 | if (group != MODP_NONE) |
918 | { | |
520d58e0 MW |
919 | if (!add_ke(this, message)) |
920 | { | |
921 | return FAILED; | |
922 | } | |
5adf855e | 923 | } |
d61f2906 MW |
924 | if (!this->tsi) |
925 | { | |
926 | this->tsi = select_ts(this, TRUE, NULL); | |
927 | } | |
928 | if (!this->tsr) | |
929 | { | |
930 | this->tsr = select_ts(this, FALSE, NULL); | |
931 | } | |
abdb82fc MW |
932 | tsi = linked_list_create_with_items(this->tsi, NULL); |
933 | tsr = linked_list_create_with_items(this->tsr, NULL); | |
696fa8e0 MW |
934 | this->tsi = this->tsr = NULL; |
935 | charon->bus->narrow(charon->bus, this->child_sa, | |
936 | NARROW_INITIATOR_PRE_AUTH, tsi, tsr); | |
937 | tsi->remove_first(tsi, (void**)&this->tsi); | |
938 | tsr->remove_first(tsr, (void**)&this->tsr); | |
939 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
940 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
c4b8539f | 941 | if (!this->tsi || !this->tsr) |
21b7db99 | 942 | { |
21b7db99 MW |
943 | return FAILED; |
944 | } | |
9cc38c8e | 945 | add_ts(this, message); |
21b7db99 MW |
946 | return NEED_MORE; |
947 | } | |
948 | case QM_NEGOTIATED: | |
949 | { | |
21b7db99 MW |
950 | return SUCCESS; |
951 | } | |
952 | default: | |
953 | return FAILED; | |
954 | } | |
2b04aa46 MW |
955 | } |
956 | ||
1755ac06 MW |
957 | /** |
958 | * Check for notify errors, return TRUE if error found | |
959 | */ | |
960 | static bool has_notify_errors(private_quick_mode_t *this, message_t *message) | |
07abb470 | 961 | { |
1755ac06 MW |
962 | enumerator_t *enumerator; |
963 | payload_t *payload; | |
964 | bool err = FALSE; | |
965 | ||
966 | enumerator = message->create_payload_enumerator(message); | |
967 | while (enumerator->enumerate(enumerator, &payload)) | |
07abb470 | 968 | { |
3ecfc83c | 969 | if (payload->get_type(payload) == PLV1_NOTIFY) |
1755ac06 MW |
970 | { |
971 | notify_payload_t *notify; | |
972 | notify_type_t type; | |
973 | ||
974 | notify = (notify_payload_t*)payload; | |
975 | type = notify->get_notify_type(notify); | |
976 | if (type < 16384) | |
977 | { | |
bf5b1d9e | 978 | |
1755ac06 MW |
979 | DBG1(DBG_IKE, "received %N error notify", |
980 | notify_type_names, type); | |
981 | err = TRUE; | |
982 | } | |
983 | else | |
984 | { | |
985 | DBG1(DBG_IKE, "received %N notify", notify_type_names, type); | |
986 | } | |
987 | } | |
07abb470 | 988 | } |
1755ac06 MW |
989 | enumerator->destroy(enumerator); |
990 | ||
991 | return err; | |
07abb470 CO |
992 | } |
993 | ||
f56c3c53 MW |
994 | /** |
995 | * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so | |
996 | */ | |
e8735440 | 997 | static void check_for_rekeyed_child(private_quick_mode_t *this, bool responder) |
f56c3c53 MW |
998 | { |
999 | enumerator_t *enumerator, *policies; | |
e8735440 | 1000 | traffic_selector_t *local, *remote, *my_ts, *other_ts; |
f56c3c53 | 1001 | child_sa_t *child_sa; |
bee8b5e3 MW |
1002 | proposal_t *proposal; |
1003 | char *name; | |
f56c3c53 | 1004 | |
e8735440 AH |
1005 | if (responder) |
1006 | { | |
1007 | my_ts = this->tsr; | |
1008 | other_ts = this->tsi; | |
1009 | } | |
1010 | else | |
1011 | { | |
1012 | my_ts = this->tsi; | |
1013 | other_ts = this->tsr; | |
1014 | } | |
1015 | ||
bee8b5e3 | 1016 | name = this->config->get_name(this->config); |
f56c3c53 | 1017 | enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa); |
fafa7698 | 1018 | while (!this->child.reqid && enumerator->enumerate(enumerator, &child_sa)) |
f56c3c53 | 1019 | { |
bee8b5e3 | 1020 | if (streq(child_sa->get_name(child_sa), name)) |
f56c3c53 | 1021 | { |
bee8b5e3 MW |
1022 | proposal = child_sa->get_proposal(child_sa); |
1023 | switch (child_sa->get_state(child_sa)) | |
f56c3c53 | 1024 | { |
bee8b5e3 MW |
1025 | case CHILD_INSTALLED: |
1026 | case CHILD_REKEYING: | |
1027 | policies = child_sa->create_policy_enumerator(child_sa); | |
1028 | if (policies->enumerate(policies, &local, &remote) && | |
e8735440 AH |
1029 | local->equals(local, my_ts) && |
1030 | remote->equals(remote, other_ts) && | |
bee8b5e3 MW |
1031 | this->proposal->equals(this->proposal, proposal)) |
1032 | { | |
bee8b5e3 | 1033 | this->rekey = child_sa->get_spi(child_sa, TRUE); |
fafa7698 TB |
1034 | this->child.reqid = child_sa->get_reqid(child_sa); |
1035 | this->child.mark_in = child_sa->get_mark(child_sa, | |
1036 | TRUE).value; | |
1037 | this->child.mark_out = child_sa->get_mark(child_sa, | |
1038 | FALSE).value; | |
1039 | this->child.if_id_in = child_sa->get_if_id(child_sa, | |
1040 | TRUE); | |
1041 | this->child.if_id_out = child_sa->get_if_id(child_sa, | |
1042 | FALSE); | |
bee8b5e3 MW |
1043 | child_sa->set_state(child_sa, CHILD_REKEYING); |
1044 | DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}", | |
246c969d MW |
1045 | child_sa->get_name(child_sa), |
1046 | child_sa->get_unique_id(child_sa)); | |
bee8b5e3 MW |
1047 | } |
1048 | policies->destroy(policies); | |
bf3bed1c TB |
1049 | break; |
1050 | case CHILD_REKEYED: | |
1051 | default: | |
1052 | break; | |
f56c3c53 | 1053 | } |
f56c3c53 MW |
1054 | } |
1055 | } | |
1056 | enumerator->destroy(enumerator); | |
1057 | } | |
1058 | ||
2b04aa46 MW |
1059 | METHOD(task_t, process_r, status_t, |
1060 | private_quick_mode_t *this, message_t *message) | |
1061 | { | |
4de361d9 TB |
1062 | if (this->mid && this->mid != message->get_message_id(message)) |
1063 | { /* not responsible for this quick mode exchange */ | |
37a22a16 | 1064 | return INVALID_ARG; |
4de361d9 TB |
1065 | } |
1066 | ||
21b7db99 MW |
1067 | switch (this->state) |
1068 | { | |
1069 | case QM_INIT: | |
1070 | { | |
1071 | sa_payload_t *sa_payload; | |
7ee37114 | 1072 | linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL; |
21b7db99 | 1073 | peer_cfg_t *peer_cfg; |
b12c53ce | 1074 | uint16_t group; |
f930b732 | 1075 | proposal_selection_flag_t flags = 0; |
21b7db99 | 1076 | |
a889cfe5 | 1077 | sa_payload = (sa_payload_t*)message->get_payload(message, |
3ecfc83c | 1078 | PLV1_SECURITY_ASSOCIATION); |
a889cfe5 TB |
1079 | if (!sa_payload) |
1080 | { | |
1081 | DBG1(DBG_IKE, "sa payload missing"); | |
1082 | return send_notify(this, INVALID_PAYLOAD_TYPE); | |
1083 | } | |
1084 | ||
fafa7698 TB |
1085 | this->mode = sa_payload->get_encap_mode(sa_payload, |
1086 | &this->child.encap); | |
a889cfe5 | 1087 | |
9cc38c8e | 1088 | if (!get_ts(this, message)) |
c4c59504 | 1089 | { |
c4b8539f | 1090 | return FAILED; |
c4c59504 | 1091 | } |
21b7db99 | 1092 | peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); |
abdb82fc MW |
1093 | tsi = linked_list_create_with_items(this->tsi, NULL); |
1094 | tsr = linked_list_create_with_items(this->tsr, NULL); | |
36431795 | 1095 | this->tsi = this->tsr = NULL; |
7ee37114 MW |
1096 | hostsi = get_dynamic_hosts(this->ike_sa, FALSE); |
1097 | hostsr = get_dynamic_hosts(this->ike_sa, TRUE); | |
21b7db99 | 1098 | this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi, |
7ee37114 MW |
1099 | hostsr, hostsi); |
1100 | hostsi->destroy(hostsi); | |
1101 | hostsr->destroy(hostsr); | |
28e3c659 MW |
1102 | if (this->config) |
1103 | { | |
1104 | this->tsi = select_ts(this, FALSE, tsi); | |
1105 | this->tsr = select_ts(this, TRUE, tsr); | |
1106 | } | |
2d38a03d TB |
1107 | if (!this->config || !this->tsi || !this->tsr || |
1108 | this->mode != this->config->get_mode(this->config)) | |
21b7db99 | 1109 | { |
a160f100 TE |
1110 | DBG1(DBG_IKE, "no matching CHILD_SA config found for " |
1111 | "%#R === %#R", tsi, tsr); | |
1112 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
1113 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
5f1df0a0 | 1114 | return send_notify(this, INVALID_ID_INFORMATION); |
21b7db99 | 1115 | } |
a160f100 TE |
1116 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); |
1117 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
21b7db99 | 1118 | |
749ac175 | 1119 | if (this->config->has_option(this->config, OPT_IPCOMP)) |
47b448b8 | 1120 | { |
44d9970f MW |
1121 | list = sa_payload->get_ipcomp_proposals(sa_payload, |
1122 | &this->cpi_i); | |
1123 | if (!list->get_count(list)) | |
47b448b8 | 1124 | { |
44d9970f MW |
1125 | DBG1(DBG_IKE, "expected IPComp proposal but peer did " |
1126 | "not send one, IPComp disabled"); | |
1127 | this->cpi_i = 0; | |
47b448b8 TB |
1128 | } |
1129 | } | |
1130 | if (!list || !list->get_count(list)) | |
1131 | { | |
1132 | DESTROY_IF(list); | |
47b448b8 TB |
1133 | list = sa_payload->get_proposals(sa_payload); |
1134 | } | |
05e373ae TE |
1135 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) |
1136 | && !lib->settings->get_bool(lib->settings, | |
1137 | "%s.accept_private_algs", FALSE, lib->ns)) | |
f930b732 | 1138 | { |
a2cb2c9c | 1139 | flags |= PROPOSAL_SKIP_PRIVATE; |
f930b732 | 1140 | } |
c9599d41 | 1141 | if (!lib->settings->get_bool(lib->settings, |
f930b732 TE |
1142 | "%s.prefer_configured_proposals", TRUE, lib->ns)) |
1143 | { | |
c9599d41 | 1144 | flags |= PROPOSAL_PREFER_SUPPLIED; |
f930b732 | 1145 | } |
f2ea230b | 1146 | this->proposal = this->config->select_proposal(this->config, list, |
f930b732 | 1147 | flags); |
21b7db99 | 1148 | list->destroy_offset(list, offsetof(proposal_t, destroy)); |
cd0017d4 MW |
1149 | |
1150 | get_lifetimes(this); | |
1151 | apply_lifetimes(this, sa_payload); | |
1152 | ||
21b7db99 MW |
1153 | if (!this->proposal) |
1154 | { | |
e7ae90c1 MW |
1155 | DBG1(DBG_IKE, "no matching proposal found, sending %N", |
1156 | notify_type_names, NO_PROPOSAL_CHOSEN); | |
1157 | return send_notify(this, NO_PROPOSAL_CHOSEN); | |
21b7db99 | 1158 | } |
5351d63c | 1159 | this->spi_i = this->proposal->get_spi(this->proposal); |
21b7db99 | 1160 | |
818330aa | 1161 | if (!get_nonce(this, &this->nonce_i, message)) |
21b7db99 | 1162 | { |
bf5b1d9e | 1163 | return send_notify(this, INVALID_PAYLOAD_TYPE); |
21b7db99 | 1164 | } |
cd0017d4 | 1165 | |
5adf855e MW |
1166 | if (this->proposal->get_algorithm(this->proposal, |
1167 | DIFFIE_HELLMAN_GROUP, &group, NULL)) | |
1168 | { | |
1169 | this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, | |
1170 | group); | |
1171 | if (!this->dh) | |
1172 | { | |
1173 | DBG1(DBG_IKE, "negotiated DH group %N not supported", | |
1174 | diffie_hellman_group_names, group); | |
bf5b1d9e | 1175 | return send_notify(this, INVALID_KEY_INFORMATION); |
5adf855e MW |
1176 | } |
1177 | if (!get_ke(this, message)) | |
1178 | { | |
bf5b1d9e | 1179 | return send_notify(this, INVALID_PAYLOAD_TYPE); |
5adf855e MW |
1180 | } |
1181 | } | |
cd0017d4 | 1182 | |
e8735440 | 1183 | check_for_rekeyed_child(this, TRUE); |
fafa7698 TB |
1184 | this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, |
1185 | TRUE); | |
1186 | this->child.if_id_out_def = this->ike_sa->get_if_id(this->ike_sa, | |
1187 | FALSE); | |
5351d63c MW |
1188 | this->child_sa = child_sa_create( |
1189 | this->ike_sa->get_my_host(this->ike_sa), | |
1190 | this->ike_sa->get_other_host(this->ike_sa), | |
fafa7698 | 1191 | this->config, &this->child); |
f942588f | 1192 | |
abdb82fc MW |
1193 | tsi = linked_list_create_with_items(this->tsi, NULL); |
1194 | tsr = linked_list_create_with_items(this->tsr, NULL); | |
f942588f MW |
1195 | this->tsi = this->tsr = NULL; |
1196 | charon->bus->narrow(charon->bus, this->child_sa, | |
1197 | NARROW_RESPONDER, tsr, tsi); | |
1198 | if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS || | |
1199 | tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS) | |
1200 | { | |
1201 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
1202 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
1203 | return send_notify(this, INVALID_ID_INFORMATION); | |
1204 | } | |
1205 | tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy)); | |
1206 | tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy)); | |
1207 | ||
21b7db99 MW |
1208 | return NEED_MORE; |
1209 | } | |
1210 | case QM_NEGOTIATED: | |
1211 | { | |
cd9bba50 | 1212 | if (has_notify_errors(this, message)) |
07abb470 | 1213 | { |
bf5b1d9e | 1214 | return SUCCESS; |
07abb470 | 1215 | } |
cd9bba50 MW |
1216 | if (message->get_exchange_type(message) == INFORMATIONAL_V1) |
1217 | { | |
1218 | if (message->get_payload(message, PLV1_DELETE)) | |
1219 | { | |
1220 | /* If the DELETE for a Quick Mode follows immediately | |
1221 | * after rekeying, we might receive it before the | |
1222 | * third completing Quick Mode message. Ignore it, as | |
1223 | * it gets handled by a separately queued delete task. */ | |
1224 | return NEED_MORE; | |
1225 | } | |
1226 | return SUCCESS; | |
1227 | } | |
71141cc8 TB |
1228 | if (!this->rekey) |
1229 | { | |
1230 | /* do another check in case SAs were created since we handled | |
1231 | * the QM request, this is consistent with the rekey check | |
1232 | * before installation on the initiator */ | |
1233 | check_for_rekeyed_child(this, TRUE); | |
1234 | if (this->rekey) | |
1235 | { | |
1236 | this->child_sa->destroy(this->child_sa); | |
1237 | this->child_sa = child_sa_create( | |
1238 | this->ike_sa->get_my_host(this->ike_sa), | |
1239 | this->ike_sa->get_other_host(this->ike_sa), | |
1240 | this->config, &this->child); | |
1241 | } | |
1242 | } | |
5351d63c MW |
1243 | if (!install(this)) |
1244 | { | |
e91157a4 TB |
1245 | ike_sa_t *ike_sa = this->ike_sa; |
1246 | task_t *task; | |
1247 | ||
1248 | task = (task_t*)quick_delete_create(this->ike_sa, | |
767966e7 | 1249 | this->proposal->get_protocol(this->proposal), |
e91157a4 TB |
1250 | this->spi_i, TRUE, TRUE); |
1251 | /* flush_queue() destroys the current task */ | |
1252 | ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE); | |
1253 | ike_sa->queue_task(ike_sa, task); | |
767966e7 | 1254 | return ALREADY_DONE; |
5351d63c | 1255 | } |
21b7db99 MW |
1256 | return SUCCESS; |
1257 | } | |
1258 | default: | |
1259 | return FAILED; | |
1260 | } | |
2b04aa46 MW |
1261 | } |
1262 | ||
1263 | METHOD(task_t, build_r, status_t, | |
1264 | private_quick_mode_t *this, message_t *message) | |
1265 | { | |
4de361d9 TB |
1266 | if (this->mid && this->mid != message->get_message_id(message)) |
1267 | { /* not responsible for this quick mode exchange */ | |
37a22a16 | 1268 | return INVALID_ARG; |
4de361d9 TB |
1269 | } |
1270 | ||
21b7db99 MW |
1271 | switch (this->state) |
1272 | { | |
1273 | case QM_INIT: | |
1274 | { | |
1275 | sa_payload_t *sa_payload; | |
0ff8d20a | 1276 | encap_t encap; |
21b7db99 | 1277 | |
908fe163 MW |
1278 | this->proto = this->proposal->get_protocol(this->proposal); |
1279 | this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto); | |
5351d63c MW |
1280 | if (!this->spi_r) |
1281 | { | |
1282 | DBG1(DBG_IKE, "allocating SPI from kernel failed"); | |
bf5b1d9e | 1283 | return send_notify(this, NO_PROPOSAL_CHOSEN); |
5351d63c MW |
1284 | } |
1285 | this->proposal->set_spi(this->proposal, this->spi_r); | |
1286 | ||
47b448b8 TB |
1287 | if (this->cpi_i) |
1288 | { | |
1289 | this->cpi_r = this->child_sa->alloc_cpi(this->child_sa); | |
1290 | if (!this->cpi_r) | |
1291 | { | |
1292 | DBG1(DBG_IKE, "unable to allocate a CPI from " | |
1293 | "kernel, IPComp disabled"); | |
1294 | return send_notify(this, NO_PROPOSAL_CHOSEN); | |
1295 | } | |
1296 | } | |
1297 | ||
fafa7698 | 1298 | if (this->child.encap && this->mode == MODE_TRANSPORT) |
29b0cb32 | 1299 | { |
3bf0be6b | 1300 | /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */ |
9f80110b | 1301 | add_nat_oa_payloads(this, message); |
29b0cb32 TB |
1302 | } |
1303 | ||
fafa7698 | 1304 | encap = get_encap(this->ike_sa, this->child.encap); |
e174e0d4 | 1305 | sa_payload = sa_payload_create_from_proposal_v1(this->proposal, |
cd0017d4 | 1306 | this->lifetime, this->lifebytes, AUTH_NONE, |
0ff8d20a | 1307 | this->mode, encap, this->cpi_r); |
21b7db99 MW |
1308 | message->add_payload(message, &sa_payload->payload_interface); |
1309 | ||
818330aa | 1310 | if (!add_nonce(this, &this->nonce_r, message)) |
21b7db99 | 1311 | { |
21b7db99 MW |
1312 | return FAILED; |
1313 | } | |
5adf855e MW |
1314 | if (this->dh) |
1315 | { | |
520d58e0 MW |
1316 | if (!add_ke(this, message)) |
1317 | { | |
1318 | return FAILED; | |
1319 | } | |
5adf855e MW |
1320 | } |
1321 | ||
9cc38c8e | 1322 | add_ts(this, message); |
21b7db99 | 1323 | |
21b7db99 | 1324 | this->state = QM_NEGOTIATED; |
4de361d9 | 1325 | this->mid = message->get_message_id(message); |
21b7db99 MW |
1326 | return NEED_MORE; |
1327 | } | |
cd9bba50 MW |
1328 | case QM_NEGOTIATED: |
1329 | if (message->get_exchange_type(message) == INFORMATIONAL_V1) | |
1330 | { | |
1331 | /* skip INFORMATIONAL response if we received a INFORMATIONAL | |
1332 | * delete, see process_r() */ | |
1333 | return ALREADY_DONE; | |
1334 | } | |
1335 | /* fall */ | |
21b7db99 MW |
1336 | default: |
1337 | return FAILED; | |
1338 | } | |
2b04aa46 MW |
1339 | } |
1340 | ||
1341 | METHOD(task_t, process_i, status_t, | |
1342 | private_quick_mode_t *this, message_t *message) | |
1343 | { | |
21b7db99 MW |
1344 | switch (this->state) |
1345 | { | |
1346 | case QM_INIT: | |
1347 | { | |
1348 | sa_payload_t *sa_payload; | |
47b448b8 | 1349 | linked_list_t *list = NULL; |
c9599d41 | 1350 | proposal_selection_flag_t flags = 0; |
21b7db99 MW |
1351 | |
1352 | sa_payload = (sa_payload_t*)message->get_payload(message, | |
3ecfc83c | 1353 | PLV1_SECURITY_ASSOCIATION); |
21b7db99 MW |
1354 | if (!sa_payload) |
1355 | { | |
1356 | DBG1(DBG_IKE, "sa payload missing"); | |
bf5b1d9e | 1357 | return send_notify(this, NO_PROPOSAL_CHOSEN); |
21b7db99 | 1358 | } |
47b448b8 TB |
1359 | if (this->cpi_i) |
1360 | { | |
1361 | list = sa_payload->get_ipcomp_proposals(sa_payload, | |
1362 | &this->cpi_r); | |
3451ecd7 TB |
1363 | if (!list->get_count(list)) |
1364 | { | |
2db6d5b8 | 1365 | DBG1(DBG_IKE, "peer did not accept our IPComp proposal, " |
3451ecd7 TB |
1366 | "IPComp disabled"); |
1367 | this->cpi_i = 0; | |
1368 | } | |
47b448b8 TB |
1369 | } |
1370 | if (!list || !list->get_count(list)) | |
1371 | { | |
1372 | DESTROY_IF(list); | |
47b448b8 TB |
1373 | list = sa_payload->get_proposals(sa_payload); |
1374 | } | |
05e373ae TE |
1375 | if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) |
1376 | && !lib->settings->get_bool(lib->settings, | |
1377 | "%s.accept_private_algs", FALSE, lib->ns)) | |
f930b732 | 1378 | { |
a2cb2c9c | 1379 | flags |= PROPOSAL_SKIP_PRIVATE; |
f930b732 | 1380 | } |
f2ea230b | 1381 | this->proposal = this->config->select_proposal(this->config, list, |
f930b732 | 1382 | flags); |
21b7db99 MW |
1383 | list->destroy_offset(list, offsetof(proposal_t, destroy)); |
1384 | if (!this->proposal) | |
1385 | { | |
1386 | DBG1(DBG_IKE, "no matching proposal found"); | |
bf5b1d9e | 1387 | return send_notify(this, NO_PROPOSAL_CHOSEN); |
21b7db99 | 1388 | } |
5351d63c MW |
1389 | this->spi_r = this->proposal->get_spi(this->proposal); |
1390 | ||
cd0017d4 MW |
1391 | apply_lifetimes(this, sa_payload); |
1392 | ||
818330aa | 1393 | if (!get_nonce(this, &this->nonce_r, message)) |
21b7db99 | 1394 | { |
bf5b1d9e | 1395 | return send_notify(this, INVALID_PAYLOAD_TYPE); |
21b7db99 | 1396 | } |
5adf855e MW |
1397 | if (this->dh && !get_ke(this, message)) |
1398 | { | |
bf5b1d9e | 1399 | return send_notify(this, INVALID_KEY_INFORMATION); |
5adf855e | 1400 | } |
9cc38c8e | 1401 | if (!get_ts(this, message)) |
c4b8539f | 1402 | { |
bf5b1d9e | 1403 | return send_notify(this, INVALID_PAYLOAD_TYPE); |
c4b8539f | 1404 | } |
e8735440 | 1405 | check_for_rekeyed_child(this, FALSE); |
5351d63c MW |
1406 | if (!install(this)) |
1407 | { | |
bf5b1d9e | 1408 | return send_notify(this, NO_PROPOSAL_CHOSEN); |
5351d63c | 1409 | } |
21b7db99 MW |
1410 | this->state = QM_NEGOTIATED; |
1411 | return NEED_MORE; | |
1412 | } | |
1413 | default: | |
1414 | return FAILED; | |
1415 | } | |
2b04aa46 MW |
1416 | } |
1417 | ||
1418 | METHOD(task_t, get_type, task_type_t, | |
1419 | private_quick_mode_t *this) | |
1420 | { | |
1421 | return TASK_QUICK_MODE; | |
1422 | } | |
1423 | ||
b12c53ce | 1424 | METHOD(quick_mode_t, get_mid, uint32_t, |
4de361d9 TB |
1425 | private_quick_mode_t *this) |
1426 | { | |
1427 | return this->mid; | |
1428 | } | |
1429 | ||
14dc7941 | 1430 | METHOD(quick_mode_t, use_reqid, void, |
b12c53ce | 1431 | private_quick_mode_t *this, uint32_t reqid) |
14dc7941 | 1432 | { |
fafa7698 | 1433 | this->child.reqid = reqid; |
14dc7941 MW |
1434 | } |
1435 | ||
85b23888 | 1436 | METHOD(quick_mode_t, use_marks, void, |
8ab33628 | 1437 | private_quick_mode_t *this, uint32_t in, uint32_t out) |
85b23888 | 1438 | { |
fafa7698 TB |
1439 | this->child.mark_in = in; |
1440 | this->child.mark_out = out; | |
85b23888 MW |
1441 | } |
1442 | ||
8ab33628 TB |
1443 | METHOD(quick_mode_t, use_if_ids, void, |
1444 | private_quick_mode_t *this, uint32_t in, uint32_t out) | |
1445 | { | |
fafa7698 TB |
1446 | this->child.if_id_in = in; |
1447 | this->child.if_id_out = out; | |
8ab33628 TB |
1448 | } |
1449 | ||
669d8bde | 1450 | METHOD(quick_mode_t, rekey, void, |
b12c53ce | 1451 | private_quick_mode_t *this, uint32_t spi) |
669d8bde MW |
1452 | { |
1453 | this->rekey = spi; | |
1454 | } | |
1455 | ||
2b04aa46 MW |
1456 | METHOD(task_t, migrate, void, |
1457 | private_quick_mode_t *this, ike_sa_t *ike_sa) | |
1458 | { | |
bce22af2 MW |
1459 | chunk_free(&this->nonce_i); |
1460 | chunk_free(&this->nonce_r); | |
1461 | DESTROY_IF(this->tsi); | |
1462 | DESTROY_IF(this->tsr); | |
1463 | DESTROY_IF(this->proposal); | |
1464 | DESTROY_IF(this->child_sa); | |
1465 | DESTROY_IF(this->dh); | |
1466 | ||
2b04aa46 | 1467 | this->ike_sa = ike_sa; |
bce22af2 MW |
1468 | this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); |
1469 | this->state = QM_INIT; | |
4de361d9 | 1470 | this->mid = 0; |
bce22af2 MW |
1471 | this->tsi = NULL; |
1472 | this->tsr = NULL; | |
1473 | this->proposal = NULL; | |
1474 | this->child_sa = NULL; | |
1475 | this->dh = NULL; | |
1476 | this->spi_i = 0; | |
1477 | this->spi_r = 0; | |
fafa7698 | 1478 | this->child = (child_sa_create_t){}; |
bce22af2 MW |
1479 | |
1480 | if (!this->initiator) | |
1481 | { | |
1482 | DESTROY_IF(this->config); | |
1483 | this->config = NULL; | |
1484 | } | |
2b04aa46 MW |
1485 | } |
1486 | ||
1487 | METHOD(task_t, destroy, void, | |
1488 | private_quick_mode_t *this) | |
1489 | { | |
1490 | chunk_free(&this->nonce_i); | |
1491 | chunk_free(&this->nonce_r); | |
1492 | DESTROY_IF(this->tsi); | |
1493 | DESTROY_IF(this->tsr); | |
1494 | DESTROY_IF(this->proposal); | |
1495 | DESTROY_IF(this->child_sa); | |
1496 | DESTROY_IF(this->config); | |
5adf855e | 1497 | DESTROY_IF(this->dh); |
2b04aa46 MW |
1498 | free(this); |
1499 | } | |
1500 | ||
1501 | /* | |
1502 | * Described in header. | |
1503 | */ | |
1504 | quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config, | |
1505 | traffic_selector_t *tsi, traffic_selector_t *tsr) | |
1506 | { | |
1507 | private_quick_mode_t *this; | |
1508 | ||
1509 | INIT(this, | |
1510 | .public = { | |
1511 | .task = { | |
1512 | .get_type = _get_type, | |
1513 | .migrate = _migrate, | |
1514 | .destroy = _destroy, | |
1515 | }, | |
4de361d9 | 1516 | .get_mid = _get_mid, |
14dc7941 | 1517 | .use_reqid = _use_reqid, |
85b23888 | 1518 | .use_marks = _use_marks, |
8ab33628 | 1519 | .use_if_ids = _use_if_ids, |
669d8bde | 1520 | .rekey = _rekey, |
2b04aa46 MW |
1521 | }, |
1522 | .ike_sa = ike_sa, | |
5351d63c | 1523 | .initiator = config != NULL, |
2b04aa46 | 1524 | .config = config, |
5351d63c | 1525 | .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa), |
2b04aa46 | 1526 | .state = QM_INIT, |
d61f2906 MW |
1527 | .tsi = tsi ? tsi->clone(tsi) : NULL, |
1528 | .tsr = tsr ? tsr->clone(tsr) : NULL, | |
908fe163 | 1529 | .proto = PROTO_ESP, |
2f3c08d2 TB |
1530 | .delete = lib->settings->get_bool(lib->settings, |
1531 | "%s.delete_rekeyed", FALSE, lib->ns), | |
2b04aa46 MW |
1532 | ); |
1533 | ||
1534 | if (config) | |
1535 | { | |
1536 | this->public.task.build = _build_i; | |
1537 | this->public.task.process = _process_i; | |
1538 | } | |
1539 | else | |
1540 | { | |
1541 | this->public.task.build = _build_r; | |
1542 | this->public.task.process = _process_r; | |
1543 | } | |
1544 | ||
1545 | return &this->public; | |
1546 | } |