[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: IPV4_RANGE causes isakmpd crash



On Tue, 10 Jun 2003, Eric Boudrand wrote:

> Isakmpd can crash during Phase 2 if a remote host uses ID like
> ID_IPV4_RANGE, ID_IPV6_RANGE, ID_DER_ASN1_DN, ID_DER_ASN1_GN et ID_KEY_ID
> (read 4.6.2.1 in RFC 2407).
>
> This occurs in ipsec_set_network function in ipsec.c file. There is a 4
> switch instructions in which these case are not supported. So when the
> execution get out of the switch, some pointers are not filled. Then it
> crashes.
>
> ID_IPV4_RANGE is used for example by ZyWall 10.
>
> Here is the patch for isakmpd.
> ---------- cut here -------------
...

Hi,

thanks for pointing this out. I just committed a fix which is effectively
the same as your suggested patch, although I took the opportunity to fix a
few nits along the way.

Here's the diff (or get it from CVS in a couple of hours):

Index: ipsec.c
===================================================================
RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v
retrieving revision 1.76
diff -u -u -r1.76 ipsec.c
--- ipsec.c	4 Jun 2003 07:31:16 -0000	1.76
+++ ipsec.c	10 Jun 2003 12:19:47 -0000
@@ -331,7 +331,7 @@
 		  /* Initiator is source, responder is destination.  */
 		  if (ipsec_set_network (ie->id_ci, ie->id_cr, isa))
 		    {
-		      log_error ("ipsec_finalize_exchange: "
+		      log_print ("ipsec_finalize_exchange: "
 				 "ipsec_set_network failed");
 		      return;
 		    }
@@ -341,7 +341,7 @@
 		  /* Responder is source, initiator is destination.  */
 		  if (ipsec_set_network (ie->id_cr, ie->id_ci, isa))
 		    {
-		      log_error ("ipsec_finalize_exchange: "
+		      log_print ("ipsec_finalize_exchange: "
 				 "ipsec_set_network failed");
 		      return;
 		    }
@@ -414,6 +414,7 @@
 ipsec_set_network (u_int8_t *src_id, u_int8_t *dst_id, struct ipsec_sa *isa)
 {
   int id;
+  char *v;

   /* Set source address/mask.  */
   id = GET_ISAKMP_ID_TYPE (src_id);
@@ -424,7 +425,7 @@
       isa->src_net =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in));
       if (!isa->src_net)
-	return -1;
+	goto memfail;
       isa->src_net->sa_family = AF_INET;
 #ifndef USE_OLD_SOCKADDR
       isa->src_net->sa_len = sizeof (struct sockaddr_in);
@@ -433,7 +434,7 @@
       isa->src_mask =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in));
       if (!isa->src_mask)
-	return -1;
+	goto memfail;
       isa->src_mask->sa_family = AF_INET;
 #ifndef USE_OLD_SOCKADDR
       isa->src_mask->sa_len = sizeof (struct sockaddr_in);
@@ -445,7 +446,7 @@
       isa->src_net =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6));
       if (!isa->src_net)
-	return -1;
+	goto memfail;
       isa->src_net->sa_family = AF_INET6;
 #ifndef USE_OLD_SOCKADDR
       isa->src_net->sa_len = sizeof (struct sockaddr_in6);
@@ -454,12 +455,23 @@
       isa->src_mask =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6));
       if (!isa->src_mask)
-	return -1;
+	goto memfail;
       isa->src_mask->sa_family = AF_INET6;
 #ifndef USE_OLD_SOCKADDR
       isa->src_mask->sa_len = sizeof (struct sockaddr_in6);
 #endif
       break;
+
+    case IPSEC_ID_IPV4_RANGE:
+    case IPSEC_ID_IPV6_RANGE:
+    case IPSEC_ID_DER_ASN1_DN:
+    case IPSEC_ID_DER_ASN1_GN:
+    case IPSEC_ID_KEY_ID:
+    default:
+      v = constant_lookup (ipsec_id_cst, id);
+      log_print ("ipsec_set_network: ID type %d (%s) not supported",
+		 id, v ? v : "<unknown>");
+      return -1;
     }

   /* Net */
@@ -494,7 +506,7 @@
       isa->dst_net =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in));
       if (!isa->dst_net)
-	return -1;
+	goto memfail;
       isa->dst_net->sa_family = AF_INET;
 #ifndef USE_OLD_SOCKADDR
       isa->dst_net->sa_len = sizeof (struct sockaddr_in);
@@ -503,7 +515,7 @@
       isa->dst_mask =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in));
       if (!isa->dst_mask)
-	return -1;
+	goto memfail;
       isa->dst_mask->sa_family = AF_INET;
 #ifndef USE_OLD_SOCKADDR
       isa->dst_mask->sa_len = sizeof (struct sockaddr_in);
@@ -515,7 +527,7 @@
       isa->dst_net =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6));
       if (!isa->dst_net)
-	return -1;
+	goto memfail;
       isa->dst_net->sa_family = AF_INET6;
 #ifndef USE_OLD_SOCKADDR
       isa->dst_net->sa_len = sizeof (struct sockaddr_in6);
@@ -524,7 +536,7 @@
       isa->dst_mask =
 	(struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6));
       if (!isa->dst_mask)
-	return -1;
+	goto memfail;
       isa->dst_mask->sa_family = AF_INET6;
 #ifndef USE_OLD_SOCKADDR
       isa->dst_mask->sa_len = sizeof (struct sockaddr_in6);
@@ -557,6 +569,10 @@
   memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF,
 	  IPSEC_ID_PORT_LEN);
   return 0;
+
+ memfail:
+  log_error ("ipsec_set_network: calloc () failed");
+  return -1;
 }

 /* Free the DOI-specific exchange data pointed to by VIE.  */


//H

--
Håkan Olsson <ho@crt.se>        (+46) 708 437 337     Carlstedt Research
Unix, Networking, Security      (+46) 31 701 4264        & Technology AB