On Fri, Sep 03, 2021 at 10:12:57AM +0200, Sebastian Benoit wrote:
> Tobias Heider(tobias.hei...@stusta.de) on 2021.09.02 15:39:46 +0200:
> > The diff below makes iked accept a list of protocols for the "proto" config
> > option in iked.conf(5).
> > This would allow us to have a single policy with "proto { ipencap, ipv6 }"
> > to secure a gif(4) tunnel, instead of requiring one policy for each 
> > protocol.
> > 
> > ok?
> 
> I only gave the parser bits a quick read.
> 
> The manpage change would be nice to compare the parser with what you
> document.
> 
> A bit more below.
>  
> > Index: iked.h
> > ===================================================================
> > RCS file: /cvs/src/sbin/iked/iked.h,v
> > retrieving revision 1.193
> > diff -u -p -r1.193 iked.h
> > --- iked.h  1 Sep 2021 15:30:06 -0000       1.193
> > +++ iked.h  2 Sep 2021 13:37:21 -0000
> > @@ -242,10 +242,9 @@ struct iked_policy {
> >  
> >  #define IKED_SKIP_FLAGS                     0
> >  #define IKED_SKIP_AF                        1
> > -#define IKED_SKIP_PROTO                     2
> > -#define IKED_SKIP_SRC_ADDR          3
> > -#define IKED_SKIP_DST_ADDR          4
> > -#define IKED_SKIP_COUNT                     5
> > +#define IKED_SKIP_SRC_ADDR          2
> > +#define IKED_SKIP_DST_ADDR          3
> > +#define IKED_SKIP_COUNT                     4
> >     struct iked_policy              *pol_skip[IKED_SKIP_COUNT];
> >  
> >     uint8_t                          pol_flags;
> > @@ -265,7 +264,8 @@ struct iked_policy {
> >     int                              pol_af;
> >     int                              pol_rdomain;
> >     uint8_t                          pol_saproto;
> > -   unsigned int                     pol_ipproto;
> > +   unsigned int                     pol_ipproto[IKED_IPPROTO_MAX];
> > +   unsigned int                     pol_nipproto;
> >  
> >     struct iked_addr                 pol_peer;
> >     struct iked_static_id            pol_peerid;
> > Index: parse.y
> > ===================================================================
> > RCS file: /cvs/src/sbin/iked/parse.y,v
> > retrieving revision 1.131
> > diff -u -p -r1.131 parse.y
> > --- parse.y 28 May 2021 18:01:39 -0000      1.131
> > +++ parse.y 2 Sep 2021 13:37:21 -0000
> > @@ -374,7 +374,7 @@ void                     copy_transforms(unsigned int,
> >                         const struct ipsec_xf **, unsigned int,
> >                         struct iked_transform **, unsigned int *,
> >                         struct iked_transform *, size_t);
> > -int                         create_ike(char *, int, uint8_t,
> > +int                         create_ike(char *, int, struct ipsec_addr_wrap 
> > *,
> >                         int, struct ipsec_hosts *,
> >                         struct ipsec_hosts *, struct ipsec_mode *,
> >                         struct ipsec_mode *, uint8_t,
> > @@ -388,9 +388,9 @@ uint8_t                  x2i(unsigned char *);
> >  int                         parsekey(unsigned char *, size_t, struct 
> > iked_auth *);
> >  int                         parsekeyfile(char *, struct iked_auth *);
> >  void                        iaw_free(struct ipsec_addr_wrap *);
> > -static int          create_flow(struct iked_policy *pol, struct 
> > ipsec_addr_wrap *ipa,
> > +static int          create_flow(struct iked_policy *pol, int, struct 
> > ipsec_addr_wrap *ipa,
> >                         struct ipsec_addr_wrap *ipb);
> > -static int          expand_flows(struct iked_policy *, struct 
> > ipsec_addr_wrap *,
> > +static int          expand_flows(struct iked_policy *, int, struct 
> > ipsec_addr_wrap *,
> >                         struct ipsec_addr_wrap *);
> >  static struct ipsec_addr_wrap *
> >                      expand_keyword(struct ipsec_addr_wrap *);
> > @@ -407,7 +407,6 @@ typedef struct {
> >             uint8_t                  ikemode;
> >             uint8_t                  dir;
> >             uint8_t                  satype;
> > -           uint8_t                  proto;
> >             char                    *string;
> >             uint16_t                 port;
> >             struct ipsec_hosts      *hosts;
> > @@ -415,6 +414,7 @@ typedef struct {
> >             struct ipsec_addr_wrap  *anyhost;
> >             struct ipsec_addr_wrap  *host;
> >             struct ipsec_addr_wrap  *cfg;
> > +           struct ipsec_addr_wrap  *proto;
> >             struct {
> >                     char            *srcid;
> >                     char            *dstid;
> > @@ -449,8 +449,7 @@ typedef struct {
> >  %token     <v.number>              NUMBER
> >  %type      <v.string>              string
> >  %type      <v.satype>              satype
> > -%type      <v.proto>               proto
> > -%type      <v.number>              protoval
> > +%type      <v.proto>               proto proto_list protoval
> >  %type      <v.hosts>               hosts hosts_list
> >  %type      <v.port>                port
> >  %type      <v.number>              portval af rdomain
> > @@ -632,8 +631,21 @@ af             : /* empty */                   { $$ = 
> > AF_UNSPEC; }
> >  
> >  proto              : /* empty */                   { $$ = 0; }
> >             | PROTO protoval                { $$ = $2; }
> > -           | PROTO ESP                     { $$ = IPPROTO_ESP; }
> > -           | PROTO AH                      { $$ = IPPROTO_AH; }
> > +           | PROTO '{' proto_list '}'      { $$ = $3; }
> 
> this will cause an error with old configs?

Yes and no. If the ESP and AH cases are moved to protoval then it will
work like before. This allows using ah and esp in this rule even though
they are yacc keywords and wont match the protoval yacc rule.
 
> Maybe people depend on it for connectivity, which makes it critical on
> upgrade.
> 
> Maybe its possible to keep old and new, and remove the old after 2 releases?
> (You can print a warning message in the parser for the old syntax).
> 
> In any case this should get a mention in current.html.

> > +           ;
> > +
> > +proto_list : protoval                      { $$ = $1; }
> > +           | proto_list comma protoval     {
> > +                   if ($3 == NULL)
> > +                           $$ = $1;
> > +                   else if ($1 == NULL)
> > +                           $$ = $3;
> > +                   else {
> > +                           $1->tail->next = $3;
> > +                           $1->tail = $3->tail;
> > +                           $$ = $1;
> > +                   }
> > +           }
> 
> why dont you make it 
> 
>               | protoval comma proto_list     {
> 
> then you dont need the conditional.

AFAIK yacc rules should be left expand. I don't fully remember the reason
but your example is not the common way.
 
> 
> >             ;
> >  
> >  protoval   : STRING                        {
> > @@ -644,7 +656,12 @@ protoval       : STRING                        {
> >                             yyerror("unknown protocol: %s", $1);
> >                             YYERROR;
> >                     }
> > -                   $$ = p->p_proto;
> > +
> > +                   if (($$ = calloc(1, sizeof(*$$))) == NULL)
> > +                           err(1, "hosts: calloc");
> > +
> > +                   $$->type = p->p_proto;
> > +                   $$->tail = $$;
> >                     free($1);
> >             }
> >             | NUMBER                        {
> > @@ -652,6 +669,11 @@ protoval       : STRING                        {
> >                             yyerror("protocol outside range");
> >                             YYERROR;
> >                     }
> > +                   if (($$ = calloc(1, sizeof(*$$))) == NULL)
> > +                           err(1, "hosts: calloc");
> > +
> > +                   $$->type = $1;
> > +                   $$->tail = $$;
> >             }

It would be helpful to add AH and ESP cases here.

                | AH {
                        if (($$ = calloc(1, sizeof(*$$))) == NULL)
                                err(1, "hosts: calloc");

                        $$->type = IPPROTO_AH;
                        $$->tail = $$;
                }
...

> >             ;
> >  
> > @@ -2444,7 +2466,7 @@ copy_transforms(unsigned int type,
> >  }
> >  
> >  int
> > -create_ike(char *name, int af, uint8_t ipproto,
> > +create_ike(char *name, int af, struct ipsec_addr_wrap *ipproto,
> >      int rdomain, struct ipsec_hosts *hosts,
> >      struct ipsec_hosts *peers, struct ipsec_mode *ike_sa,
> >      struct ipsec_mode *ipsec_sa, uint8_t saproto,
> > @@ -2454,7 +2476,7 @@ create_ike(char *name, int af, uint8_t i
> >      struct ipsec_addr_wrap *ikecfg, char *iface)
> >  {
> >     char                     idstr[IKED_ID_SIZE];
> > -   struct ipsec_addr_wrap  *ipa, *ipb;
> > +   struct ipsec_addr_wrap  *ipa, *ipb, *ipp;
> >     struct iked_auth        *ikeauth;
> >     struct iked_policy       pol;
> >     struct iked_proposal    *p, *ptmp;
> > @@ -2473,7 +2495,15 @@ create_ike(char *name, int af, uint8_t i
> >     pol.pol_certreqtype = env->sc_certreqtype;
> >     pol.pol_af = af;
> >     pol.pol_saproto = saproto;
> > -   pol.pol_ipproto = ipproto;
> > +   for (i = 0, ipp = ipproto; ipp; ipp = ipp->next, i++) {
> > +           if (i > IKED_IPPROTO_MAX) {
> > +                   yyerror("too many protocols");
> > +                   return (-1);
> 
> elsewhere in create_ike() you use fatalx() for errors, is the return value
> checked everywhere?
> 
> > +           }
> > +           pol.pol_ipproto[i] = ipp->type;
> > +           pol.pol_nipproto++;
> > +   }
> > +   
> >     pol.pol_flags = flags;
> >     pol.pol_rdomain = rdomain;
> >     memcpy(&pol.pol_auth, authtype, sizeof(struct iked_auth));
> > @@ -2826,10 +2856,13 @@ create_ike(char *name, int af, uint8_t i
> >     if (hosts == NULL || hosts->src == NULL || hosts->dst == NULL)
> >             fatalx("create_ike: no traffic selectors/flows");
> >  
> > -   for (ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
> > -       ipa = ipa->next, ipb = ipb->next)
> > -           if (expand_flows(&pol, ipa, ipb))
> > -                   fatalx("create_ike: invalid flow");
> > +   for (j = 0; j < pol.pol_nipproto; j++) {
> > +           for (ipa = hosts->src, ipb = hosts->dst; ipa && ipb;
> > +               ipa = ipa->next, ipb = ipb->next) {
> > +                   if (expand_flows(&pol, pol.pol_ipproto[j], ipa, ipb))
> > +                           fatalx("create_ike: invalid flow");
> > +           }
> > +   }
> >  
> >     for (j = 0, ipa = ikecfg; ipa; ipa = ipa->next, j++) {
> >             if (j >= IKED_CFG_MAX)
> > @@ -2918,6 +2951,7 @@ done:
> >             free(hosts);
> >     }
> >     iaw_free(ikecfg);
> > +   iaw_free(ipproto);
> >     RB_FOREACH_SAFE(flow, iked_flows, &pol.pol_flows, ftmp) {
> >             RB_REMOVE(iked_flows, &pol.pol_flows, flow);
> >             free(flow);
> > @@ -2929,7 +2963,7 @@ done:
> >  }
> >  
> >  static int
> > -create_flow(struct iked_policy *pol, struct ipsec_addr_wrap *ipa,
> > +create_flow(struct iked_policy *pol, int proto, struct ipsec_addr_wrap 
> > *ipa,
> >      struct ipsec_addr_wrap *ipb)
> >  {
> >     struct iked_flow        *flow;
> > @@ -2969,8 +3003,8 @@ create_flow(struct iked_policy *pol, str
> >     }
> >  
> >     flow->flow_dir = IPSP_DIRECTION_OUT;
> > +   flow->flow_ipproto = proto;
> >     flow->flow_saproto = pol->pol_saproto;
> > -   flow->flow_ipproto = pol->pol_ipproto;
> >     flow->flow_rdomain = pol->pol_rdomain;
> >  
> >     if (RB_INSERT(iked_flows, &pol->pol_flows, flow) == NULL)
> > @@ -2984,11 +3018,15 @@ create_flow(struct iked_policy *pol, str
> >  }
> >  
> >  static int
> > -expand_flows(struct iked_policy *pol, struct ipsec_addr_wrap *src,
> > +expand_flows(struct iked_policy *pol, int proto, struct ipsec_addr_wrap 
> > *src,
> >      struct ipsec_addr_wrap *dst)
> >  {
> >     struct ipsec_addr_wrap  *ipa = NULL, *ipb = NULL;
> >     int                      ret = -1;
> > +   int                      srcaf, dstaf;
> > +
> > +   srcaf = src->af;
> > +   dstaf = dst->af;
> >  
> >     if (src->af == AF_UNSPEC &&
> >         dst->af == AF_UNSPEC) {
> > @@ -2998,7 +3036,7 @@ expand_flows(struct iked_policy *pol, st
> >             ipb = expand_keyword(dst);
> >             if (!ipa || !ipb)
> >                     goto done;
> > -           if (create_flow(pol, ipa, ipb))
> > +           if (create_flow(pol, proto, ipa, ipb))
> >                     goto done;
> >  
> >             iaw_free(ipa);
> > @@ -3008,26 +3046,28 @@ expand_flows(struct iked_policy *pol, st
> >             ipb = expand_keyword(dst);
> >             if (!ipa || !ipb)
> >                     goto done;
> > -           if (create_flow(pol, ipa, ipb))
> > +           if (create_flow(pol, proto, ipa, ipb))
> >                     goto done;
> >     } else if (src->af == AF_UNSPEC) {
> >             src->af = dst->af;
> >             ipa = expand_keyword(src);
> >             if (!ipa)
> >                     goto done;
> > -           if (create_flow(pol, ipa, dst))
> > +           if (create_flow(pol, proto, ipa, dst))
> >                     goto done;
> >     } else if (dst->af == AF_UNSPEC) {
> >             dst->af = src->af;
> >             ipa = expand_keyword(dst);
> >             if (!ipa)
> >                     goto done;
> > -           if (create_flow(pol, src, ipa))
> > +           if (create_flow(pol, proto, src, ipa))
> >                     goto done;
> > -   } else if (create_flow(pol, src, dst))
> > +   } else if (create_flow(pol, proto, src, dst))
> >             goto done;
> >     ret = 0;
> >   done:
> > +   src->af = srcaf;
> > +   dst->af = dstaf;
> >     iaw_free(ipa);
> >     iaw_free(ipb);
> >     return (ret);
> > Index: policy.c
> > ===================================================================
> > RCS file: /cvs/src/sbin/iked/policy.c,v
> > retrieving revision 1.83
> > diff -u -p -r1.83 policy.c
> > --- policy.c        1 Sep 2021 15:30:06 -0000       1.83
> > +++ policy.c        2 Sep 2021 13:37:21 -0000
> > @@ -223,9 +223,6 @@ policy_test(struct iked *env, struct ike
> >             else if (key->pol_af && p->pol_af &&
> >                 key->pol_af != p->pol_af)
> >                     p = p->pol_skip[IKED_SKIP_AF];
> > -           else if (key->pol_ipproto && p->pol_ipproto &&
> > -               key->pol_ipproto != p->pol_ipproto)
> > -                   p = p->pol_skip[IKED_SKIP_PROTO];
> >             else if (sockaddr_cmp((struct sockaddr *)&key->pol_peer.addr,
> >                 (struct sockaddr *)&p->pol_peer.addr,
> >                 p->pol_peer.addr_mask) != 0)
> > @@ -334,9 +331,6 @@ policy_calc_skip_steps(struct iked_polic
> >                 prev->pol_af != AF_UNSPEC &&
> >                 cur->pol_af != prev->pol_af)
> >                     IKED_SET_SKIP_STEPS(IKED_SKIP_AF);
> > -           if (cur->pol_ipproto && prev->pol_ipproto &&
> > -               cur->pol_ipproto != prev->pol_ipproto)
> > -                   IKED_SET_SKIP_STEPS(IKED_SKIP_PROTO);
> >             if (IKED_ADDR_NEQ(&cur->pol_peer, &prev->pol_peer))
> >                     IKED_SET_SKIP_STEPS(IKED_SKIP_DST_ADDR);
> >             if (IKED_ADDR_NEQ(&cur->pol_local, &prev->pol_local))
> > Index: print.c
> > ===================================================================
> > RCS file: /cvs/src/sbin/iked/print.c,v
> > retrieving revision 1.2
> > diff -u -p -r1.2 print.c
> > --- print.c 21 Mar 2021 22:18:00 -0000      1.2
> > +++ print.c 2 Sep 2021 13:37:21 -0000
> > @@ -90,8 +90,16 @@ print_policy(struct iked_policy *pol)
> >  
> >     print_verbose(" %s", print_xf(pol->pol_saproto, 0, saxfs));
> >  
> > -   if (pol->pol_ipproto)
> > -           print_verbose(" proto %s", print_proto(pol->pol_ipproto));
> > +   if (pol->pol_nipproto > 0) {
> > +           print_verbose(" proto {");
> > +           for (i = 0; i < pol->pol_nipproto; i++) {
> > +                   if (i == 0)
> > +                           print_verbose(" %s", 
> > print_proto(pol->pol_ipproto[i]));
> > +                   else
> > +                           print_verbose(", %s", 
> > print_proto(pol->pol_ipproto[i]));
> > +           }
> > +           print_verbose(" }");
> > +   }
> >  
> >     if (pol->pol_af) {
> >             if (pol->pol_af == AF_INET)
> > Index: types.h
> > ===================================================================
> > RCS file: /cvs/src/sbin/iked/types.h,v
> > retrieving revision 1.45
> > diff -u -p -r1.45 types.h
> > --- types.h 1 Sep 2021 15:30:06 -0000       1.45
> > +++ types.h 2 Sep 2021 13:37:21 -0000
> > @@ -63,6 +63,7 @@
> >  #define IKED_PSK_SIZE              1024    /* XXX should be dynamic */
> >  #define IKED_MSGBUF_MAX            8192
> >  #define IKED_CFG_MAX               16      /* maximum CP attributes */
> > +#define IKED_IPPROTO_MAX   16
> >  #define IKED_TAG_SIZE              64
> >  #define IKED_CYCLE_BUFFERS 8       /* # of static buffers for mapping */
> >  #define IKED_PASSWORD_SIZE 256     /* limited by most EAP types */
> > 

-- 
:wq Claudio

Reply via email to