Extended nonce payload for IKEv1 support
[strongswan.git] / src / libcharon / sa / tasks / child_create.c
index 3de27ee..587e37a 100644 (file)
@@ -117,6 +117,11 @@ struct private_child_create_t {
        ipsec_mode_t mode;
 
        /**
+        * peer accepts TFC padding for this SA
+        */
+       bool tfcv3;
+
+       /**
         * IPComp transform to use
         */
        ipcomp_transform_t ipcomp;
@@ -208,13 +213,13 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host)
 {
        traffic_selector_t *ts;
        bool is_host = TRUE;
-       iterator_t *iterator = list->create_iterator(list, TRUE);
+       enumerator_t *enumerator = list->create_enumerator(list);
 
-       while (is_host && iterator->iterate(iterator, (void**)&ts))
+       while (is_host && enumerator->enumerate(enumerator, (void**)&ts))
        {
                is_host = is_host && ts->is_host(ts, host);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        return is_host;
 }
 
@@ -261,7 +266,7 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
        {
                close_ike = lib->settings->get_bool(lib->settings,
                                                                                "charon.inactivity_close_ike", FALSE);
-               charon->scheduler->schedule_job(charon->scheduler, (job_t*)
+               lib->scheduler->schedule_job(lib->scheduler, (job_t*)
                                inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
                                                                          timeout, close_ike), timeout);
        }
@@ -455,17 +460,21 @@ static status_t select_and_install(private_child_create_t *this,
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                       this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                       this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                       encr_r, integ_r, this->my_spi, this->my_cpi,
+                                                       TRUE, this->tfcv3, my_ts, other_ts);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                       encr_i, integ_i, this->other_spi, this->other_cpi,
+                                                       FALSE, this->tfcv3, my_ts, other_ts);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                       this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                       this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                       encr_i, integ_i, this->my_spi, this->my_cpi,
+                                                       TRUE, this->tfcv3, my_ts, other_ts);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                       encr_r, integ_r, this->other_spi, this->other_cpi,
+                                                       FALSE, this->tfcv3, my_ts, other_ts);
                }
        }
        chunk_clear(&integ_i);
@@ -517,18 +526,20 @@ static void build_payloads(private_child_create_t *this, message_t *message)
        /* add SA payload */
        if (this->initiator)
        {
-               sa_payload = sa_payload_create_from_proposal_list(this->proposals);
+               sa_payload = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION,
+                                                                                                                 this->proposals);
        }
        else
        {
-               sa_payload = sa_payload_create_from_proposal(this->proposal);
+               sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION,
+                                                                                                        this->proposal);
        }
        message->add_payload(message, (payload_t*)sa_payload);
 
        /* add nonce payload if not in IKE_AUTH */
        if (message->get_exchange_type(message) == CREATE_CHILD_SA)
        {
-               nonce_payload = nonce_payload_create();
+               nonce_payload = nonce_payload_create(NONCE);
                nonce_payload->set_nonce(nonce_payload, this->my_nonce);
                message->add_payload(message, (payload_t*)nonce_payload);
        }
@@ -631,7 +642,13 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
                                                 ipcomp_transform_names, ipcomp);
                                        break;
                        }
+                       break;
                }
+               case ESP_TFC_PADDING_NOT_SUPPORTED:
+                       DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding",
+                                notify_type_names, notify->get_notify_type(notify));
+                       this->tfcv3 = FALSE;
+                       break;
                default:
                        break;
        }
@@ -691,10 +708,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
        enumerator->destroy(enumerator);
 }
 
-/**
- * Implementation of task_t.build for initiator
- */
-static status_t build_i(private_child_create_t *this, message_t *message)
+METHOD(task_t, build_i, status_t,
+       private_child_create_t *this, message_t *message)
 {
        host_t *me, *other, *vip;
        peer_cfg_t *peer_cfg;
@@ -831,10 +846,8 @@ static status_t build_i(private_child_create_t *this, message_t *message)
        return NEED_MORE;
 }
 
-/**
- * Implementation of task_t.process for responder
- */
-static status_t process_r(private_child_create_t *this, message_t *message)
+METHOD(task_t, process_r, status_t,
+       private_child_create_t *this, message_t *message)
 {
        switch (message->get_exchange_type(message))
        {
@@ -871,16 +884,18 @@ static void handle_child_sa_failure(private_child_create_t *this,
                /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
                 * first */
                DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
-               charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
+               lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
                        delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
                        100);
        }
+       else
+       {
+               DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
+       }
 }
 
-/**
- * Implementation of task_t.build for responder
- */
-static status_t build_r(private_child_create_t *this, message_t *message)
+METHOD(task_t, build_r, status_t,
+       private_child_create_t *this, message_t *message)
 {
        peer_cfg_t *peer_cfg;
        payload_t *payload;
@@ -958,7 +973,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
                                case INTERNAL_ADDRESS_FAILURE:
                                case FAILED_CP_REQUIRED:
                                {
-                                       DBG1(DBG_IKE,"configuration payload negotation "
+                                       DBG1(DBG_IKE,"configuration payload negotiation "
                                                 "failed, no CHILD_SA built");
                                        enumerator->destroy(enumerator);
                                        handle_child_sa_failure(this, message);
@@ -1029,10 +1044,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
        return SUCCESS;
 }
 
-/**
- * Implementation of task_t.process for initiator
- */
-static status_t process_i(private_child_create_t *this, message_t *message)
+METHOD(task_t, process_i, status_t,
+       private_child_create_t *this, message_t *message)
 {
        enumerator_t *enumerator;
        payload_t *payload;
@@ -1103,7 +1116,21 @@ static status_t process_i(private_child_create_t *this, message_t *message)
                                        return NEED_MORE;
                                }
                                default:
+                               {
+                                       if (message->get_exchange_type(message) == CREATE_CHILD_SA)
+                                       {       /* handle notifies if not handled in IKE_AUTH */
+                                               if (type <= 16383)
+                                               {
+                                                       DBG1(DBG_IKE, "received %N notify error",
+                                                                notify_type_names, type);
+                                                       enumerator->destroy(enumerator);
+                                                       return SUCCESS;
+                                               }
+                                               DBG2(DBG_IKE, "received %N notify",
+                                                        notify_type_names, type);
+                                       }
                                        break;
+                               }
                        }
                }
        }
@@ -1155,34 +1182,20 @@ static status_t process_i(private_child_create_t *this, message_t *message)
        return SUCCESS;
 }
 
-/**
- * Implementation of task_t.get_type
- */
-static task_type_t get_type(private_child_create_t *this)
-{
-       return CHILD_CREATE;
-}
-
-/**
- * Implementation of child_create_t.use_reqid
- */
-static void use_reqid(private_child_create_t *this, u_int32_t reqid)
+METHOD(child_create_t, use_reqid, void,
+       private_child_create_t *this, u_int32_t reqid)
 {
        this->reqid = reqid;
 }
 
-/**
- * Implementation of child_create_t.get_child
- */
-static child_sa_t* get_child(private_child_create_t *this)
+METHOD(child_create_t, get_child, child_sa_t*,
+       private_child_create_t *this)
 {
        return this->child_sa;
 }
 
-/**
- * Implementation of child_create_t.get_lower_nonce
- */
-static chunk_t get_lower_nonce(private_child_create_t *this)
+METHOD(child_create_t, get_lower_nonce, chunk_t,
+       private_child_create_t *this)
 {
        if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
                           min(this->my_nonce.len, this->other_nonce.len)) < 0)
@@ -1195,10 +1208,14 @@ static chunk_t get_lower_nonce(private_child_create_t *this)
        }
 }
 
-/**
- * Implementation of task_t.migrate
- */
-static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
+METHOD(task_t, get_type, task_type_t,
+       private_child_create_t *this)
+{
+       return CHILD_CREATE;
+}
+
+METHOD(task_t, migrate, void,
+       private_child_create_t *this, ike_sa_t *ike_sa)
 {
        chunk_free(&this->my_nonce);
        chunk_free(&this->other_nonce);
@@ -1234,10 +1251,8 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
        this->established = FALSE;
 }
 
-/**
- * Implementation of task_t.destroy
- */
-static void destroy(private_child_create_t *this)
+METHOD(task_t, destroy, void,
+       private_child_create_t *this)
 {
        chunk_free(&this->my_nonce);
        chunk_free(&this->other_nonce);
@@ -1273,52 +1288,45 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
                                                        child_cfg_t *config, bool rekey,
                                                        traffic_selector_t *tsi, traffic_selector_t *tsr)
 {
-       private_child_create_t *this = malloc_thing(private_child_create_t);
-
-       this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
-       this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
-       this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
-       this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
-       this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
-       this->public.task.destroy = (void(*)(task_t*))destroy;
+       private_child_create_t *this;
+
+       INIT(this,
+               .public = {
+                       .get_child = _get_child,
+                       .get_lower_nonce = _get_lower_nonce,
+                       .use_reqid = _use_reqid,
+                       .task = {
+                               .get_type = _get_type,
+                               .migrate = _migrate,
+                               .destroy = _destroy,
+                       },
+               },
+               .ike_sa = ike_sa,
+               .config = config,
+               .packet_tsi = tsi ? tsi->clone(tsi) : NULL,
+               .packet_tsr = tsr ? tsr->clone(tsr) : NULL,
+               .dh_group = MODP_NONE,
+               .keymat = ike_sa->get_keymat(ike_sa),
+               .mode = MODE_TUNNEL,
+               .tfcv3 = TRUE,
+               .ipcomp = IPCOMP_NONE,
+               .ipcomp_received = IPCOMP_NONE,
+               .rekey = rekey,
+       );
+
        if (config)
        {
-               this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
-               this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
+               this->public.task.build = _build_i;
+               this->public.task.process = _process_i;
                this->initiator = TRUE;
                config->get_ref(config);
        }
        else
        {
-               this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
-               this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
+               this->public.task.build = _build_r;
+               this->public.task.process = _process_r;
                this->initiator = FALSE;
        }
 
-       this->ike_sa = ike_sa;
-       this->config = config;
-       this->my_nonce = chunk_empty;
-       this->other_nonce = chunk_empty;
-       this->proposals = NULL;
-       this->proposal = NULL;
-       this->tsi = NULL;
-       this->tsr = NULL;
-       this->packet_tsi = tsi ? tsi->clone(tsi) : NULL;
-       this->packet_tsr = tsr ? tsr->clone(tsr) : NULL;
-       this->dh = NULL;
-       this->dh_group = MODP_NONE;
-       this->keymat = ike_sa->get_keymat(ike_sa);
-       this->child_sa = NULL;
-       this->mode = MODE_TUNNEL;
-       this->ipcomp = IPCOMP_NONE;
-       this->ipcomp_received = IPCOMP_NONE;
-       this->my_spi = 0;
-       this->other_spi = 0;
-       this->my_cpi = 0;
-       this->other_cpi = 0;
-       this->reqid = 0;
-       this->established = FALSE;
-       this->rekey = rekey;
-
        return &this->public;
 }