payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
index afdff8c..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);
@@ -306,17 +311,21 @@ static bool install(private_quick_mode_t *this)
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
-                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, TRUE, FALSE, tsi, tsr);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, FALSE, FALSE, tsi, tsr);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
-                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, TRUE, FALSE, tsr, tsi);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, FALSE, FALSE, tsr, tsi);
                }
        }
        chunk_clear(&integ_i);
@@ -358,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)
        {
@@ -412,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);
 
@@ -427,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");
@@ -445,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);
 }
 
@@ -456,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");
@@ -487,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));
@@ -500,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);
 }
 
 /**
@@ -544,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;
 
@@ -647,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;
 }
 
 /**
@@ -733,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,
@@ -745,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)
 {
@@ -752,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;
@@ -774,58 +798,63 @@ METHOD(task_t, build_i, status_t,
 
                        if (this->config->use_ipcomp(this->config))
                        {
-                               if (this->udp)
-                               {
-                                       DBG1(DBG_IKE, "IPComp is not supported if either peer is "
-                                                "natted, IPComp disabled");
-                               }
-                               else
+                               this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
+                               if (!this->cpi_i)
                                {
-                                       this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
-                                       if (!this->cpi_i)
-                                       {
-                                               DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
-                                                        "IPComp disabled");
-                                       }
+                                       DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
+                                                "IPComp disabled");
                                }
                        }
 
-                       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);
@@ -888,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;
@@ -921,30 +950,37 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
        enumerator_t *enumerator, *policies;
        traffic_selector_t *local, *remote;
        child_sa_t *child_sa;
+       proposal_t *proposal;
+       char *name;
 
+       name = this->config->get_name(this->config);
        enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
        while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
        {
-               if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
-                       streq(child_sa->get_name(child_sa),
-                                 this->config->get_name(this->config)))
+               if (streq(child_sa->get_name(child_sa), name))
                {
-                       policies = child_sa->create_policy_enumerator(child_sa);
-                       if (policies->enumerate(policies, &local, &remote))
+                       proposal = child_sa->get_proposal(child_sa);
+                       switch (child_sa->get_state(child_sa))
                        {
-                               if (local->equals(local, this->tsr) &&
-                                       remote->equals(remote, this->tsi) &&
-                                       this->proposal->equals(this->proposal,
-                                                                                  child_sa->get_proposal(child_sa)))
-                               {
-                                       this->reqid = child_sa->get_reqid(child_sa);
-                                       this->rekey = child_sa->get_spi(child_sa, TRUE);
-                                       child_sa->set_state(child_sa, CHILD_REKEYING);
-                                       DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
-                                                child_sa->get_name(child_sa), this->reqid);
-                               }
+                               case CHILD_INSTALLED:
+                               case CHILD_REKEYING:
+                                       policies = child_sa->create_policy_enumerator(child_sa);
+                                       if (policies->enumerate(policies, &local, &remote) &&
+                                               local->equals(local, this->tsr) &&
+                                               remote->equals(remote, this->tsi) &&
+                                               this->proposal->equals(this->proposal, proposal))
+                                       {
+                                               this->reqid = child_sa->get_reqid(child_sa);
+                                               this->rekey = child_sa->get_spi(child_sa, TRUE);
+                                               child_sa->set_state(child_sa, CHILD_REKEYING);
+                                               DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
+                                                        child_sa->get_name(child_sa), this->reqid);
+                                       }
+                                       policies->destroy(policies);
+                               break;
+                       default:
+                               break;
                        }
-                       policies->destroy(policies);
                }
        }
        enumerator->destroy(enumerator);
@@ -964,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");
@@ -1002,21 +1038,13 @@ METHOD(task_t, process_r, status_t,
 
                        if (this->config->use_ipcomp(this->config))
                        {
-                               if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
-                               {
-                                       DBG1(DBG_IKE, "IPComp is not supported if either peer is "
-                                                "natted, IPComp disabled");
-                               }
-                               else
+                               list = sa_payload->get_ipcomp_proposals(sa_payload,
+                                                                                                               &this->cpi_i);
+                               if (!list->get_count(list))
                                {
-                                       list = sa_payload->get_ipcomp_proposals(sa_payload,
-                                                                                                                       &this->cpi_i);
-                                       if (!list->get_count(list))
-                                       {
-                                               DBG1(DBG_IKE, "expected IPComp proposal but peer did "
-                                                        "not send one, IPComp disabled");
-                                               this->cpi_i = 0;
-                                       }
+                                       DBG1(DBG_IKE, "expected IPComp proposal but peer did "
+                                                "not send one, IPComp disabled");
+                                       this->cpi_i = 0;
                                }
                        }
                        if (!list || !list->get_count(list))
@@ -1124,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");
@@ -1186,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");
@@ -1332,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)