ikev2: better handling when no IKE DH configured 22/30122/3
authorFilip Tehlar <ftehlar@cisco.com>
Sat, 21 Nov 2020 21:30:45 +0000 (21:30 +0000)
committerFilip Tehlar <ftehlar@cisco.com>
Thu, 26 Nov 2020 12:18:56 +0000 (12:18 +0000)
Type: improvement

Change-Id: I4289d20adaa3f2872889d5dbaafd9c025df8aca8
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2_api.c

index 31d6d43..336f896 100644 (file)
@@ -61,6 +61,37 @@ format_ikev2_trace (u8 * s, va_list * args)
   return s;
 }
 
+#define IKEV2_GENERATE_SA_INIT_OK_str ""
+#define IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR \
+  "no DH group configured for IKE proposals!"
+#define IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR \
+  "DH group not supported!"
+
+typedef enum
+{
+  IKEV2_GENERATE_SA_INIT_OK,
+  IKEV2_GENERATE_SA_INIT_ERR_NO_DH,
+  IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH,
+} ikev2_generate_sa_error_t;
+
+static u8 *
+format_ikev2_gen_sa_error (u8 * s, va_list * args)
+{
+  ikev2_generate_sa_error_t e = va_arg (*args, ikev2_generate_sa_error_t);
+  switch (e)
+    {
+    case IKEV2_GENERATE_SA_INIT_OK:
+      break;
+    case IKEV2_GENERATE_SA_INIT_ERR_NO_DH:
+      s = format (s, IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR);
+      break;
+    case IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH:
+      s = format (s, IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR);
+      break;
+    }
+  return s;
+}
+
 #define foreach_ikev2_error \
 _(PROCESSED, "IKEv2 packets processed") \
 _(IKE_SA_INIT_RETRANSMIT, "IKE_SA_INIT retransmit ") \
@@ -357,16 +388,14 @@ ikev2_delete_sa (ikev2_main_per_thread_data_t * ptd, ikev2_sa_t * sa)
     }
 }
 
-static void
+static ikev2_generate_sa_error_t
 ikev2_generate_sa_init_data (ikev2_sa_t * sa)
 {
   ikev2_sa_transform_t *t = 0, *t2;
   ikev2_main_t *km = &ikev2_main;
 
   if (sa->dh_group == IKEV2_TRANSFORM_DH_TYPE_NONE)
-    {
-      return;
-    }
+    return IKEV2_GENERATE_SA_INIT_ERR_NO_DH;
 
   /* check if received DH group is on our list of supported groups */
   vec_foreach (t2, km->supported_transforms)
@@ -381,7 +410,7 @@ ikev2_generate_sa_init_data (ikev2_sa_t * sa)
   if (!t)
     {
       sa->dh_group = IKEV2_TRANSFORM_DH_TYPE_NONE;
-      return;
+      return IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH;
     }
 
   if (sa->is_initiator)
@@ -406,6 +435,7 @@ ikev2_generate_sa_init_data (ikev2_sa_t * sa)
   /* generate dh keys */
   ikev2_generate_dh (sa, t);
 
+  return IKEV2_GENERATE_SA_INIT_OK;
 }
 
 static void
@@ -2788,6 +2818,20 @@ ikev2_elog_uint_peers_addr (u32 exchange, ip4_header_t * ip4,
                         exchange, src, dst);
 }
 
+static void
+ikev2_generate_sa_init_data_and_log (ikev2_sa_t * sa)
+{
+  ikev2_generate_sa_error_t rc = ikev2_generate_sa_init_data (sa);
+
+  if (PREDICT_TRUE (rc == IKEV2_GENERATE_SA_INIT_OK))
+    return;
+
+  if (rc == IKEV2_GENERATE_SA_INIT_ERR_NO_DH)
+    ikev2_elog_error (IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR);
+  else if (rc == IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH)
+    ikev2_elog_error (IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR);
+}
+
 static_always_inline uword
 ikev2_node_internal (vlib_main_t * vm,
                     vlib_node_runtime_t * node, vlib_frame_t * frame,
@@ -2925,7 +2969,7 @@ ikev2_node_internal (vlib_main_t * vm,
                      sa0->r_proposals =
                        ikev2_select_proposal (sa0->i_proposals,
                                               IKEV2_PROTOCOL_IKE);
-                     ikev2_generate_sa_init_data (sa0);
+                     ikev2_generate_sa_init_data_and_log (sa0);
                    }
 
                  if (sa0->state == IKEV2_STATE_SA_INIT
@@ -4150,15 +4194,6 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
       valid_ip = 1;
     }
 
-  bi0 = ikev2_get_new_ike_header_buff (vm, &b0);
-  if (!bi0)
-    {
-      char *errmsg = "buffer alloc failure";
-      ikev2_log_error (errmsg);
-      return clib_error_return (0, errmsg);
-    }
-  ike0 = vlib_buffer_get_current (b0);
-
   /* Prepare the SA and the IKE payload */
   ikev2_sa_t sa;
   clib_memset (&sa, 0, sizeof (ikev2_sa_t));
@@ -4186,7 +4221,15 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
   sa.is_tun_itf_set = 1;
   sa.initial_contact = 1;
   sa.dst_port = IKEV2_PORT;
-  ikev2_generate_sa_init_data (&sa);
+
+  ikev2_generate_sa_error_t rc = ikev2_generate_sa_init_data (&sa);
+  if (rc != IKEV2_GENERATE_SA_INIT_OK)
+    {
+      ikev2_sa_free_all_vec (&sa);
+      ikev2_payload_destroy_chain (chain);
+      return clib_error_return (0, "%U", format_ikev2_gen_sa_error, rc);
+    }
+
   ikev2_payload_add_ke (chain, sa.dh_group, sa.i_dh_data);
   ikev2_payload_add_nonce (chain, sa.i_nonce);
 
@@ -4226,6 +4269,17 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
                            sig_hash_algo);
   vec_free (sig_hash_algo);
 
+  bi0 = ikev2_get_new_ike_header_buff (vm, &b0);
+  if (!bi0)
+    {
+      ikev2_sa_free_all_vec (&sa);
+      ikev2_payload_destroy_chain (chain);
+      char *errmsg = "buffer alloc failure";
+      ikev2_log_error (errmsg);
+      return clib_error_return (0, errmsg);
+    }
+  ike0 = vlib_buffer_get_current (b0);
+
   /* Buffer update and boilerplate */
   len += vec_len (chain->data);
   ike0->nextpayload = chain->first_payload_type;
@@ -5015,7 +5069,12 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
              p = pool_elt_at_index (km->profiles, sa->profile_index);
              if (p)
                {
-                 ikev2_initiate_sa_init (vm, p->name);
+                 clib_error_t *e = ikev2_initiate_sa_init (vm, p->name);
+                 if (e)
+                   {
+                     ikev2_log_error ("%U", format_clib_error, e);
+                     clib_error_free (e);
+                   }
                }
            }
        }
index 63d8760..dd4c094 100644 (file)
@@ -481,7 +481,11 @@ static void
   error = ikev2_set_liveness_params (clib_net_to_host_u32 (mp->period),
                                     clib_net_to_host_u32 (mp->max_retries));
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -502,7 +506,11 @@ vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -528,7 +536,11 @@ static void
   vec_free (tmp);
   vec_free (data);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -553,7 +565,11 @@ vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
   vec_free (tmp);
   vec_free (data);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -575,7 +591,11 @@ static void
   error = ikev2_set_profile_udp_encap (vm, tmp);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -603,7 +623,11 @@ vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
                          start_addr, end_addr, mp->ts.is_local);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -623,7 +647,11 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
 
   error = ikev2_set_local_key (vm, mp->key_file);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -649,7 +677,11 @@ vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
   error = ikev2_set_profile_responder (vm, tmp, sw_if_index, ip);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -677,7 +709,11 @@ vl_api_ikev2_set_ike_transforms_t_handler (vl_api_ikev2_set_ike_transforms_t *
                                      ntohl (mp->tr.crypto_key_size));
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -704,7 +740,11 @@ vl_api_ikev2_set_esp_transforms_t_handler (vl_api_ikev2_set_esp_transforms_t *
                                      ntohl (mp->tr.crypto_key_size));
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -733,7 +773,11 @@ vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp)
                                   (mp->lifetime_maxdata));
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -782,7 +826,11 @@ static void
                                              ntohl (mp->sw_if_index));
 
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
   vec_free (tmp);
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
@@ -807,7 +855,11 @@ vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp)
   error = ikev2_initiate_sa_init (vm, tmp);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -828,7 +880,11 @@ vl_api_ikev2_initiate_del_ike_sa_t_handler (vl_api_ikev2_initiate_del_ike_sa_t
 
   error = ikev2_initiate_delete_ike_sa (vm, mp->ispi);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -849,7 +905,11 @@ static void
 
   error = ikev2_initiate_delete_child_sa (vm, mp->ispi);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -871,7 +931,11 @@ static void
   error = ikev2_profile_natt_disable (tmp);
   vec_free (tmp);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif
@@ -892,7 +956,11 @@ static void
 
   error = ikev2_initiate_rekey_child_sa (vm, mp->ispi);
   if (error)
-    rv = VNET_API_ERROR_UNSPECIFIED;
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
 #else
   rv = VNET_API_ERROR_UNIMPLEMENTED;
 #endif