[redhat-lspp] [PoC PATCH 1/1] Allow racoon to negotiate with the same instance of itself

Joy Latten latten at austin.ibm.com
Mon Jan 29 20:13:54 UTC 2007


Thanks! I'll apply the patch and run an ipv4 and ipv6 stress test using
racoon to ensure no regression. Maybe I should try stress test over
loopback too. :-) 

Regards,
Joy
 
On Mon, 2007-01-29 at 14:23 -0500, Paul Moore wrote:
> plain text document attachment (localhost-ike)
> This patch allows racoon to negotiate with the same instance of itself.  This
> means that IKE negotiations over local addresses, including localhost, are now
> possibile.  The only major change in this patch is to include
> side/directionality in the phase-1 and phase-2 SA lookup functions, the other
> changes in this patch are either results of this extra search field or some
> simple logic to pick the correct SA for a negotiation when two SA exist for the
> same IKE cookie pair.
> 
> Please be warned that this is a proof of concept patch and has not been
> throughly tested or reviewed.  In face, with certain configure flags it may not
> even compile.
> 
> ---
>  src/racoon/admin.c        |    4 +-
>  src/racoon/handler.c      |   35 ++++++++++++++++----
>  src/racoon/handler.h      |   15 ++++----
>  src/racoon/isakmp.c       |   80 +++++++++++++++++++++++++++++++++++++++-------
>  src/racoon/isakmp.h       |    2 +
>  src/racoon/isakmp_inf.c   |    6 +--
>  src/racoon/isakmp_xauth.c |    2 -
>  7 files changed, 112 insertions(+), 32 deletions(-)
> 
> Index: ipsec-tools-0.6.5-6/src/racoon/admin.c
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/admin.c
> +++ ipsec-tools-0.6.5-6/src/racoon/admin.c
> @@ -289,7 +289,7 @@ admin_process(so2, combuf)
>  			break;
>  		}
>  
> -		if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
> +		if ((iph1 = getph1byaddrwop(src, dst, ANYSIDE)) == NULL) {
>  			plog(LLV_ERROR, LOCATION, NULL, 
>  			    "phase 1 for %s -> %s not found\n", loc, rem);
>  		} else {
> @@ -322,7 +322,7 @@ admin_process(so2, combuf)
>  		plog(LLV_INFO, LOCATION, NULL, 
>  		    "Flushing all SAs for peer %s\n", rem);
>  
> -		while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
> +		while ((iph1 = getph1bydstaddrwop(dst, ANYSIDE)) != NULL) {
>  			if ((loc = strdup(saddrwop2str(iph1->local))) == NULL) {
>  				plog(LLV_ERROR, LOCATION, NULL, 
>  				    "cannot allocate memory\n");
> Index: ipsec-tools-0.6.5-6/src/racoon/handler.c
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/handler.c
> +++ ipsec-tools-0.6.5-6/src/racoon/handler.c
> @@ -93,14 +93,17 @@ static void sweep_recvdpkt __P((void *))
>  extern caddr_t val2str(const char *, size_t);
>  
>  struct ph1handle *
> -getph1byindex(index)
> +getph1byindex(index, side)
>  	isakmp_index *index;
> +	int side;
>  {
>  	struct ph1handle *p;
>  
>  	LIST_FOREACH(p, &ph1tree, chain) {
>  		if (p->status == PHASE1ST_EXPIRED)
>  			continue;
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (memcmp(&p->index, index, sizeof(*index)) == 0)
>  			return p;
>  	}
> @@ -112,14 +115,17 @@ getph1byindex(index)
>   * search for isakmp handler by i_ck in index.
>   */
>  struct ph1handle *
> -getph1byindex0(index)
> +getph1byindex0(index, side)
>  	isakmp_index *index;
> +	int side;
>  {
>  	struct ph1handle *p;
>  
>  	LIST_FOREACH(p, &ph1tree, chain) {
>  		if (p->status == PHASE1ST_EXPIRED)
>  			continue;
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
>  			return p;
>  	}
> @@ -133,14 +139,17 @@ getph1byindex0(index)
>   * with phase 2's destinaion.
>   */
>  struct ph1handle *
> -getph1byaddr(local, remote)
> +getph1byaddr(local, remote, side)
>  	struct sockaddr *local, *remote;
> +	int side;
>  {
>  	struct ph1handle *p;
>  
>  	LIST_FOREACH(p, &ph1tree, chain) {
>  		if (p->status == PHASE1ST_EXPIRED)
>  			continue;
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (CMPSADDR(local, p->local) == 0
>  		 && CMPSADDR(remote, p->remote) == 0)
>  			return p;
> @@ -150,14 +159,17 @@ getph1byaddr(local, remote)
>  }
>  
>  struct ph1handle *
> -getph1byaddrwop(local, remote)
> +getph1byaddrwop(local, remote, side)
>  	struct sockaddr *local, *remote;
> +	int side;
>  {
>  	struct ph1handle *p;
>  
>  	LIST_FOREACH(p, &ph1tree, chain) {
>  		if (p->status == PHASE1ST_EXPIRED)
>  			continue;
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (cmpsaddrwop(local, p->local) == 0
>  		 && cmpsaddrwop(remote, p->remote) == 0)
>  			return p;
> @@ -172,14 +184,17 @@ getph1byaddrwop(local, remote)
>   * with phase 2's destinaion.
>   */
>  struct ph1handle *
> -getph1bydstaddrwop(remote)
> +getph1bydstaddrwop(remote, side)
>  	struct sockaddr *remote;
> +	int side;
>  {
>  	struct ph1handle *p;
>  
>  	LIST_FOREACH(p, &ph1tree, chain) {
>  		if (p->status == PHASE1ST_EXPIRED)
>  			continue;
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (cmpsaddrwop(remote, p->remote) == 0)
>  			return p;
>  	}
> @@ -444,13 +459,16 @@ getph2byseq(seq)
>   * search ph2handle with message id.
>   */
>  struct ph2handle *
> -getph2bymsgid(iph1, msgid)
> +getph2bymsgid(iph1, msgid, side)
>  	struct ph1handle *iph1;
>  	u_int32_t msgid;
> +	int side;
>  {
>  	struct ph2handle *p;
>  
>  	LIST_FOREACH(p, &ph2tree, chain) {
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (p->msgid == msgid)
>  			return p;
>  	}
> @@ -476,12 +494,15 @@ getph2byid(src, dst, spid)
>  }
>  
>  struct ph2handle *
> -getph2bysaddr(src, dst)
> +getph2bysaddr(src, dst, side)
>  	struct sockaddr *src, *dst;
> +	int side;
>  {
>  	struct ph2handle *p;
>  
>  	LIST_FOREACH(p, &ph2tree, chain) {
> +		if (p->side != side && side != ANYSIDE)
> +			continue;
>  		if (cmpsaddrstrict(src, p->src) == 0 &&
>  		    cmpsaddrstrict(dst, p->dst) == 0)
>  			return p;
> Index: ipsec-tools-0.6.5-6/src/racoon/handler.h
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/handler.h
> +++ ipsec-tools-0.6.5-6/src/racoon/handler.h
> @@ -417,13 +417,13 @@ struct ph1handle;
>  struct ph2handle;
>  struct policyindex;
>  
> -extern struct ph1handle *getph1byindex __P((isakmp_index *));
> -extern struct ph1handle *getph1byindex0 __P((isakmp_index *));
> +extern struct ph1handle *getph1byindex __P((isakmp_index *, int));
> +extern struct ph1handle *getph1byindex0 __P((isakmp_index *, int));
>  extern struct ph1handle *getph1byaddr __P((struct sockaddr *,
> -	struct sockaddr *));
> +					   struct sockaddr *, int));
>  extern struct ph1handle *getph1byaddrwop __P((struct sockaddr *,
> -	struct sockaddr *));
> -extern struct ph1handle *getph1bydstaddrwop __P((struct sockaddr *));
> +	struct sockaddr *, int));
> +extern struct ph1handle *getph1bydstaddrwop __P((struct sockaddr *, int));
>  extern vchar_t *dumpph1 __P((void));
>  extern struct ph1handle *newph1 __P((void));
>  extern void delph1 __P((struct ph1handle *));
> @@ -436,8 +436,9 @@ extern struct ph2handle *getph2byspidx _
>  extern struct ph2handle *getph2byspid __P((u_int32_t));
>  extern struct ph2handle *getph2byseq __P((u_int32_t));
>  extern struct ph2handle *getph2bysaddr __P((struct sockaddr *,
> -	struct sockaddr *));
> -extern struct ph2handle *getph2bymsgid __P((struct ph1handle *, u_int32_t));
> +	struct sockaddr *, int));
> +extern struct ph2handle *getph2bymsgid __P((struct ph1handle *, u_int32_t,
> +	int));
>  extern struct ph2handle *getph2byid __P((struct sockaddr *,
>  	struct sockaddr *, u_int32_t));
>  extern struct ph2handle *getph2bysaidx __P((struct sockaddr *,
> Index: ipsec-tools-0.6.5-6/src/racoon/isakmp.c
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/isakmp.c
> +++ ipsec-tools-0.6.5-6/src/racoon/isakmp.c
> @@ -369,6 +369,34 @@ end:
>  }
>  
>  /*
> + * isakmp phase 1 search helper
> + */
> +static struct ph1handle *
> +isakmp_ph1pickside(iph1_i, iph1_r, local)
> +	struct ph1handle *iph1_i, *iph1_r;
> +	struct sockaddr *local;
> +{
> +	if (iph1_i == NULL && iph1_r != NULL) {
> +		if (cmpsaddrstrict(iph1_r->remote, local) != 0)
> +			return iph1_r;
> +		else
> +			return NULL;
> +	} else if (iph1_i != NULL && iph1_r == NULL) {
> +		if (cmpsaddrstrict(iph1_i->remote, local) != 0)
> +			return iph1_i;
> +		else
> +			return NULL;
> +	} else if (iph1_i != NULL && iph1_r != NULL) {
> +		if (iph1_r->status < iph1_i->status)
> +			return iph1_r;
> +		else
> +			return iph1_i;
> +	}
> +
> +	return NULL;
> +}
> +
> +/*
>   * main processing to handle isakmp payload
>   */
>  static int
> @@ -434,7 +462,9 @@ isakmp_main(msg, remote, local)
>  		}
>  	}
>  
> -	iph1 = getph1byindex(index);
> +	iph1 = isakmp_ph1pickside(getph1byindex(index, INITIATOR),
> +				  getph1byindex(index, RESPONDER),
> +				  local);
>  	if (iph1 != NULL) {
>  		/* validity check */
>  		if (memcmp(&isakmp->r_ck, r_ck0, sizeof(cookie_t)) == 0 &&
> @@ -516,7 +546,10 @@ isakmp_main(msg, remote, local)
>  			 */
>  
>  			/* search for phase1 handle by index without r_ck */
> -			iph1 = getph1byindex0(index);
> +			iph1 = isakmp_ph1pickside(
> +				getph1byindex0(index, INITIATOR),
> +				getph1byindex0(index, RESPONDER),
> +				local);
>  			if (iph1 == NULL) {
>  				/*it must be the 1st message from a initiator.*/
>  				if (memcmp(&isakmp->r_ck, r_ck0,
> @@ -592,7 +625,7 @@ isakmp_main(msg, remote, local)
>  		 * NOTE: We think such informational exchange should be ignored.
>  		 */
>  		if (iph1 == NULL) {
> -			iph1 = getph1byindex0(index);
> +			iph1 = getph1byindex0(index, INITIATOR);
>  			if (iph1 == NULL) {
>  				plog(LLV_ERROR, LOCATION, remote,
>  					"unknown Informational "
> @@ -619,6 +652,7 @@ isakmp_main(msg, remote, local)
>  	case ISAKMP_ETYPE_QUICK:
>  	{
>  		struct ph2handle *iph2;
> +		struct ph2handle *iph2_i, *iph2_r;
>  
>  		if (iph1 == NULL) {
>  			isakmp_info_send_nx(isakmp, remote, local,
> @@ -646,7 +680,25 @@ isakmp_main(msg, remote, local)
>  		}
>  
>  		/* search isakmp phase 2 stauts record. */
> -		iph2 = getph2bymsgid(iph1, msgid);
> +		iph2_i = getph2bymsgid(iph1, msgid, INITIATOR);
> +		iph2_r = getph2bymsgid(iph1, msgid, RESPONDER);
> +		if (iph2_i == NULL && iph2_r != NULL) {
> +			if (cmpsaddrstrict(iph1->remote, local) != 0)
> +				iph2 = iph2_r;
> +			else
> +				iph2 = NULL;
> +		} else if (iph2_i != NULL && iph2_r == NULL) {
> +			if (cmpsaddrstrict(iph1->remote, local) != 0)
> +				iph2 = iph2_i;
> +			else
> +				iph2 = NULL;
> +		} else if (iph2_i != NULL && iph2_r != NULL) {
> +			if (iph2_r->status < iph2_i->status)
> +				iph2 = iph2_r;
> +			else
> +				iph2 = iph2_i;
> +		} else
> +			iph2 = NULL;
>  		if (iph2 == NULL) {
>  			/* it must be new negotiation as responder */
>  			if (isakmp_ph2begin_r(iph1, msg) < 0)
> @@ -2041,15 +2093,17 @@ isakmp_post_acquire(iph2)
>  	 */
>  #ifdef ENABLE_NATT
>  	if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
> -		if ((iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL) {
> +		if ((iph1 = getph1byaddrwop(iph2->src,
> +					    iph2->dst,
> +					    ANYSIDE)) != NULL) {
>  			set_port(iph2->src, extract_port(iph1->local));
>  			set_port(iph2->dst, extract_port(iph1->remote));
>  		}
>  	} else {
> -		iph1 = getph1byaddr(iph2->src, iph2->dst);
> +		iph1 = getph1byaddr(iph2->src, iph2->dst, ANYSIDE);
>  	}
>  #else
> -	iph1 = getph1byaddr(iph2->src, iph2->dst);
> +	iph1 = getph1byaddr(iph2->src, iph2->dst, ANYSIDE);
>  #endif
>  
>  	/* no ISAKMP-SA found. */
> @@ -2175,15 +2229,17 @@ isakmp_chkph1there(iph2)
>  	 */
>  #ifdef ENABLE_NATT
>  	if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
> -		if ((iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL) {
> +		if ((iph1 = getph1byaddrwop(iph2->src,
> +					    iph2->dst,
> +					    ANYSIDE)) != NULL) {
>  			set_port(iph2->src, extract_port(iph1->local));
>  			set_port(iph2->dst, extract_port(iph1->remote));
>  		}
>  	} else {
> -		iph1 = getph1byaddr(iph2->src, iph2->dst);
> +		iph1 = getph1byaddr(iph2->src, iph2->dst, ANYSIDE);
>  	}
>  #else
> -	iph1 = getph1byaddr(iph2->src, iph2->dst);
> +	iph1 = getph1byaddr(iph2->src, iph2->dst, ANYSIDE);
>  #endif
>  
>  	/* XXX Even if ph1 as responder is there, should we not start
> @@ -2432,7 +2488,7 @@ isakmp_newmsgid2(iph1)
>  
>  	do {
>  		msgid2 = eay_random();
> -	} while (getph2bymsgid(iph1, msgid2));
> +	} while (getph2bymsgid(iph1, msgid2, iph1->side));
>  
>  	return msgid2;
>  }
> @@ -3094,7 +3150,7 @@ purge_remote(iph1)
>  	iph1->status = PHASE1ST_EXPIRED;
>  
>  	/* Check if we have another, still valid, phase1 SA. */
> -	new_iph1 = getph1byaddr(iph1->local, iph1->remote);
> +	new_iph1 = getph1byaddr(iph1->local, iph1->remote, ANYSIDE);
>  
>  	/*
>  	 * Delete all orphaned or binded to the deleting ph1handle phase2 SAs.
> Index: ipsec-tools-0.6.5-6/src/racoon/isakmp.h
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/isakmp.h
> +++ ipsec-tools-0.6.5-6/src/racoon/isakmp.h
> @@ -37,6 +37,8 @@
>  /* must include <netinet/in.h> first. */
>  /* must include "isakmp_var.h" first. */
>  
> +#define ANYSIDE		-1	/* either INITIATOR or RESPONDER */
> +
>  #define INITIATOR	0	/* synonym sender */
>  #define RESPONDER	1	/* synonym receiver */
>  
> Index: ipsec-tools-0.6.5-6/src/racoon/isakmp_inf.c
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/isakmp_inf.c
> +++ ipsec-tools-0.6.5-6/src/racoon/isakmp_inf.c
> @@ -363,7 +363,7 @@ isakmp_info_send_d2(iph2)
>  	 * don't send delete information if there is no phase 1 handler.
>  	 * It's nonsensical to negotiate phase 1 to send the information.
>  	 */
> -	iph1 = getph1byaddr(iph2->src, iph2->dst); 
> +	iph1 = getph1byaddr(iph2->src, iph2->dst, ANYSIDE);
>  	if (iph1 == NULL)
>  		return 0;
>  
> @@ -892,7 +892,7 @@ isakmp_info_recv_n(iph1, msg)
>  				"delete phase1 handle.\n");
>  			return -1;
>  		} else {
> -			iph2 = getph2bymsgid(iph1, msgid);
> +			iph2 = getph2bymsgid(iph1, msgid, iph1->side);
>  			if (iph2 == NULL) {
>  				plog(LLV_ERROR, LOCATION, iph1->remote,
>  					"unknown notify message, "
> @@ -937,7 +937,7 @@ purge_isakmp_spi(proto, spi, n)
>  	size_t i;
>  
>  	for (i = 0; i < n; i++) {
> -		iph1 = getph1byindex(&spi[i]);
> +		iph1 = getph1byindex(&spi[i], ANYSIDE);
>  		if (!iph1)
>  			continue;
>  
> Index: ipsec-tools-0.6.5-6/src/racoon/isakmp_xauth.c
> ===================================================================
> --- ipsec-tools-0.6.5-6.orig/src/racoon/isakmp_xauth.c
> +++ ipsec-tools-0.6.5-6/src/racoon/isakmp_xauth.c
> @@ -338,7 +338,7 @@ xauth_reply_stub(args)
>  	struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args;
>  	struct ph1handle *iph1;
>  
> -	if ((iph1 = getph1byindex(&xra->index)) != NULL)
> +	if ((iph1 = getph1byindex(&xra->index, ANYSIDE)) != NULL)
>  		xauth_reply(iph1, xra->port, xra->id, xra->res);
>  	else
>  		plog(LLV_ERROR, LOCATION, NULL, 
> 
> --
> paul moore
> linux security @ hp
> 
> --
> redhat-lspp mailing list
> redhat-lspp at redhat.com
> https://www.redhat.com/mailman/listinfo/redhat-lspp




More information about the redhat-lspp mailing list