payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
index 52ea34b..e627368 100644 (file)
@@ -165,6 +165,11 @@ struct private_quick_mode_t {
         */
        ipsec_mode_t mode;
 
+       /*
+        * SA protocol (ESP|AH) negotiated
+        */
+       protocol_id_t proto;
+
        /**
         * Use UDP encapsulation
         */
@@ -189,7 +194,7 @@ static void schedule_inactivity_timeout(private_quick_mode_t *this)
        if (timeout)
        {
                close_ike = lib->settings->get_bool(lib->settings,
-                                                               "%s.inactivity_close_ike", FALSE, charon->name);
+                                                                       "%s.inactivity_close_ike", FALSE, lib->ns);
                lib->scheduler->schedule_job(lib->scheduler, (job_t*)
                                inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
                                                                          timeout, close_ike), timeout);
@@ -259,7 +264,7 @@ static bool install(private_quick_mode_t *this)
 {
        status_t status, status_i, status_o;
        chunk_t encr_i, encr_r, integ_i, integ_r;
-       linked_list_t *tsi, *tsr;
+       linked_list_t *tsi, *tsr, *my_ts, *other_ts;
        child_sa_t *old = NULL;
 
        this->child_sa->set_proposal(this->child_sa, this->proposal);
@@ -362,14 +367,20 @@ static bool install(private_quick_mode_t *this)
        this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
        this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
 
+       my_ts = linked_list_create_from_enumerator(
+                               this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
+       other_ts = linked_list_create_from_enumerator(
+                               this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
+
        DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
                 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
                 this->child_sa->get_name(this->child_sa),
                 this->child_sa->get_reqid(this->child_sa),
                 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
-                ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
-                this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
-                this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+                ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts);
+
+       my_ts->destroy(my_ts);
+       other_ts->destroy(other_ts);
 
        if (this->rekey)
        {
@@ -416,7 +427,7 @@ static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
        }
        nonceg->destroy(nonceg);
 
-       nonce_payload = nonce_payload_create(NONCE_V1);
+       nonce_payload = nonce_payload_create(PLV1_NONCE);
        nonce_payload->set_nonce(nonce_payload, *nonce);
        message->add_payload(message, &nonce_payload->payload_interface);
 
@@ -431,7 +442,7 @@ static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
 {
        nonce_payload_t *nonce_payload;
 
-       nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+       nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
        if (!nonce_payload)
        {
                DBG1(DBG_IKE, "NONCE payload missing in message");
@@ -449,7 +460,7 @@ static void add_ke(private_quick_mode_t *this, message_t *message)
 {
        ke_payload_t *ke_payload;
 
-       ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
+       ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, this->dh);
        message->add_payload(message, &ke_payload->payload_interface);
 }
 
@@ -460,7 +471,7 @@ static bool get_ke(private_quick_mode_t *this, message_t *message)
 {
        ke_payload_t *ke_payload;
 
-       ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
+       ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
        if (!ke_payload)
        {
                DBG1(DBG_IKE, "KE payload missing");
@@ -491,7 +502,7 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
        else
        {
                DBG1(DBG_IKE, "%s traffic selector missing in configuration",
-                        local ? "local" : "local");
+                        local ? "local" : "remote");
                ts = NULL;
        }
        list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
@@ -504,33 +515,11 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
 static void add_ts(private_quick_mode_t *this, message_t *message)
 {
        id_payload_t *id_payload;
-       host_t *hsi, *hsr;
 
-       if (this->initiator)
-       {
-               hsi = this->ike_sa->get_my_host(this->ike_sa);
-               hsr = this->ike_sa->get_other_host(this->ike_sa);
-       }
-       else
-       {
-               hsr = this->ike_sa->get_my_host(this->ike_sa);
-               hsi = this->ike_sa->get_other_host(this->ike_sa);
-       }
-       /* add ID payload only if negotiating non host2host tunnels */
-       if (!this->tsi->is_host(this->tsi, hsi) ||
-               !this->tsr->is_host(this->tsr, hsr) ||
-               this->tsi->get_protocol(this->tsi) ||
-               this->tsr->get_protocol(this->tsr) ||
-               this->tsi->get_from_port(this->tsi) ||
-               this->tsr->get_from_port(this->tsr) ||
-               this->tsi->get_to_port(this->tsi) != 65535 ||
-               this->tsr->get_to_port(this->tsr) != 65535)
-       {
-               id_payload = id_payload_create_from_ts(this->tsi);
-               message->add_payload(message, &id_payload->payload_interface);
-               id_payload = id_payload_create_from_ts(this->tsr);
-               message->add_payload(message, &id_payload->payload_interface);
-       }
+       id_payload = id_payload_create_from_ts(this->tsi);
+       message->add_payload(message, &id_payload->payload_interface);
+       id_payload = id_payload_create_from_ts(this->tsr);
+       message->add_payload(message, &id_payload->payload_interface);
 }
 
 /**
@@ -548,7 +537,7 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
        enumerator = message->create_payload_enumerator(message);
        while (enumerator->enumerate(enumerator, &payload))
        {
-               if (payload->get_type(payload) == ID_V1)
+               if (payload->get_type(payload) == PLV1_ID)
                {
                        id_payload = (id_payload_t*)payload;
 
@@ -651,9 +640,9 @@ static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
 {
        if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
        {
-               return NAT_OA_DRAFT_00_03_V1;
+               return PLV1_NAT_OA_DRAFT_00_03;
        }
-       return NAT_OA_V1;
+       return PLV1_NAT_OA;
 }
 
 /**
@@ -737,8 +726,8 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
 {
        notify_payload_t *notify;
 
-       notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
-                                                                                                                 PROTO_ESP, type);
+       notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
+                                                                                                                 this->proto, type);
        notify->set_spi(notify, this->spi_i);
 
        this->ike_sa->queue_task(this->ike_sa,
@@ -749,6 +738,38 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
        return ALREADY_DONE;
 }
 
+/**
+ * Prepare a list of proposals from child_config containing only the specified
+ * DH group, unless it is set to MODP_NONE.
+ */
+static linked_list_t *get_proposals(private_quick_mode_t *this,
+                                                                       diffie_hellman_group_t group)
+{
+       linked_list_t *list;
+       proposal_t *proposal;
+       enumerator_t *enumerator;
+
+       list = this->config->get_proposals(this->config, FALSE);
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &proposal))
+       {
+               if (group != MODP_NONE)
+               {
+                       if (!proposal->has_dh_group(proposal, group))
+                       {
+                               list->remove_at(list, enumerator);
+                               proposal->destroy(proposal);
+                               continue;
+                       }
+                       proposal->strip_dh(proposal, group);
+               }
+               proposal->set_spi(proposal, this->spi_i);
+       }
+       enumerator->destroy(enumerator);
+
+       return list;
+}
+
 METHOD(task_t, build_i, status_t,
        private_quick_mode_t *this, message_t *message)
 {
@@ -756,7 +777,6 @@ METHOD(task_t, build_i, status_t,
        {
                case QM_INIT:
                {
-                       enumerator_t *enumerator;
                        sa_payload_t *sa_payload;
                        linked_list_t *list, *tsi, *tsr;
                        proposal_t *proposal;
@@ -786,42 +806,55 @@ METHOD(task_t, build_i, status_t,
                                }
                        }
 
-                       this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+                       list = this->config->get_proposals(this->config, MODP_NONE);
+                       if (list->get_first(list, (void**)&proposal) == SUCCESS)
+                       {
+                               this->proto = proposal->get_protocol(proposal);
+                       }
+                       list->destroy_offset(list, offsetof(proposal_t, destroy));
+                       this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto);
                        if (!this->spi_i)
                        {
                                DBG1(DBG_IKE, "allocating SPI from kernel failed");
                                return FAILED;
                        }
+
                        group = this->config->get_dh_group(this->config);
                        if (group != MODP_NONE)
                        {
+                               proposal_t *proposal;
+                               u_int16_t preferred_group;
+
+                               proposal = this->ike_sa->get_proposal(this->ike_sa);
+                               proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+                                                                               &preferred_group, NULL);
+                               /* try the negotiated DH group from IKE_SA */
+                               list = get_proposals(this, preferred_group);
+                               if (list->get_count(list))
+                               {
+                                       group = preferred_group;
+                               }
+                               else
+                               {
+                                       /* fall back to the first configured DH group */
+                                       list->destroy(list);
+                                       list = get_proposals(this, group);
+                               }
+
                                this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
                                                                                                                  group);
                                if (!this->dh)
                                {
                                        DBG1(DBG_IKE, "configured DH group %N not supported",
                                                 diffie_hellman_group_names, group);
+                                       list->destroy_offset(list, offsetof(proposal_t, destroy));
                                        return FAILED;
                                }
                        }
-
-                       list = this->config->get_proposals(this->config, FALSE);
-                       enumerator = list->create_enumerator(list);
-                       while (enumerator->enumerate(enumerator, &proposal))
+                       else
                        {
-                               if (group != MODP_NONE)
-                               {
-                                       if (!proposal->has_dh_group(proposal, group))
-                                       {
-                                               list->remove_at(list, enumerator);
-                                               proposal->destroy(proposal);
-                                               continue;
-                                       }
-                                       proposal->strip_dh(proposal, group);
-                               }
-                               proposal->set_spi(proposal, this->spi_i);
+                               list = get_proposals(this, MODP_NONE);
                        }
-                       enumerator->destroy(enumerator);
 
                        get_lifetimes(this);
                        encap = get_encap(this->ike_sa, this->udp);
@@ -884,7 +917,7 @@ static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
        enumerator = message->create_payload_enumerator(message);
        while (enumerator->enumerate(enumerator, &payload))
        {
-               if (payload->get_type(payload) == NOTIFY_V1)
+               if (payload->get_type(payload) == PLV1_NOTIFY)
                {
                        notify_payload_t *notify;
                        notify_type_t type;
@@ -967,7 +1000,7 @@ METHOD(task_t, process_r, status_t,
                        bool private;
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
-                                                                                                       SECURITY_ASSOCIATION_V1);
+                                                                                                       PLV1_SECURITY_ASSOCIATION);
                        if (!sa_payload)
                        {
                                DBG1(DBG_IKE, "sa payload missing");
@@ -1119,7 +1152,8 @@ METHOD(task_t, build_r, status_t,
                        sa_payload_t *sa_payload;
                        encap_t encap;
 
-                       this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+                       this->proto = this->proposal->get_protocol(this->proposal);
+                       this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto);
                        if (!this->spi_r)
                        {
                                DBG1(DBG_IKE, "allocating SPI from kernel failed");
@@ -1181,7 +1215,7 @@ METHOD(task_t, process_i, status_t,
                        bool private;
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
-                                                                                                       SECURITY_ASSOCIATION_V1);
+                                                                                                       PLV1_SECURITY_ASSOCIATION);
                        if (!sa_payload)
                        {
                                DBG1(DBG_IKE, "sa payload missing");
@@ -1327,6 +1361,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
                .state = QM_INIT,
                .tsi = tsi ? tsi->clone(tsi) : NULL,
                .tsr = tsr ? tsr->clone(tsr) : NULL,
+               .proto = PROTO_ESP,
        );
 
        if (config)