2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
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>.
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
19 #include "quick_mode.h"
24 #include <sa/ikev1/keymat_v1.h>
25 #include <encoding/payloads/sa_payload.h>
26 #include <encoding/payloads/nonce_payload.h>
27 #include <encoding/payloads/ke_payload.h>
28 #include <encoding/payloads/id_payload.h>
29 #include <encoding/payloads/payload.h>
30 #include <sa/ikev1/tasks/informational.h>
31 #include <sa/ikev1/tasks/quick_delete.h>
32 #include <processing/jobs/inactivity_job.h>
34 typedef struct private_quick_mode_t private_quick_mode_t
;
37 * Private members of a quick_mode_t task.
39 struct private_quick_mode_t
{
42 * Public methods and task_t interface.
52 * TRUE if we are initiating quick mode
57 * Traffic selector of initiator
59 traffic_selector_t
*tsi
;
62 * Traffic selector of responder
64 traffic_selector_t
*tsr
;
87 * Initiators IPComp CPI
92 * Responders IPComp CPI
97 * selected CHILD_SA proposal
102 * Config of CHILD_SA to establish
107 * CHILD_SA we are about to establish
109 child_sa_t
*child_sa
;
117 * DH exchange, when PFS is in use
119 diffie_hellman_t
*dh
;
122 * Negotiated lifetime of new SA
127 * Negotaited lifebytes of new SA
132 * Reqid to use, 0 for auto-allocate
142 * Negotiated mode, tunnel or transport
147 * Use UDP encapsulation
151 /** states of quick mode */
159 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
161 static void schedule_inactivity_timeout(private_quick_mode_t
*this)
166 timeout
= this->config
->get_inactivity(this->config
);
169 close_ike
= lib
->settings
->get_bool(lib
->settings
,
170 "%s.inactivity_close_ike", FALSE
, charon
->name
);
171 lib
->scheduler
->schedule_job(lib
->scheduler
, (job_t
*)
172 inactivity_job_create(this->child_sa
->get_reqid(this->child_sa
),
173 timeout
, close_ike
), timeout
);
178 * Check if we have a an address pool configured
180 static bool have_pool(ike_sa_t
*ike_sa
)
182 enumerator_t
*enumerator
;
183 peer_cfg_t
*peer_cfg
;
187 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
190 enumerator
= peer_cfg
->create_pool_enumerator(peer_cfg
);
191 if (enumerator
->enumerate(enumerator
, &pool
))
195 enumerator
->destroy(enumerator
);
201 * Get hosts to use for dynamic traffic selectors
203 static linked_list_t
*get_dynamic_hosts(ike_sa_t
*ike_sa
, bool local
)
205 enumerator_t
*enumerator
;
209 list
= linked_list_create();
210 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, local
);
211 while (enumerator
->enumerate(enumerator
, &host
))
213 list
->insert_last(list
, host
);
215 enumerator
->destroy(enumerator
);
217 if (list
->get_count(list
) == 0)
218 { /* no virtual IPs assigned */
221 host
= ike_sa
->get_my_host(ike_sa
);
222 list
->insert_last(list
, host
);
224 else if (!have_pool(ike_sa
))
225 { /* use host only if we don't have a pool configured */
226 host
= ike_sa
->get_other_host(ike_sa
);
227 list
->insert_last(list
, host
);
234 * Install negotiated CHILD_SA
236 static bool install(private_quick_mode_t
*this)
238 status_t status
, status_i
, status_o
;
239 chunk_t encr_i
, encr_r
, integ_i
, integ_r
;
240 linked_list_t
*tsi
, *tsr
;
241 child_sa_t
*old
= NULL
;
243 this->child_sa
->set_proposal(this->child_sa
, this->proposal
);
244 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLING
);
245 this->child_sa
->set_mode(this->child_sa
, this->mode
);
247 if (this->cpi_i
&& this->cpi_r
)
248 { /* DEFLATE is the only transform we currently support */
249 this->child_sa
->set_ipcomp(this->child_sa
, IPCOMP_DEFLATE
);
253 this->cpi_i
= this->cpi_r
= 0;
256 this->child_sa
->set_protocol(this->child_sa
,
257 this->proposal
->get_protocol(this->proposal
));
259 status_i
= status_o
= FAILED
;
260 encr_i
= encr_r
= integ_i
= integ_r
= chunk_empty
;
261 tsi
= linked_list_create_with_items(this->tsi
->clone(this->tsi
), NULL
);
262 tsr
= linked_list_create_with_items(this->tsr
->clone(this->tsr
), NULL
);
265 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
266 NARROW_INITIATOR_POST_AUTH
, tsi
, tsr
);
270 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
271 NARROW_RESPONDER_POST
, tsr
, tsi
);
273 if (tsi
->get_count(tsi
) == 0 || tsr
->get_count(tsr
) == 0)
275 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
276 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
277 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
281 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
, this->dh
,
282 this->spi_i
, this->spi_r
, this->nonce_i
, this->nonce_r
,
283 &encr_i
, &integ_i
, &encr_r
, &integ_r
))
287 status_i
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
288 this->spi_i
, this->cpi_i
, TRUE
, FALSE
, tsi
, tsr
);
289 status_o
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
290 this->spi_r
, this->cpi_r
, FALSE
, FALSE
, tsi
, tsr
);
294 status_i
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
295 this->spi_r
, this->cpi_r
, TRUE
, FALSE
, tsr
, tsi
);
296 status_o
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
297 this->spi_i
, this->cpi_i
, FALSE
, FALSE
, tsr
, tsi
);
300 chunk_clear(&integ_i
);
301 chunk_clear(&integ_r
);
302 chunk_clear(&encr_i
);
303 chunk_clear(&encr_r
);
305 if (status_i
!= SUCCESS
|| status_o
!= SUCCESS
)
307 DBG1(DBG_IKE
, "unable to install %s%s%sIPsec SA (SAD) in kernel",
308 (status_i
!= SUCCESS
) ?
"inbound " : "",
309 (status_i
!= SUCCESS
&& status_o
!= SUCCESS
) ?
"and ": "",
310 (status_o
!= SUCCESS
) ?
"outbound " : "");
311 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
312 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
318 status
= this->child_sa
->add_policies(this->child_sa
, tsi
, tsr
);
322 status
= this->child_sa
->add_policies(this->child_sa
, tsr
, tsi
);
324 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
325 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
326 if (status
!= SUCCESS
)
328 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
332 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->initiator
,
333 this->dh
, this->nonce_i
, this->nonce_r
);
335 /* add to IKE_SA, and remove from task */
336 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
337 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
339 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
340 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
341 this->child_sa
->get_name(this->child_sa
),
342 this->child_sa
->get_reqid(this->child_sa
),
343 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
344 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
345 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
346 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
350 old
= this->ike_sa
->get_child_sa(this->ike_sa
,
351 this->proposal
->get_protocol(this->proposal
),
356 charon
->bus
->child_rekey(charon
->bus
, old
, this->child_sa
);
360 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
364 schedule_inactivity_timeout(this);
366 this->child_sa
= NULL
;
371 * Generate and add NONCE
373 static bool add_nonce(private_quick_mode_t
*this, chunk_t
*nonce
,
376 nonce_payload_t
*nonce_payload
;
379 nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
382 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
385 if (!nonceg
->allocate_nonce(nonceg
, NONCE_SIZE
, nonce
))
387 DBG1(DBG_IKE
, "nonce allocation failed");
388 nonceg
->destroy(nonceg
);
391 nonceg
->destroy(nonceg
);
393 nonce_payload
= nonce_payload_create(NONCE_V1
);
394 nonce_payload
->set_nonce(nonce_payload
, *nonce
);
395 message
->add_payload(message
, &nonce_payload
->payload_interface
);
401 * Extract nonce from NONCE payload
403 static bool get_nonce(private_quick_mode_t
*this, chunk_t
*nonce
,
406 nonce_payload_t
*nonce_payload
;
408 nonce_payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE_V1
);
411 DBG1(DBG_IKE
, "NONCE payload missing in message");
414 *nonce
= nonce_payload
->get_nonce(nonce_payload
);
420 * Add KE payload to message
422 static void add_ke(private_quick_mode_t
*this, message_t
*message
)
424 ke_payload_t
*ke_payload
;
426 ke_payload
= ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1
, this->dh
);
427 message
->add_payload(message
, &ke_payload
->payload_interface
);
431 * Get DH value from a KE payload
433 static bool get_ke(private_quick_mode_t
*this, message_t
*message
)
435 ke_payload_t
*ke_payload
;
437 ke_payload
= (ke_payload_t
*)message
->get_payload(message
, KEY_EXCHANGE_V1
);
440 DBG1(DBG_IKE
, "KE payload missing");
443 this->dh
->set_other_public_value(this->dh
,
444 ke_payload
->get_key_exchange_data(ke_payload
));
449 * Select a traffic selector from configuration
451 static traffic_selector_t
* select_ts(private_quick_mode_t
*this, bool local
,
452 linked_list_t
*supplied
)
454 traffic_selector_t
*ts
;
455 linked_list_t
*list
, *hosts
;
457 hosts
= get_dynamic_hosts(this->ike_sa
, local
);
458 list
= this->config
->get_traffic_selectors(this->config
,
459 local
, supplied
, hosts
);
460 hosts
->destroy(hosts
);
461 if (list
->get_first(list
, (void**)&ts
) == SUCCESS
)
467 DBG1(DBG_IKE
, "%s traffic selector missing in configuration",
468 local ?
"local" : "local");
471 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
476 * Add selected traffic selectors to message
478 static void add_ts(private_quick_mode_t
*this, message_t
*message
)
480 id_payload_t
*id_payload
;
485 hsi
= this->ike_sa
->get_my_host(this->ike_sa
);
486 hsr
= this->ike_sa
->get_other_host(this->ike_sa
);
490 hsr
= this->ike_sa
->get_my_host(this->ike_sa
);
491 hsi
= this->ike_sa
->get_other_host(this->ike_sa
);
493 /* add ID payload only if negotiating non host2host tunnels */
494 if (!this->tsi
->is_host(this->tsi
, hsi
) ||
495 !this->tsr
->is_host(this->tsr
, hsr
) ||
496 this->tsi
->get_protocol(this->tsi
) ||
497 this->tsr
->get_protocol(this->tsr
) ||
498 this->tsi
->get_from_port(this->tsi
) ||
499 this->tsr
->get_from_port(this->tsr
) ||
500 this->tsi
->get_to_port(this->tsi
) != 65535 ||
501 this->tsr
->get_to_port(this->tsr
) != 65535)
503 id_payload
= id_payload_create_from_ts(this->tsi
);
504 message
->add_payload(message
, &id_payload
->payload_interface
);
505 id_payload
= id_payload_create_from_ts(this->tsr
);
506 message
->add_payload(message
, &id_payload
->payload_interface
);
511 * Get traffic selectors from received message
513 static bool get_ts(private_quick_mode_t
*this, message_t
*message
)
515 traffic_selector_t
*tsi
= NULL
, *tsr
= NULL
;
516 enumerator_t
*enumerator
;
517 id_payload_t
*id_payload
;
522 enumerator
= message
->create_payload_enumerator(message
);
523 while (enumerator
->enumerate(enumerator
, &payload
))
525 if (payload
->get_type(payload
) == ID_V1
)
527 id_payload
= (id_payload_t
*)payload
;
531 tsi
= id_payload
->get_ts(id_payload
);
536 tsr
= id_payload
->get_ts(id_payload
);
541 enumerator
->destroy(enumerator
);
543 /* create host2host selectors if ID payloads missing */
546 hsi
= this->ike_sa
->get_my_host(this->ike_sa
);
547 hsr
= this->ike_sa
->get_other_host(this->ike_sa
);
551 hsr
= this->ike_sa
->get_my_host(this->ike_sa
);
552 hsi
= this->ike_sa
->get_other_host(this->ike_sa
);
556 tsi
= traffic_selector_create_from_subnet(hsi
->clone(hsi
),
557 hsi
->get_family(hsi
) == AF_INET ?
32 : 128, 0, 0);
561 tsr
= traffic_selector_create_from_subnet(hsr
->clone(hsr
),
562 hsr
->get_family(hsr
) == AF_INET ?
32 : 128, 0, 0);
564 if (this->mode
== MODE_TRANSPORT
&& this->udp
&&
565 (!tsi
->is_host(tsi
, hsi
) || !tsr
->is_host(tsr
, hsr
)))
566 { /* change TS in case of a NAT in transport mode */
567 DBG2(DBG_IKE
, "changing received traffic selectors %R=== %R due to NAT",
569 tsi
->set_address(tsi
, hsi
);
570 tsr
->set_address(tsr
, hsr
);
575 /* check if peer selection is valid */
576 if (!tsr
->is_contained_in(tsr
, this->tsr
) ||
577 !tsi
->is_contained_in(tsi
, this->tsi
))
579 DBG1(DBG_IKE
, "peer selected invalid traffic selectors: "
580 "%R for %R, %R for %R", tsi
, this->tsi
, tsr
, this->tsr
);
585 this->tsi
->destroy(this->tsi
);
586 this->tsr
->destroy(this->tsr
);
599 * Add NAT-OA payloads
601 static void add_nat_oa_payloads(private_quick_mode_t
*this, message_t
*message
)
603 identification_t
*id
;
604 id_payload_t
*nat_oa
;
607 src
= message
->get_source(message
);
608 dst
= message
->get_destination(message
);
610 src
= this->initiator ? src
: dst
;
611 dst
= this->initiator ? dst
: src
;
613 /* first NAT-OA is the initiator's address */
614 id
= identification_create_from_sockaddr(src
->get_sockaddr(src
));
615 nat_oa
= id_payload_create_from_identification(NAT_OA_V1
, id
);
616 message
->add_payload(message
, (payload_t
*)nat_oa
);
619 /* second NAT-OA is that of the responder */
620 id
= identification_create_from_sockaddr(dst
->get_sockaddr(dst
));
621 nat_oa
= id_payload_create_from_identification(NAT_OA_V1
, id
);
622 message
->add_payload(message
, (payload_t
*)nat_oa
);
629 static void get_lifetimes(private_quick_mode_t
*this)
633 lft
= this->config
->get_lifetime(this->config
);
636 this->lifetime
= lft
->time
.life
;
638 else if (lft
->bytes
.life
)
640 this->lifebytes
= lft
->bytes
.life
;
646 * Check and apply lifetimes
648 static void apply_lifetimes(private_quick_mode_t
*this, sa_payload_t
*sa_payload
)
653 lifetime
= sa_payload
->get_lifetime(sa_payload
);
654 lifebytes
= sa_payload
->get_lifebytes(sa_payload
);
655 if (this->lifetime
!= lifetime
)
657 DBG1(DBG_IKE
, "received %us lifetime, configured %us",
658 lifetime
, this->lifetime
);
659 this->lifetime
= lifetime
;
661 if (this->lifebytes
!= lifebytes
)
663 DBG1(DBG_IKE
, "received %llu lifebytes, configured %llu",
664 lifebytes
, this->lifebytes
);
665 this->lifebytes
= lifebytes
;
670 * Set the task ready to build notify error message
672 static status_t
send_notify(private_quick_mode_t
*this, notify_type_t type
)
674 notify_payload_t
*notify
;
676 notify
= notify_payload_create_from_protocol_and_type(NOTIFY_V1
,
678 notify
->set_spi(notify
, this->spi_i
);
680 this->ike_sa
->queue_task(this->ike_sa
,
681 (task_t
*)informational_create(this->ike_sa
, notify
));
682 /* cancel all active/passive tasks in favour of informational */
683 this->ike_sa
->flush_queue(this->ike_sa
,
684 this->initiator ? TASK_QUEUE_ACTIVE
: TASK_QUEUE_PASSIVE
);
688 METHOD(task_t
, build_i
, status_t
,
689 private_quick_mode_t
*this, message_t
*message
)
695 enumerator_t
*enumerator
;
696 sa_payload_t
*sa_payload
;
697 linked_list_t
*list
, *tsi
, *tsr
;
698 proposal_t
*proposal
;
699 diffie_hellman_group_t group
;
701 this->udp
= this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
);
702 this->mode
= this->config
->get_mode(this->config
);
703 this->child_sa
= child_sa_create(
704 this->ike_sa
->get_my_host(this->ike_sa
),
705 this->ike_sa
->get_other_host(this->ike_sa
),
706 this->config
, this->reqid
, this->udp
);
708 if (this->udp
&& this->mode
== MODE_TRANSPORT
)
710 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
711 add_nat_oa_payloads(this, message
);
714 if (this->config
->use_ipcomp(this->config
))
718 DBG1(DBG_IKE
, "IPComp is not supported if either peer is "
719 "natted, IPComp disabled");
723 this->cpi_i
= this->child_sa
->alloc_cpi(this->child_sa
);
726 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, "
732 this->spi_i
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
735 DBG1(DBG_IKE
, "allocating SPI from kernel failed");
738 group
= this->config
->get_dh_group(this->config
);
739 if (group
!= MODP_NONE
)
741 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
745 DBG1(DBG_IKE
, "configured DH group %N not supported",
746 diffie_hellman_group_names
, group
);
751 list
= this->config
->get_proposals(this->config
, FALSE
);
752 enumerator
= list
->create_enumerator(list
);
753 while (enumerator
->enumerate(enumerator
, &proposal
))
755 if (group
!= MODP_NONE
)
757 if (!proposal
->has_dh_group(proposal
, group
))
759 list
->remove_at(list
, enumerator
);
760 proposal
->destroy(proposal
);
763 proposal
->strip_dh(proposal
, group
);
765 proposal
->set_spi(proposal
, this->spi_i
);
767 enumerator
->destroy(enumerator
);
770 sa_payload
= sa_payload_create_from_proposals_v1(list
,
771 this->lifetime
, this->lifebytes
, AUTH_NONE
,
772 this->mode
, this->udp
, this->cpi_i
);
773 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
774 message
->add_payload(message
, &sa_payload
->payload_interface
);
776 if (!add_nonce(this, &this->nonce_i
, message
))
780 if (group
!= MODP_NONE
)
782 add_ke(this, message
);
786 this->tsi
= select_ts(this, TRUE
, NULL
);
790 this->tsr
= select_ts(this, FALSE
, NULL
);
792 tsi
= linked_list_create_with_items(this->tsi
, NULL
);
793 tsr
= linked_list_create_with_items(this->tsr
, NULL
);
794 this->tsi
= this->tsr
= NULL
;
795 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
796 NARROW_INITIATOR_PRE_AUTH
, tsi
, tsr
);
797 tsi
->remove_first(tsi
, (void**)&this->tsi
);
798 tsr
->remove_first(tsr
, (void**)&this->tsr
);
799 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
800 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
801 if (!this->tsi
|| !this->tsr
)
805 add_ts(this, message
);
818 * Check for notify errors, return TRUE if error found
820 static bool has_notify_errors(private_quick_mode_t
*this, message_t
*message
)
822 enumerator_t
*enumerator
;
826 enumerator
= message
->create_payload_enumerator(message
);
827 while (enumerator
->enumerate(enumerator
, &payload
))
829 if (payload
->get_type(payload
) == NOTIFY_V1
)
831 notify_payload_t
*notify
;
834 notify
= (notify_payload_t
*)payload
;
835 type
= notify
->get_notify_type(notify
);
839 DBG1(DBG_IKE
, "received %N error notify",
840 notify_type_names
, type
);
845 DBG1(DBG_IKE
, "received %N notify", notify_type_names
, type
);
849 enumerator
->destroy(enumerator
);
855 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
857 static void check_for_rekeyed_child(private_quick_mode_t
*this)
859 enumerator_t
*enumerator
, *policies
;
860 traffic_selector_t
*local
, *remote
;
861 child_sa_t
*child_sa
;
863 enumerator
= this->ike_sa
->create_child_sa_enumerator(this->ike_sa
);
864 while (this->reqid
== 0 && enumerator
->enumerate(enumerator
, &child_sa
))
866 if (child_sa
->get_state(child_sa
) == CHILD_INSTALLED
&&
867 streq(child_sa
->get_name(child_sa
),
868 this->config
->get_name(this->config
)))
870 policies
= child_sa
->create_policy_enumerator(child_sa
);
871 if (policies
->enumerate(policies
, &local
, &remote
))
873 if (local
->equals(local
, this->tsr
) &&
874 remote
->equals(remote
, this->tsi
) &&
875 this->proposal
->equals(this->proposal
,
876 child_sa
->get_proposal(child_sa
)))
878 this->reqid
= child_sa
->get_reqid(child_sa
);
879 this->rekey
= child_sa
->get_spi(child_sa
, TRUE
);
880 child_sa
->set_state(child_sa
, CHILD_REKEYING
);
881 DBG1(DBG_IKE
, "detected rekeying of CHILD_SA %s{%u}",
882 child_sa
->get_name(child_sa
), this->reqid
);
885 policies
->destroy(policies
);
888 enumerator
->destroy(enumerator
);
891 METHOD(task_t
, process_r
, status_t
,
892 private_quick_mode_t
*this, message_t
*message
)
898 sa_payload_t
*sa_payload
;
899 linked_list_t
*tsi
, *tsr
, *hostsi
, *hostsr
, *list
= NULL
;
900 peer_cfg_t
*peer_cfg
;
904 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
905 SECURITY_ASSOCIATION_V1
);
908 DBG1(DBG_IKE
, "sa payload missing");
909 return send_notify(this, INVALID_PAYLOAD_TYPE
);
912 this->mode
= sa_payload
->get_encap_mode(sa_payload
, &this->udp
);
914 if (!get_ts(this, message
))
918 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
919 tsi
= linked_list_create_with_items(this->tsi
, NULL
);
920 tsr
= linked_list_create_with_items(this->tsr
, NULL
);
921 this->tsi
= this->tsr
= NULL
;
922 hostsi
= get_dynamic_hosts(this->ike_sa
, FALSE
);
923 hostsr
= get_dynamic_hosts(this->ike_sa
, TRUE
);
924 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, tsr
, tsi
,
926 hostsi
->destroy(hostsi
);
927 hostsr
->destroy(hostsr
);
930 this->tsi
= select_ts(this, FALSE
, tsi
);
931 this->tsr
= select_ts(this, TRUE
, tsr
);
933 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
934 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
935 if (!this->config
|| !this->tsi
|| !this->tsr
)
937 DBG1(DBG_IKE
, "no matching CHILD_SA config found");
938 return send_notify(this, INVALID_ID_INFORMATION
);
941 if (this->config
->use_ipcomp(this->config
))
943 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
945 DBG1(DBG_IKE
, "IPComp is not supported if either peer is "
946 "natted, IPComp disabled");
950 list
= sa_payload
->get_ipcomp_proposals(sa_payload
,
952 if (!list
->get_count(list
))
954 DBG1(DBG_IKE
, "expected IPComp proposal but peer did "
955 "not send one, IPComp disabled");
960 if (!list
|| !list
->get_count(list
))
963 list
= sa_payload
->get_proposals(sa_payload
);
965 private = this->ike_sa
->supports_extension(this->ike_sa
,
967 this->proposal
= this->config
->select_proposal(this->config
,
968 list
, FALSE
, private);
969 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
972 apply_lifetimes(this, sa_payload
);
976 DBG1(DBG_IKE
, "no matching proposal found, sending %N",
977 notify_type_names
, NO_PROPOSAL_CHOSEN
);
978 return send_notify(this, NO_PROPOSAL_CHOSEN
);
980 this->spi_i
= this->proposal
->get_spi(this->proposal
);
982 if (!get_nonce(this, &this->nonce_i
, message
))
984 return send_notify(this, INVALID_PAYLOAD_TYPE
);
987 if (this->proposal
->get_algorithm(this->proposal
,
988 DIFFIE_HELLMAN_GROUP
, &group
, NULL
))
990 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
994 DBG1(DBG_IKE
, "negotiated DH group %N not supported",
995 diffie_hellman_group_names
, group
);
996 return send_notify(this, INVALID_KEY_INFORMATION
);
998 if (!get_ke(this, message
))
1000 return send_notify(this, INVALID_PAYLOAD_TYPE
);
1004 check_for_rekeyed_child(this);
1006 this->child_sa
= child_sa_create(
1007 this->ike_sa
->get_my_host(this->ike_sa
),
1008 this->ike_sa
->get_other_host(this->ike_sa
),
1009 this->config
, this->reqid
, this->udp
);
1011 tsi
= linked_list_create_with_items(this->tsi
, NULL
);
1012 tsr
= linked_list_create_with_items(this->tsr
, NULL
);
1013 this->tsi
= this->tsr
= NULL
;
1014 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
1015 NARROW_RESPONDER
, tsr
, tsi
);
1016 if (tsi
->remove_first(tsi
, (void**)&this->tsi
) != SUCCESS
||
1017 tsr
->remove_first(tsr
, (void**)&this->tsr
) != SUCCESS
)
1019 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
1020 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
1021 return send_notify(this, INVALID_ID_INFORMATION
);
1023 tsi
->destroy_offset(tsi
, offsetof(traffic_selector_t
, destroy
));
1024 tsr
->destroy_offset(tsr
, offsetof(traffic_selector_t
, destroy
));
1030 if (message
->get_exchange_type(message
) == INFORMATIONAL_V1
||
1031 has_notify_errors(this, message
))
1037 ike_sa_t
*ike_sa
= this->ike_sa
;
1040 task
= (task_t
*)quick_delete_create(this->ike_sa
,
1041 this->proposal
->get_protocol(this->proposal
),
1042 this->spi_i
, TRUE
, TRUE
);
1043 /* flush_queue() destroys the current task */
1044 ike_sa
->flush_queue(ike_sa
, TASK_QUEUE_PASSIVE
);
1045 ike_sa
->queue_task(ike_sa
, task
);
1046 return ALREADY_DONE
;
1055 METHOD(task_t
, build_r
, status_t
,
1056 private_quick_mode_t
*this, message_t
*message
)
1058 switch (this->state
)
1062 sa_payload_t
*sa_payload
;
1064 this->spi_r
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
1067 DBG1(DBG_IKE
, "allocating SPI from kernel failed");
1068 return send_notify(this, NO_PROPOSAL_CHOSEN
);
1070 this->proposal
->set_spi(this->proposal
, this->spi_r
);
1074 this->cpi_r
= this->child_sa
->alloc_cpi(this->child_sa
);
1077 DBG1(DBG_IKE
, "unable to allocate a CPI from "
1078 "kernel, IPComp disabled");
1079 return send_notify(this, NO_PROPOSAL_CHOSEN
);
1083 if (this->udp
&& this->mode
== MODE_TRANSPORT
)
1085 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
1086 add_nat_oa_payloads(this, message
);
1089 sa_payload
= sa_payload_create_from_proposal_v1(this->proposal
,
1090 this->lifetime
, this->lifebytes
, AUTH_NONE
,
1091 this->mode
, this->udp
, this->cpi_r
);
1092 message
->add_payload(message
, &sa_payload
->payload_interface
);
1094 if (!add_nonce(this, &this->nonce_r
, message
))
1100 add_ke(this, message
);
1103 add_ts(this, message
);
1105 this->state
= QM_NEGOTIATED
;
1113 METHOD(task_t
, process_i
, status_t
,
1114 private_quick_mode_t
*this, message_t
*message
)
1116 switch (this->state
)
1120 sa_payload_t
*sa_payload
;
1121 linked_list_t
*list
= NULL
;
1124 sa_payload
= (sa_payload_t
*)message
->get_payload(message
,
1125 SECURITY_ASSOCIATION_V1
);
1128 DBG1(DBG_IKE
, "sa payload missing");
1129 return send_notify(this, NO_PROPOSAL_CHOSEN
);
1133 list
= sa_payload
->get_ipcomp_proposals(sa_payload
,
1135 if (!list
->get_count(list
))
1137 DBG1(DBG_IKE
, "peer did not acccept our IPComp proposal, "
1142 if (!list
|| !list
->get_count(list
))
1145 list
= sa_payload
->get_proposals(sa_payload
);
1147 private = this->ike_sa
->supports_extension(this->ike_sa
,
1149 this->proposal
= this->config
->select_proposal(this->config
,
1150 list
, FALSE
, private);
1151 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
1152 if (!this->proposal
)
1154 DBG1(DBG_IKE
, "no matching proposal found");
1155 return send_notify(this, NO_PROPOSAL_CHOSEN
);
1157 this->spi_r
= this->proposal
->get_spi(this->proposal
);
1159 apply_lifetimes(this, sa_payload
);
1161 if (!get_nonce(this, &this->nonce_r
, message
))
1163 return send_notify(this, INVALID_PAYLOAD_TYPE
);
1165 if (this->dh
&& !get_ke(this, message
))
1167 return send_notify(this, INVALID_KEY_INFORMATION
);
1169 if (!get_ts(this, message
))
1171 return send_notify(this, INVALID_PAYLOAD_TYPE
);
1175 return send_notify(this, NO_PROPOSAL_CHOSEN
);
1177 this->state
= QM_NEGOTIATED
;
1185 METHOD(task_t
, get_type
, task_type_t
,
1186 private_quick_mode_t
*this)
1188 return TASK_QUICK_MODE
;
1191 METHOD(quick_mode_t
, use_reqid
, void,
1192 private_quick_mode_t
*this, u_int32_t reqid
)
1194 this->reqid
= reqid
;
1197 METHOD(quick_mode_t
, rekey
, void,
1198 private_quick_mode_t
*this, u_int32_t spi
)
1203 METHOD(task_t
, migrate
, void,
1204 private_quick_mode_t
*this, ike_sa_t
*ike_sa
)
1206 chunk_free(&this->nonce_i
);
1207 chunk_free(&this->nonce_r
);
1208 DESTROY_IF(this->tsi
);
1209 DESTROY_IF(this->tsr
);
1210 DESTROY_IF(this->proposal
);
1211 DESTROY_IF(this->child_sa
);
1212 DESTROY_IF(this->dh
);
1214 this->ike_sa
= ike_sa
;
1215 this->keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
1216 this->state
= QM_INIT
;
1219 this->proposal
= NULL
;
1220 this->child_sa
= NULL
;
1225 if (!this->initiator
)
1227 DESTROY_IF(this->config
);
1228 this->config
= NULL
;
1232 METHOD(task_t
, destroy
, void,
1233 private_quick_mode_t
*this)
1235 chunk_free(&this->nonce_i
);
1236 chunk_free(&this->nonce_r
);
1237 DESTROY_IF(this->tsi
);
1238 DESTROY_IF(this->tsr
);
1239 DESTROY_IF(this->proposal
);
1240 DESTROY_IF(this->child_sa
);
1241 DESTROY_IF(this->config
);
1242 DESTROY_IF(this->dh
);
1247 * Described in header.
1249 quick_mode_t
*quick_mode_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
,
1250 traffic_selector_t
*tsi
, traffic_selector_t
*tsr
)
1252 private_quick_mode_t
*this;
1257 .get_type
= _get_type
,
1258 .migrate
= _migrate
,
1259 .destroy
= _destroy
,
1261 .use_reqid
= _use_reqid
,
1265 .initiator
= config
!= NULL
,
1267 .keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
),
1269 .tsi
= tsi ? tsi
->clone(tsi
) : NULL
,
1270 .tsr
= tsr ? tsr
->clone(tsr
) : NULL
,
1275 this->public.task
.build
= _build_i
;
1276 this->public.task
.process
= _process_i
;
1280 this->public.task
.build
= _build_r
;
1281 this->public.task
.process
= _process_r
;
1284 return &this->public;