On Tue, Dec 05, 2017 at 12:53:38PM +0100, Patrick Wildt wrote:
> Hi,
> 
> this diff changes the config parsing code so that we can specify
> multiple ikesa and childsa proposals by using the keywords multiple
> times.  It needs the other payload parsing diff that I posted as well.
> 
> Multiple proposals can be specified like this:
> 
>     ikesa auth hmac-sha2-256 enc aes-192 group modp2048 \
>     ikesa auth hmac-sha2-256 enc aes-256 group modp2048 \
>     ikesa auth hmac-sha1 enc aes-256 group modp2048 \
>     childsa auth hmac-sha2-256 enc aes-192 group modp2048 \
>     childsa auth hmac-sha2-256 enc aes-256 group modp2048 \
>     childsa auth hmac-sha1 enc aes-256 group modp2048 \
> 
> ok?

Bump.

> Patrick
> 
> diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
> index 58b12e6d0b4..25f9360bf9c 100644
> --- a/sbin/iked/parse.y
> +++ b/sbin/iked/parse.y
> @@ -120,8 +120,8 @@ struct ipsec_transforms {
>  };
>  
>  struct ipsec_mode {
> -     struct ipsec_transforms *xfs;
> -     uint8_t                  ike_exch;
> +     struct ipsec_transforms **xfs;
> +     unsigned int              nxfs;
>  };
>  
>  struct iked_transform ikev2_default_ike_transforms[] = {
> @@ -329,9 +329,8 @@ const struct ipsec_xf     *parse_xf(const char *, 
> unsigned int,
>  const char           *print_xf(unsigned int, unsigned int,
>                           const struct ipsec_xf *);
>  void                  copy_transforms(unsigned int, const struct ipsec_xf *,
> -                         const struct ipsec_xf *,
> -                         struct iked_transform *, size_t,
> -                         unsigned int *, struct iked_transform *, size_t);
> +                         struct iked_transform **, unsigned int *,
> +                         struct iked_transform *, size_t);
>  int                   create_ike(char *, int, uint8_t, struct ipsec_hosts *,
>                           struct ipsec_hosts *, struct ipsec_mode *,
>                           struct ipsec_mode *, uint8_t,
> @@ -347,6 +346,7 @@ int                        parsekeyfile(char *, struct 
> iked_auth *);
>  
>  struct ipsec_transforms *ipsec_transforms;
>  struct ipsec_filters *ipsec_filters;
> +struct ipsec_mode *ipsec_mode;
>  
>  typedef struct {
>       union {
> @@ -405,7 +405,7 @@ typedef struct {
>  %type        <v.ikemode>             ikeflags ikematch ikemode ipcomp
>  %type        <v.ikeauth>             ikeauth
>  %type        <v.ikekey>              keyspec
> -%type        <v.mode>                ike_sa child_sa
> +%type        <v.mode>                ike_sas child_sas
>  %type        <v.lifetime>            lifetime
>  %type        <v.number>              byte_spec time_spec ikelifetime
>  %type        <v.string>              name
> @@ -463,7 +463,7 @@ user              : USER STRING STRING            {
>               ;
>  
>  ikev2rule    : IKEV2 name ikeflags satype af proto hosts_list peers
> -                 ike_sa child_sa ids ikelifetime lifetime ikeauth ikecfg
> +                 ike_sas child_sas ids ikelifetime lifetime ikeauth ikecfg
>                   filters {
>                       if (create_ike($2, $5, $6, $7, &$8, $9, $10, $4, $3,
>                           $11.srcid, $11.dstid, $12, &$13, &$14,
> @@ -774,27 +774,61 @@ transform       : AUTHXF STRING                 {
>               }
>               ;
>  
> -ike_sa               : /* empty */   {
> +ike_sas              :                                       {
> +                     if ((ipsec_mode = calloc(1,
> +                         sizeof(struct ipsec_mode))) == NULL)
> +                             err(1, "ike_sas: calloc");
> +             }
> +                 ike_sas_l                           {
> +                     $$ = ipsec_mode;
> +             }
> +             | /* empty */                           {
>                       $$ = NULL;
>               }
> -             | IKESA         {
> +             ;
> +
> +ike_sas_l    : ike_sas_l ike_sa
> +             | ike_sa
> +             ;
> +
> +ike_sa               : IKESA         {
> +                     if ((ipsec_mode->xfs = recallocarray(ipsec_mode->xfs,
> +                         ipsec_mode->nxfs, ipsec_mode->nxfs + 1,
> +                         sizeof(struct ipsec_transforms *))) == NULL)
> +                             err(1, "ike_sa: recallocarray");
> +                     ipsec_mode->nxfs++;
>                       encxfs = ikeencxfs;
>               } transforms    {
> -                     if (($$ = calloc(1, sizeof(*$$))) == NULL)
> -                             err(1, "ike_sa: calloc");
> -                     $$->xfs = $3;
> +                     ipsec_mode->xfs[ipsec_mode->nxfs - 1] = $3;
>               }
>               ;
>  
> -child_sa     : /* empty */   {
> +child_sas    :                                       {
> +                     if ((ipsec_mode = calloc(1,
> +                         sizeof(struct ipsec_mode))) == NULL)
> +                             err(1, "child_sas: calloc");
> +             }
> +                 child_sas_l                         {
> +                     $$ = ipsec_mode;
> +             }
> +             | /* empty */                           {
>                       $$ = NULL;
>               }
> -             | CHILDSA       {
> +             ;
> +
> +child_sas_l  : child_sas_l child_sa
> +             | child_sa
> +             ;
> +
> +child_sa     : CHILDSA       {
> +                     if ((ipsec_mode->xfs = recallocarray(ipsec_mode->xfs,
> +                         ipsec_mode->nxfs, ipsec_mode->nxfs + 1,
> +                         sizeof(struct ipsec_transforms *))) == NULL)
> +                             err(1, "child_sa: recallocarray");
> +                     ipsec_mode->nxfs++;
>                       encxfs = ipsecencxfs;
>               } transforms    {
> -                     if (($$ = calloc(1, sizeof(*$$))) == NULL)
> -                             err(1, "child_sa: calloc");
> -                     $$->xfs = $3;
> +                     ipsec_mode->xfs[ipsec_mode->nxfs - 1] = $3;
>               }
>               ;
>  
> @@ -2544,17 +2578,18 @@ print_policy(struct iked_policy *pol)
>  
>  void
>  copy_transforms(unsigned int type, const struct ipsec_xf *xf,
> -    const struct ipsec_xf *xfs,
> -    struct iked_transform *dst, size_t ndst,
> -    unsigned int *n, struct iked_transform *src, size_t nsrc)
> +    struct iked_transform **dst, unsigned int *ndst,
> +    struct iked_transform *src, size_t nsrc)
>  {
>       unsigned int             i;
>       struct iked_transform   *a, *b;
>  
>       if (xf != NULL) {
> -             if (*n >= ndst)
> -                     return;
> -             b = dst + (*n)++;
> +             *dst = recallocarray(*dst, *ndst,
> +                 *ndst + 1, sizeof(struct iked_transform));
> +             if (*dst == NULL)
> +                     err(1, "copy_transforms: recallocarray");
> +             b = *dst + (*ndst)++;
>  
>               b->xform_type = type;
>               b->xform_id = xf->id;
> @@ -2567,9 +2602,11 @@ copy_transforms(unsigned int type, const struct 
> ipsec_xf *xf,
>               a = src + i;
>               if (a->xform_type != type)
>                       continue;
> -             if (*n >= ndst)
> -                     return;
> -             b = dst + (*n)++;
> +             *dst = recallocarray(*dst, *ndst,
> +                 *ndst + 1, sizeof(struct iked_transform));
> +             if (*dst == NULL)
> +                     err(1, "copy_transforms: recallocarray");
> +             b = *dst + (*ndst)++;
>               memcpy(b, a, sizeof(*b));
>       }
>  }
> @@ -2587,18 +2624,16 @@ create_ike(char *name, int af, uint8_t ipproto, 
> struct ipsec_hosts *hosts,
>       unsigned int             idtype = IKEV2_ID_NONE;
>       struct ipsec_addr_wrap  *ipa, *ipb, *ippn;
>       struct iked_policy       pol;
> -     struct iked_proposal     prop[2];
> -     unsigned int             j;
> +     struct iked_proposal    *p, *ptmp;
> +     struct iked_transform   *xf;
> +     unsigned int             i, j, xfi;
>       unsigned int             ikepropid = 1, ipsecpropid = 1;
> -     struct iked_transform    ikexforms[64], ipsecxforms[64];
>       struct iked_flow         flows[64];
>       static unsigned int      policy_id = 0;
>       struct iked_cfg         *cfg;
> +     int                      ret = -1;
>  
>       bzero(&pol, sizeof(pol));
> -     bzero(&prop, sizeof(prop));
> -     bzero(&ikexforms, sizeof(ikexforms));
> -     bzero(&ipsecxforms, sizeof(ipsecxforms));
>       bzero(&flows, sizeof(flows));
>       bzero(idstr, sizeof(idstr));
>  
> @@ -2720,79 +2755,106 @@ create_ike(char *name, int af, uint8_t ipproto, 
> struct ipsec_hosts *hosts,
>       TAILQ_INIT(&pol.pol_proposals);
>       RB_INIT(&pol.pol_flows);
>  
> -     prop[0].prop_id = ikepropid++;
> -     prop[0].prop_protoid = IKEV2_SAPROTO_IKE;
> -     if (ike_sa == NULL || ike_sa->xfs == NULL) {
> -             prop[0].prop_nxforms = ikev2_default_nike_transforms;
> -             prop[0].prop_xforms = ikev2_default_ike_transforms;
> -     } else {
> -             j = 0;
> -             copy_transforms(IKEV2_XFORMTYPE_INTEGR,
> -                 ike_sa->xfs->authxf, authxfs,
> -                 ikexforms, nitems(ikexforms), &j,
> -                 ikev2_default_ike_transforms,
> -                 ikev2_default_nike_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_ENCR,
> -                 ike_sa->xfs->encxf, ikeencxfs,
> -                 ikexforms, nitems(ikexforms), &j,
> -                 ikev2_default_ike_transforms,
> -                 ikev2_default_nike_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_DH,
> -                 ike_sa->xfs->groupxf, groupxfs,
> -                 ikexforms, nitems(ikexforms), &j,
> -                 ikev2_default_ike_transforms,
> -                 ikev2_default_nike_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_PRF,
> -                 ike_sa->xfs->prfxf, prfxfs,
> -                 ikexforms, nitems(ikexforms), &j,
> -                 ikev2_default_ike_transforms,
> -                 ikev2_default_nike_transforms);
> -             prop[0].prop_nxforms = j;
> -             prop[0].prop_xforms = ikexforms;
> -     }
> -     TAILQ_INSERT_TAIL(&pol.pol_proposals, &prop[0], prop_entry);
> -     pol.pol_nproposals++;
> -
> -     prop[1].prop_id = ipsecpropid++;
> -     prop[1].prop_protoid = saproto;
> -     if (ipsec_sa == NULL || ipsec_sa->xfs == NULL) {
> -             prop[1].prop_nxforms = ikev2_default_nesp_transforms;
> -             prop[1].prop_xforms = ikev2_default_esp_transforms;
> +     if (ike_sa == NULL || ike_sa->nxfs == 0) {
> +             if ((p = calloc(1, sizeof(*p))) == NULL)
> +                     err(1, "create_ike: calloc");
> +             p->prop_id = ikepropid++;
> +             p->prop_protoid = IKEV2_SAPROTO_IKE;
> +             p->prop_nxforms = ikev2_default_nike_transforms;
> +             p->prop_xforms = ikev2_default_ike_transforms;
> +             TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
> +             pol.pol_nproposals++;
>       } else {
> -             j = 0;
> -             if (ipsec_sa->xfs->encxf && ipsec_sa->xfs->encxf->noauth &&
> -                 ipsec_sa->xfs->authxf) {
> -                     yyerror("authentication is implicit for %s",
> -                         ipsec_sa->xfs->encxf->name);
> -                     return (-1);
> -             }
> -             if (ipsec_sa->xfs->encxf == NULL ||
> -                 (ipsec_sa->xfs->encxf && !ipsec_sa->xfs->encxf->noauth))
> +             for (i = 0; i < ike_sa->nxfs; i++) {
> +                     if ((p = calloc(1, sizeof(*p))) == NULL)
> +                             err(1, "create_ike: calloc");
> +
> +                     xf = NULL;
> +                     xfi = 0;
>                       copy_transforms(IKEV2_XFORMTYPE_INTEGR,
> -                         ipsec_sa->xfs->authxf, authxfs,
> -                         ipsecxforms, nitems(ipsecxforms), &j,
> +                         ike_sa->xfs[i]->authxf, &xf, &xfi,
> +                         ikev2_default_ike_transforms,
> +                         ikev2_default_nike_transforms);
> +                     copy_transforms(IKEV2_XFORMTYPE_ENCR,
> +                         ike_sa->xfs[i]->encxf, &xf, &xfi,
> +                         ikev2_default_ike_transforms,
> +                         ikev2_default_nike_transforms);
> +                     copy_transforms(IKEV2_XFORMTYPE_DH,
> +                         ike_sa->xfs[i]->groupxf, &xf, &xfi,
> +                         ikev2_default_ike_transforms,
> +                         ikev2_default_nike_transforms);
> +                     copy_transforms(IKEV2_XFORMTYPE_PRF,
> +                         ike_sa->xfs[i]->prfxf, &xf, &xfi,
> +                         ikev2_default_ike_transforms,
> +                         ikev2_default_nike_transforms);
> +                     free(ike_sa->xfs[i]);
> +
> +                     p->prop_id = ikepropid++;
> +                     p->prop_protoid = IKEV2_SAPROTO_IKE;
> +                     p->prop_xforms = xf;
> +                     p->prop_nxforms = xfi;
> +                     TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
> +                     pol.pol_nproposals++;
> +             }
> +             free(ike_sa->xfs);
> +     }
> +     free(ike_sa);
> +
> +     if (ipsec_sa == NULL || ipsec_sa->nxfs == 0) {
> +             if ((p = calloc(1, sizeof(*p))) == NULL)
> +                     err(1, "create_ike: calloc");
> +             p->prop_id = ipsecpropid++;
> +             p->prop_protoid = saproto;
> +             p->prop_nxforms = ikev2_default_nesp_transforms;
> +             p->prop_xforms = ikev2_default_esp_transforms;
> +             TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
> +             pol.pol_nproposals++;
> +     } else {
> +             for (i = 0; i < ipsec_sa->nxfs; i++) {
> +                     if (ipsec_sa->xfs[i]->encxf &&
> +                         ipsec_sa->xfs[i]->encxf->noauth &&
> +                         ipsec_sa->xfs[i]->authxf) {
> +                             yyerror("authentication is implicit for %s",
> +                                 ipsec_sa->xfs[i]->encxf->name);
> +                             return (-1);
> +                     }
> +
> +                     if ((p = calloc(1, sizeof(*p))) == NULL)
> +                             err(1, "create_ike: calloc");
> +
> +                     xf = NULL;
> +                     xfi = 0;
> +                     if (ipsec_sa->xfs[i]->encxf == NULL ||
> +                         (ipsec_sa->xfs[i]->encxf &&
> +                         !ipsec_sa->xfs[i]->encxf->noauth))
> +                             copy_transforms(IKEV2_XFORMTYPE_INTEGR,
> +                                 ipsec_sa->xfs[i]->authxf, &xf, &xfi,
> +                                 ikev2_default_esp_transforms,
> +                                 ikev2_default_nesp_transforms);
> +                     copy_transforms(IKEV2_XFORMTYPE_ENCR,
> +                         ipsec_sa->xfs[i]->encxf, &xf, &xfi,
>                           ikev2_default_esp_transforms,
>                           ikev2_default_nesp_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_ENCR,
> -                 ipsec_sa->xfs->encxf, ipsecencxfs,
> -                 ipsecxforms, nitems(ipsecxforms), &j,
> -                 ikev2_default_esp_transforms,
> -                 ikev2_default_nesp_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_DH,
> -                 ipsec_sa->xfs->groupxf, groupxfs,
> -                 ipsecxforms, nitems(ipsecxforms), &j,
> -                 ikev2_default_esp_transforms,
> -                 ikev2_default_nesp_transforms);
> -             copy_transforms(IKEV2_XFORMTYPE_ESN,
> -                 NULL, NULL,
> -                 ipsecxforms, nitems(ipsecxforms), &j,
> -                 ikev2_default_esp_transforms,
> -                 ikev2_default_nesp_transforms);
> -             prop[1].prop_nxforms = j;
> -             prop[1].prop_xforms = ipsecxforms;
> -     }
> -     TAILQ_INSERT_TAIL(&pol.pol_proposals, &prop[1], prop_entry);
> -     pol.pol_nproposals++;
> +                     copy_transforms(IKEV2_XFORMTYPE_DH,
> +                         ipsec_sa->xfs[i]->groupxf, &xf, &xfi,
> +                         ikev2_default_esp_transforms,
> +                         ikev2_default_nesp_transforms);
> +                     copy_transforms(IKEV2_XFORMTYPE_ESN,
> +                         NULL, &xf, &xfi,
> +                         ikev2_default_esp_transforms,
> +                         ikev2_default_nesp_transforms);
> +                     free(ipsec_sa->xfs[i]);
> +
> +                     p->prop_id = ipsecpropid++;
> +                     p->prop_protoid = saproto;
> +                     p->prop_xforms = xf;
> +                     p->prop_nxforms = xfi;
> +                     TAILQ_INSERT_TAIL(&pol.pol_proposals, p, prop_entry);
> +                     pol.pol_nproposals++;
> +             }
> +             free(ipsec_sa->xfs);
> +     }
> +     free(ipsec_sa);
>  
>       if (hosts == NULL || hosts->src == NULL || hosts->dst == NULL)
>               fatalx("create_ike: no traffic selectors/flows");
> @@ -2871,14 +2933,24 @@ create_ike(char *name, int af, uint8_t ipproto, 
> struct ipsec_hosts *hosts,
>       /* Make sure that we know how to authenticate this peer */
>       if (idtype && set_policy(idstr, idtype, &pol) < 0) {
>               log_debug("%s: set_policy failed", __func__);
> -             return (-1);
> +             goto done;
>       }
>  
>       config_setpolicy(env, &pol, PROC_IKEV2);
>       config_setflow(env, &pol, PROC_IKEV2);
>  
>       rules++;
> -     return (0);
> +     ret = 0;
> +
> +done:
> +     TAILQ_FOREACH_SAFE(p, &pol.pol_proposals, prop_entry, ptmp) {
> +             if (p->prop_xforms != ikev2_default_ike_transforms &&
> +                 p->prop_xforms != ikev2_default_esp_transforms)
> +                     free(p->prop_xforms);
> +             free(p);
> +     }
> +
> +     return (ret);
>  }
>  
>  int

Reply via email to