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?

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.


>               ;
>  
>  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 = $$;
>               }
>               ;
>  
> @@ -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 */
> 

Reply via email to