Hi, here is an update of the last diff rebased onto current with minor fixes. There were some problems when multiple transport and non-transport policies were configured, which should now be fixed. I also have a test case for the new regression test which runs successfully.
ok? diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5 index 671cb5c7955..5af0a2e6d63 100644 --- a/sbin/iked/iked.conf.5 +++ b/sbin/iked/iked.conf.5 @@ -271,6 +271,15 @@ The optional compression is applied before packets are encapsulated. IPcomp must be enabled in the kernel: .Pp .Dl # sysctl net.inet.ipcomp.enable=1 +.It Op Ar tmode +.Ar tmode +describes the encapsulation mode to be used. +Possible modes are +.Ar tunnel +and +.Ar transport ; +the default is +.Ar tunnel . .It Op Ar encap .Ar encap specifies the encapsulation protocol to be used. @@ -280,15 +289,6 @@ and .Ar ah ; the default is .Ar esp . -.\" .It Op Ar tmode -.\" .Ar tmode -.\" describes the encapsulation mode to be used. -.\" Possible modes are -.\" .Ar tunnel -.\" and -.\" .Ar transport ; -.\" the default is -.\" .Ar tunnel . .It Op Ar af This policy only applies to endpoints of the specified address family which can be either diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index d99d52ff77c..7b4c2075810 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -254,6 +254,7 @@ struct iked_policy { #define IKED_POLICY_QUICK 0x08 #define IKED_POLICY_SKIP 0x10 #define IKED_POLICY_IPCOMP 0x20 +#define IKED_POLICY_TRANSPORT 0x40 int pol_refcnt; @@ -481,6 +482,9 @@ struct iked_sa { int sa_mobike; /* MOBIKE */ int sa_frag; /* fragmentation */ + int sa_use_transport_mode; /* peer requested */ + int sa_used_transport_mode; /* we enabled */ + struct iked_timer sa_timer; /* SA timeouts */ #define IKED_IKE_SA_EXCHANGE_TIMEOUT 300 /* 5 minutes */ #define IKED_IKE_SA_REKEY_TIMEOUT 120 /* 2 minutes */ diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index 842e8da110f..505cd31a204 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -142,15 +142,17 @@ int ikev2_cp_setaddr(struct iked *, struct iked_sa *, sa_family_t); int ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *, struct iked_addr *); -ssize_t ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **, +ssize_t ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **, ssize_t); -ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *, +ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *, struct ikev2_payload **, struct iked_message *, ssize_t); ssize_t ikev2_add_notify(struct ibuf *, struct ikev2_payload **, ssize_t, - uint16_t); + uint16_t); ssize_t ikev2_add_mobike(struct ibuf *, struct ikev2_payload **, ssize_t); -ssize_t ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **, - struct iked_message *, ssize_t); +ssize_t ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **, + struct iked_message *, ssize_t); +ssize_t ikev2_add_transport_mode(struct iked *, struct ibuf *, + struct ikev2_payload **, ssize_t, struct iked_sa *); int ikev2_update_sa_addresses(struct iked *, struct iked_sa *); int ikev2_resp_informational(struct iked *, struct iked_sa *, struct iked_message *); @@ -1246,10 +1248,13 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa) goto done; } - /* compression */ + /* compression, transport mode */ if ((pol->pol_flags & IKED_POLICY_IPCOMP) && (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 1)) == -1) goto done; + if ((pol->pol_flags & IKED_POLICY_TRANSPORT) && + (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) + goto done; if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA) == -1) goto done; @@ -1786,6 +1791,13 @@ ikev2_add_sighashnotify(struct ibuf *e, struct ikev2_payload **pld, return (len); } +ssize_t +ikev2_add_transport_mode(struct iked *env, struct ibuf *e, + struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa) +{ + return ikev2_add_notify(e, pld, len, IKEV2_N_USE_TRANSPORT_MODE); +} + int ikev2_next_payload(struct ikev2_payload *pld, size_t length, uint8_t nextpayload) @@ -2990,10 +3002,13 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) goto done; } - /* compression */ + /* compression, transport mode */ if (sa->sa_ipcompr.ic_transform && (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 0)) == -1) goto done; + if (sa->sa_used_transport_mode && + (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) + goto done; /* MOBIKE */ if (sa->sa_mobike && @@ -3233,10 +3248,13 @@ ikev2_send_create_child_sa(struct iked *env, struct iked_sa *sa, if ((e = ibuf_static()) == NULL) goto done; - /* compression */ + /* compression, transport mode */ if ((pol->pol_flags & IKED_POLICY_IPCOMP) && (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 1)) == -1) goto done; + if ((pol->pol_flags & IKED_POLICY_TRANSPORT) && + (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) + goto done; if (pld) { firstpayload = IKEV2_PAYLOAD_NOTIFY; @@ -4055,10 +4073,13 @@ ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg) if ((e = ibuf_static()) == NULL) goto done; - /* compression (unless IKE rekeying) */ + /* compression, transport mode (unless IKE rekeying) */ if (!nsa && sa->sa_ipcompr.ic_transform && (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 0)) == -1) goto done; + if (!nsa && sa->sa_used_transport_mode && + (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) + goto done; if (pld) { firstpayload = IKEV2_PAYLOAD_NOTIFY; @@ -5320,6 +5341,9 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, (initiator && ic->ic_cpi_in == 0)) ic = NULL; + /* reset state */ + sa->sa_used_transport_mode = 0; + /* We need to determine the key material length first */ TAILQ_FOREACH(prop, proposals, prop_entry) { if (prop->prop_protoid == IKEV2_SAPROTO_IKE) @@ -5460,6 +5484,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, csa->csa_spi.spi_protoid = prop->prop_protoid; csa->csa_esn = esn; csa->csa_acquired = acquired; + csa->csa_transport = sa->sa_use_transport_mode; + sa->sa_used_transport_mode = sa->sa_use_transport_mode; /* Set up responder's SPIs */ if (initiator) { @@ -5597,6 +5623,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, ret = 0; done: + sa->sa_use_transport_mode = 0; /* reset state after use */ ibuf_release(dhsecret); ibuf_release(keymat); ibuf_release(seed); diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index 5cf0dee6615..c13a7e11158 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1172,6 +1172,24 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, } msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE; break; + case IKEV2_N_USE_TRANSPORT_MODE: + if (!msg->msg_e) { + log_debug("%s: N_USE_TRANSPORT_MODE not encrypted", + __func__); + return (-1); + } + if (len != 0) { + log_debug("%s: ignoring malformed transport mode" + " notification: %zu", __func__, len); + return (0); + } + if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) { + log_debug("%s: ignoring transport mode" + " notification (policy)", __func__); + return (0); + } + msg->msg_sa->sa_use_transport_mode = 1; + break; case IKEV2_N_UPDATE_SA_ADDRESSES: if (!msg->msg_e) { log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted", diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y index fe052068922..3ca68e2fd7a 100644 --- a/sbin/iked/parse.y +++ b/sbin/iked/parse.y @@ -426,7 +426,7 @@ typedef struct { %type <v.id> id %type <v.transforms> transforms %type <v.filters> filters -%type <v.ikemode> ikeflags ikematch ikemode ipcomp +%type <v.ikemode> ikeflags ikematch ikemode ipcomp tmode %type <v.ikeauth> ikeauth %type <v.ikekey> keyspec %type <v.mode> ike_sas child_sas @@ -890,7 +890,7 @@ child_sa : CHILDSA { } ; -ikeflags : ikematch ikemode ipcomp { $$ = $1 | $2 | $3; } +ikeflags : ikematch ikemode ipcomp tmode { $$ = $1 | $2 | $3 | $4; } ; ikematch : /* empty */ { $$ = 0; } @@ -908,6 +908,11 @@ ipcomp : /* empty */ { $$ = 0; } | IPCOMP { $$ = IKED_POLICY_IPCOMP; } ; +tmode : /* empty */ { $$ = 0; } + | TUNNEL { $$ = 0; } + | TRANSPORT { $$ = IKED_POLICY_TRANSPORT; } + ; + ikeauth : /* empty */ { $$.auth_method = IKEV2_AUTH_SIG_ANY; /* default */ $$.auth_eap = 0; @@ -2465,6 +2470,9 @@ print_policy(struct iked_policy *pol) else print_verbose(" passive"); + if (pol->pol_flags & IKED_POLICY_TRANSPORT) + print_verbose(" transport"); + print_verbose(" %s", print_xf(pol->pol_saproto, 0, saxfs)); if (pol->pol_ipproto)