Hi,

Currently ipsecctl(8) groups SAs with identical src and dst to the
flow which the first SA with the type of the flow matches.  This
behaviour is mostly undocumented and unexpected.  I want to make
this explicit in the ipsec.conf(5).  I have chosen the keyword
bundle for the SA groups, as group is already used for DH.  The
bundles are already mentioned in ipcomp(4).

markus@ has suggested to remove the feature from the kernel to
reduce complexity.  But I think it is useful for compression.  You
make one flow lookup and do several SA transformations.  I just
don't want it automatically as it makes testing IPsec hard.  isakmpd(8)
has some code that might use bundles.

This change could break existing setups, but I doubt that anyone
uses the feature intentionally.  I discovered it by reading source
code.

ok?

bluhm

Index: sbin/ipsecctl/ipsec.conf.5
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sbin/ipsecctl/ipsec.conf.5,v
retrieving revision 1.151
diff -u -p -r1.151 ipsec.conf.5
--- sbin/ipsecctl/ipsec.conf.5  9 Dec 2015 21:41:50 -0000       1.151
+++ sbin/ipsecctl/ipsec.conf.5  12 Apr 2017 19:53:30 -0000
@@ -918,6 +918,15 @@ authkey file "filename"
 .It Ic enckey Ar keyspec
 The encryption key is defined similarly to
 .Ic authkey .
+.It Ic bundle Ar identifier
+Several SAs can be attached to a single flow.
+The cryptographic transforms are applied in order.
+The type of the first SA has to match the type of the flow.
+All SAs with identical
+.Ar src , dst ,
+and
+.Ar identifier
+are grouped together.
 .It Xo
 .Ic tcpmd5
 .Ic from Ar src
Index: sbin/ipsecctl/ipsecctl.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sbin/ipsecctl/ipsecctl.h,v
retrieving revision 1.69
diff -u -p -r1.69 ipsecctl.h
--- sbin/ipsecctl/ipsecctl.h    9 Dec 2015 21:41:50 -0000       1.69
+++ sbin/ipsecctl/ipsecctl.h    12 Apr 2017 17:50:16 -0000
@@ -216,6 +216,7 @@ struct ipsec_rule {
        TAILQ_ENTRY(ipsec_rule) dst_group_entry;
 
        struct dst_group_queue  dst_group_queue;
+       char                    *bundle;
 };
 
 TAILQ_HEAD(ipsec_rule_queue, ipsec_rule);
Index: sbin/ipsecctl/parse.y
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sbin/ipsecctl/parse.y,v
retrieving revision 1.166
diff -u -p -r1.166 parse.y
--- sbin/ipsecctl/parse.y       5 Jan 2017 12:42:18 -0000       1.166
+++ sbin/ipsecctl/parse.y       12 Apr 2017 17:50:16 -0000
@@ -201,13 +201,13 @@ int                        set_rule_peers(struct 
ipsec_rule 
 void                    expand_any(struct ipsec_addr_wrap *);
 int                     expand_rule(struct ipsec_rule *, struct ipsec_hosts *,
                             u_int8_t, u_int32_t, struct ipsec_key *,
-                            struct ipsec_key *, int);
+                            struct ipsec_key *, char *);
 struct ipsec_rule      *reverse_rule(struct ipsec_rule *);
 struct ipsec_rule      *create_ike(u_int8_t, struct ipsec_hosts *,
                             struct ike_mode *, struct ike_mode *, u_int8_t,
                             u_int8_t, u_int8_t, char *, char *,
                             struct ike_auth *, char *);
-int                     add_sagroup(struct ipsec_rule *);
+int                     add_sagroup(struct ipsec_rule *, char *);
 int                     get_id_type(char *);
 
 struct ipsec_transforms *ipsec_transforms;
@@ -263,7 +263,7 @@ typedef struct {
 %token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK AGGRESSIVE
 %token PASSIVE ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC LIFETIME
 %token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT TAG
-%token INCLUDE
+%token INCLUDE BUNDLE
 %token <v.string>              STRING
 %token <v.number>              NUMBER
 %type  <v.string>              string
@@ -284,6 +284,7 @@ typedef struct {
 %type  <v.spis>                spispec
 %type  <v.authkeys>            authkeyspec
 %type  <v.enckeys>             enckeyspec
+%type  <v.string>              bundlestring
 %type  <v.keys>                keyspec
 %type  <v.transforms>          transforms
 %type  <v.ikemode>             ikemode
@@ -333,13 +334,13 @@ tcpmd5rule        : TCPMD5 hosts spispec authke
                                YYERROR;
 
                        if (expand_rule(r, NULL, 0, $3.spiin, $4.keyin, NULL,
-                           0))
+                           NULL))
                                errx(1, "tcpmd5rule: expand_rule");
                }
                ;
 
 sarule         : satype tmode hosts spispec transforms authkeyspec
-                   enckeyspec {
+                   enckeyspec bundlestring {
                        struct ipsec_rule       *r;
 
                        r = create_sa($1, $2, &$3, $4.spiout, $5, $6.keyout,
@@ -348,7 +349,7 @@ sarule              : satype tmode hosts spispec tra
                                YYERROR;
 
                        if (expand_rule(r, NULL, 0, $4.spiin, $6.keyin,
-                           $7.keyin, 1))
+                           $7.keyin, $8))
                                errx(1, "sarule: expand_rule");
                }
                ;
@@ -361,7 +362,7 @@ flowrule    : FLOW satype dir proto hosts p
                        if (r == NULL)
                                YYERROR;
 
-                       if (expand_rule(r, &$6, $3, 0, NULL, NULL, 0))
+                       if (expand_rule(r, &$6, $3, 0, NULL, NULL, NULL))
                                errx(1, "flowrule: expand_rule");
                }
                ;
@@ -375,7 +376,7 @@ ikerule             : IKE ikemode satype tmode prot
                        if (r == NULL)
                                YYERROR;
 
-                       if (expand_rule(r, &$7, 0, 0, NULL, NULL, 0))
+                       if (expand_rule(r, &$7, 0, 0, NULL, NULL, NULL))
                                errx(1, "ikerule: expand_rule");
                }
                ;
@@ -806,6 +807,10 @@ enckeyspec : /* empty */                   {
                }
                ;
 
+bundlestring   : /* empty */                   { $$ = NULL; }
+               | BUNDLE STRING                 { $$ = $2; }
+               ;
+
 keyspec                : STRING                        {
                        unsigned char   *hex;
                        unsigned char   *p = strchr($1, ':');
@@ -950,6 +955,7 @@ lookup(char *s)
                { "any",                ANY },
                { "auth",               AUTHXF },
                { "authkey",            AUTHKEY },
+               { "bundle",             BUNDLE },
                { "bypass",             BYPASS },
                { "comp",               COMPXF },
                { "deny",               DENY },
@@ -2338,14 +2344,15 @@ validate_sa(u_int32_t spi, u_int8_t saty
 }
 
 int
-add_sagroup(struct ipsec_rule *r)
+add_sagroup(struct ipsec_rule *r, char *bundle)
 {
        struct ipsec_rule       *rp, *last, *group;
        int                      found = 0;
 
        TAILQ_FOREACH(rp, &ipsec->group_queue, group_entry) {
                if ((strcmp(rp->src->name, r->src->name) == 0) &&
-                   (strcmp(rp->dst->name, r->dst->name) == 0)) {
+                   (strcmp(rp->dst->name, r->dst->name) == 0) &&
+                   (strcmp(rp->bundle, bundle) == 0)) {
                        found = 1;
                        break;
                }
@@ -2365,6 +2372,7 @@ add_sagroup(struct ipsec_rule *r)
                TAILQ_INSERT_TAIL(&ipsec->group_queue, r, group_entry);
                TAILQ_INIT(&r->dst_group_queue);
                TAILQ_INSERT_TAIL(&r->dst_group_queue, r, dst_group_entry);
+               r->bundle = bundle;
        }
 
        return (0);
@@ -2624,7 +2632,7 @@ set_rule_peers(struct ipsec_rule *r, str
 int
 expand_rule(struct ipsec_rule *rule, struct ipsec_hosts *peers,
     u_int8_t direction, u_int32_t spi, struct ipsec_key *authkey,
-    struct ipsec_key *enckey, int group)
+    struct ipsec_key *enckey, char *bundle)
 {
        struct ipsec_rule       *r, *revr;
        struct ipsec_addr_wrap  *src, *dst;
@@ -2653,7 +2661,7 @@ expand_rule(struct ipsec_rule *rule, str
                        r->nr = ipsec->rule_nr++;
                        if (ipsecctl_add_rule(ipsec, r))
                                goto out;
-                       if (group && add_sagroup(r))
+                       if (bundle && add_sagroup(r, bundle))
                                goto out;
 
                        if (direction == IPSEC_INOUT) {
@@ -2665,7 +2673,7 @@ expand_rule(struct ipsec_rule *rule, str
                                revr->nr = ipsec->rule_nr++;
                                if (ipsecctl_add_rule(ipsec, revr))
                                        goto out;
-                               if (group && add_sagroup(revr))
+                               if (bundle && add_sagroup(revr, bundle))
                                        goto out;
                        } else if (spi != 0 || authkey || enckey) {
                                /* Create and add reverse sa rule. */
@@ -2676,7 +2684,7 @@ expand_rule(struct ipsec_rule *rule, str
                                revr->nr = ipsec->rule_nr++;
                                if (ipsecctl_add_rule(ipsec, revr))
                                        goto out;
-                               if (group && add_sagroup(revr))
+                               if (bundle && add_sagroup(revr, bundle))
                                        goto out;
                        }
                        added++;

Reply via email to