ikev2: fix possible SEGV
[vpp.git] / src / plugins / ikev2 / ikev2.c
index b521104..5c1aa58 100644 (file)
@@ -1367,7 +1367,6 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
   int p = 0;
   u8 payload = ike->nextpayload;
   u8 *plaintext = 0;
-  u8 rekeying = 0;
   ikev2_rekey_t *rekey;
   ike_payload_header_t *ikep;
   ikev2_notify_t *n = 0;
@@ -1410,11 +1409,15 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
        }
       else if (payload == IKEV2_PAYLOAD_NOTIFY)
        {
-         n = ikev2_parse_notify_payload (ikep, current_length);
-         if (n->msg_type == IKEV2_NOTIFY_MSG_REKEY_SA)
+         ikev2_notify_t *n0;
+         n0 = ikev2_parse_notify_payload (ikep, current_length);
+         if (n0->msg_type == IKEV2_NOTIFY_MSG_REKEY_SA)
            {
-             rekeying = 1;
+             vec_free (n);
+             n = n0;
            }
+         else
+           vec_free (n0);
        }
       else if (payload == IKEV2_PAYLOAD_DELETE)
        {
@@ -1460,6 +1463,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
       rekey = sa->rekey;
       if (vec_len (rekey) == 0)
        goto cleanup_and_exit;
+      rekey->notify_type = 0;
       rekey->protocol_id = proposal->protocol_id;
       rekey->i_proposal =
        ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
@@ -1478,7 +1482,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
     }
   else
     {
-      if (rekeying)
+      if (n)
        {
          child_sa = ikev2_sa_get_child (sa, n->spi, n->protocol_id, 1);
          if (!child_sa)
@@ -1488,22 +1492,34 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
              goto cleanup_and_exit;
            }
          vec_add2 (sa->rekey, rekey, 1);
+         rekey->notify_type = 0;
          rekey->protocol_id = n->protocol_id;
          rekey->spi = n->spi;
-         rekey->i_proposal = proposal;
-         rekey->r_proposal =
-           ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
-         /* update Ni */
-         vec_reset_length (sa->i_nonce);
-         vec_add (sa->i_nonce, nonce, nonce_len);
-         /* generate new Nr */
-         vec_validate (sa->r_nonce, nonce_len - 1);
-         RAND_bytes ((u8 *) sa->r_nonce, nonce_len);
+         if (sa->old_remote_id_present)
+           {
+             rekey->notify_type = IKEV2_NOTIFY_MSG_TEMPORARY_FAILURE;
+             vec_free (proposal);
+             vec_free (tsr);
+             vec_free (tsi);
+           }
+         else
+           {
+             rekey->i_proposal = proposal;
+             rekey->r_proposal =
+               ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
+             /* update Ni */
+             vec_reset_length (sa->i_nonce);
+             vec_add (sa->i_nonce, nonce, nonce_len);
+             /* generate new Nr */
+             vec_validate (sa->r_nonce, nonce_len - 1);
+             RAND_bytes ((u8 *) sa->r_nonce, nonce_len);
+           }
        }
       else
        {
          /* create new child SA */
          vec_add2 (sa->new_child, rekey, 1);
+         rekey->notify_type = 0;
          rekey->i_proposal = proposal;
          rekey->r_proposal =
            ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
@@ -1910,8 +1926,8 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
     .t_mode = TUNNEL_MODE_P2P,
     .t_table_id = 0,
     .t_hop_limit = 255,
-    .t_src = a->local_ip,
-    .t_dst = a->remote_ip,
+    .t_src = a->remote_ip,
+    .t_dst = a->local_ip,
   };
   tunnel_t tun_out = {
     .t_flags = TUNNEL_FLAG_NONE,
@@ -1920,8 +1936,8 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
     .t_mode = TUNNEL_MODE_P2P,
     .t_table_id = 0,
     .t_hop_limit = 255,
-    .t_src = a->remote_ip,
-    .t_dst = a->local_ip,
+    .t_src = a->local_ip,
+    .t_dst = a->remote_ip,
   };
 
   if (~0 == a->sw_if_index)
@@ -2552,10 +2568,17 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
        }
       else if (vec_len (sa->rekey) > 0)
        {
-         ikev2_payload_add_sa (chain, sa->rekey[0].r_proposal);
-         ikev2_payload_add_nonce (chain, sa->r_nonce);
-         ikev2_payload_add_ts (chain, sa->rekey[0].tsi, IKEV2_PAYLOAD_TSI);
-         ikev2_payload_add_ts (chain, sa->rekey[0].tsr, IKEV2_PAYLOAD_TSR);
+         if (sa->rekey[0].notify_type)
+           ikev2_payload_add_notify (chain, sa->rekey[0].notify_type, 0);
+         else
+           {
+             ikev2_payload_add_sa (chain, sa->rekey[0].r_proposal);
+             ikev2_payload_add_nonce (chain, sa->r_nonce);
+             ikev2_payload_add_ts (chain, sa->rekey[0].tsi,
+                                   IKEV2_PAYLOAD_TSI);
+             ikev2_payload_add_ts (chain, sa->rekey[0].tsr,
+                                   IKEV2_PAYLOAD_TSR);
+           }
          vec_del1 (sa->rekey, 0);
        }
       else if (vec_len (sa->new_child) > 0)
@@ -3315,11 +3338,12 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                  goto dispatch0;
                }
 
-             if (sa0->rekey)
+             if (vec_len (sa0->rekey) > 0)
                {
-                 if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
+                 if (!sa0->rekey[0].notify_type &&
+                     sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
                    {
-                     if (sa0->childs)
+                     if (vec_len (sa0->childs) > 0)
                        ikev2_sa_free_all_child_sa (&sa0->childs);
                      ikev2_child_sa_t *child;
                      vec_add2 (sa0->childs, child, 1);
@@ -3348,7 +3372,7 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                                                     1);
                    }
                }
-             else if (sa0->new_child)
+             else if (vec_len (sa0->new_child) > 0)
                {
                  ikev2_child_sa_t *c;
                  vec_add2 (sa0->childs, c, 1);