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
> [email protected]
> https://www.redhat.com/mailman/listinfo/redhat-lspp

--
redhat-lspp mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/redhat-lspp

Reply via email to