? isakmpd/run Index: ipsecctl/ike.c =================================================================== RCS file: /cvs/src/sbin/ipsecctl/ike.c,v retrieving revision 1.82 diff -u -p -r1.82 ike.c --- ipsecctl/ike.c 27 Oct 2017 08:29:32 -0000 1.82 +++ ipsecctl/ike.c 3 Apr 2022 09:12:02 -0000 @@ -148,6 +148,8 @@ ike_section_ipsec(struct ipsec_rule *r, if (r->tag) fprintf(fd, SET "[%s]:PF-Tag=%s force\n", r->p2name, r->tag); + if (r->interface) + fprintf(fd, SET "[%s]:Flags=Interface force\n", r->p2name); } static int @@ -691,16 +693,18 @@ ike_section_p2ids(struct ipsec_rule *r, src->name); } - if (src->srcnat && src->srcnat->netaddress) { - ike_section_p2ids_net(&src->srcnat->mask, src->af, src->srcnat->name, - r->p2nid, fd); - } else if (src->srcnat) { - fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n", - r->p2nid, ((src->af == AF_INET) ? 4 : 6)); - if ((p = strrchr(src->srcnat->name, '/')) != NULL) - *p = '\0'; - fprintf(fd, SET "[%s]:Address=%s force\n", r->p2nid, - src->srcnat->name); + if (src->srcnat) { + if (src->srcnat->netaddress) { + ike_section_p2ids_net(&src->srcnat->mask, src->af, + src->srcnat->name, r->p2nid, fd); + } else { + fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n", + r->p2nid, ((src->af == AF_INET) ? 4 : 6)); + if ((p = strrchr(src->srcnat->name, '/')) != NULL) + *p = '\0'; + fprintf(fd, SET "[%s]:Address=%s force\n", r->p2nid, + src->srcnat->name); + } } if (dst->netaddress) { Index: ipsecctl/ipsecctl.h =================================================================== RCS file: /cvs/src/sbin/ipsecctl/ipsecctl.h,v retrieving revision 1.75 diff -u -p -r1.75 ipsecctl.h --- ipsecctl/ipsecctl.h 22 Oct 2021 12:30:54 -0000 1.75 +++ ipsecctl/ipsecctl.h 3 Apr 2022 09:12:02 -0000 @@ -209,6 +209,7 @@ struct ipsec_rule { u_int8_t p1ie; u_int8_t p2ie; u_int8_t udpencap; + u_int8_t interface; /* negotiate tunnel, but protect gif */ u_int16_t udpdport; u_int16_t sport; u_int16_t dport; Index: ipsecctl/parse.y =================================================================== RCS file: /cvs/src/sbin/ipsecctl/parse.y,v retrieving revision 1.181 diff -u -p -r1.181 parse.y --- ipsecctl/parse.y 22 Oct 2021 12:30:54 -0000 1.181 +++ ipsecctl/parse.y 3 Apr 2022 09:12:02 -0000 @@ -285,7 +285,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 BUNDLE UDPENCAP +%token INCLUDE BUNDLE UDPENCAP ROUTING %token STRING %token NUMBER %type string @@ -399,9 +399,44 @@ ikerule : IKE ikemode satype tmode prot if (r == NULL) YYERROR; + r->interface = 0; + if (expand_rule(r, &$7, 0, 0, NULL, NULL, NULL)) errx(1, "ikerule: expand_rule"); } + /* ike routing from $h_self to $h_s2s1 ... */ + | IKE ikemode ROUTING peers + phase1mode phase2mode ids ikeauth { + uint8_t proto = IPPROTO_IPIP; + struct ipsec_hosts hosts; + struct ike_mode *phase1mode = $5; + struct ike_mode *phase2mode = $6; + uint8_t satype = IPSEC_ESP; + uint8_t tmode = IPSEC_TRANSPORT; + uint8_t mode = $2; + struct ike_auth *authtype = &$8; + char *tag = NULL; + + struct ipsec_rule *r; + + hosts.src = copyhost($4.src); + hosts.sport = htons(0); + hosts.dst = copyhost($4.dst); + hosts.dport = htons(0); + + r = create_ike(proto, &hosts, phase1mode, phase2mode, + satype, tmode, mode, $7.srcid, $7.dstid, + authtype, tag); + if (r == NULL) { + YYERROR; + } + + r->interface = 1; + + if (expand_rule(r, &$4, 0, 0, NULL, NULL, NULL)) + errx(1, "ikerule: expand routint rule"); + + } ; satype : /* empty */ { $$ = IPSEC_ESP; } @@ -1023,6 +1058,7 @@ lookup(char *s) { "psk", PSK }, { "quick", QUICK }, { "require", REQUIRE }, + { "routing", ROUTING }, { "rsa", RSA }, { "spi", SPI }, { "srcid", SRCID }, @@ -2232,6 +2268,7 @@ copyrule(struct ipsec_rule *rule) r->udpencap = rule->udpencap; r->udpdport = rule->udpdport; r->nr = rule->nr; + r->interface = rule->interface; return (r); } Index: isakmpd/exchange.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/exchange.c,v retrieving revision 1.142 diff -u -p -r1.142 exchange.c --- isakmpd/exchange.c 15 Jan 2018 09:54:48 -0000 1.142 +++ isakmpd/exchange.c 3 Apr 2022 09:12:02 -0000 @@ -854,6 +854,7 @@ exchange_establish_p2(struct sa *isakmp_ u_int32_t seq = 0; int i; char *tag, *str; + int interface = 0; if (isakmp_sa) doi = isakmp_sa->doi->id; @@ -897,6 +898,22 @@ exchange_establish_p2(struct sa *isakmp_ return -1; } } + + { + struct conf_list *attrs; + struct conf_list_node *attr; + int flags = 0; + + attrs = conf_get_list(name, "Flags"); + if (attrs) { + for (attr = TAILQ_FIRST(&attrs->fields); attr; + attr = TAILQ_NEXT(attr, link)) + flags |= sa_flag(attr->field); + conf_free_list(attrs); + } + + interface = (flags & SA_FLAG_INTERFACE); + } } exchange = exchange_create(2, 1, doi, type); if (!exchange) { @@ -922,6 +939,8 @@ exchange_establish_p2(struct sa *isakmp_ exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE) exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; + if (interface) + exchange->flags |= EXCHANGE_FLAG_INTERFACE; exchange_enter(exchange); exchange_dump("exchange_establish_p2", exchange); Index: isakmpd/exchange.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/exchange.h,v retrieving revision 1.37 diff -u -p -r1.37 exchange.h --- isakmpd/exchange.h 15 Jan 2018 09:54:48 -0000 1.37 +++ isakmpd/exchange.h 3 Apr 2022 09:12:02 -0000 @@ -224,6 +224,7 @@ struct exchange { #define EXCHANGE_FLAG_NAT_T_RFC 0x0080 /* Peer does RFC NAT-T. */ #define EXCHANGE_FLAG_NAT_T_DRAFT 0x0100 /* Peer does draft NAT-T.*/ #define EXCHANGE_FLAG_OPENBSD 0x0200 /* Peer is OpenBSD */ +#define EXCHANGE_FLAG_INTERFACE 0x0400 extern int exchange_add_certs(struct message *); extern int exchange_add_certreqs(struct message *); Index: isakmpd/ike_quick_mode.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/ike_quick_mode.c,v retrieving revision 1.114 diff -u -p -r1.114 ike_quick_mode.c --- isakmpd/ike_quick_mode.c 15 Jan 2018 09:54:48 -0000 1.114 +++ isakmpd/ike_quick_mode.c 3 Apr 2022 09:12:02 -0000 @@ -409,6 +409,7 @@ initiator_send_HASH_SA_NONCE(struct mess char *name; int group_desc = -1, new_group_desc; struct ipsec_sa *isa = msg->isakmp_sa->data; + int interface = exchange->flags & EXCHANGE_FLAG_INTERFACE; struct hash *hash = hash_get(isa->hash); struct sockaddr *src; struct proto_attr *pa; @@ -629,9 +630,8 @@ initiator_send_HASH_SA_NONCE(struct mess name = conf_get_str(xf->field, "ENCAPSULATION_MODE"); if (name) { - value = constant_value( - ipsec_encap_cst, - name); + value = interface ? IPSEC_ENCAP_TUNNEL : + constant_value(ipsec_encap_cst, name); switch (value) { case IPSEC_ENCAP_TUNNEL: value = exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT ? @@ -649,6 +649,11 @@ initiator_send_HASH_SA_NONCE(struct mess IPSEC_ATTR_ENCAPSULATION_MODE, value); } + } else if (interface) { + attr = attribute_set_basic( + attr, + IPSEC_ATTR_ENCAPSULATION_MODE, + IPSEC_ENCAP_TUNNEL); } else { attribute_set_constant(xf->field, "ENCAPSULATION_MODE", @@ -901,9 +906,35 @@ initiator_send_HASH_SA_NONCE(struct mess return -1; } } + /* Generate optional client ID payloads. XXX Share with responder. */ - local_id = conf_get_str(exchange->name, "Local-ID"); - remote_id = conf_get_str(exchange->name, "Remote-ID"); + if (interface) { + id = ipsec_build_interface_id(&sz); + if (id == NULL) + return -1; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_send_HASH_SA_NONCE: IDic", id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } + + id = ipsec_build_interface_id(&sz); + if (id == NULL) + return -1; + LOG_DBG_BUF((LOG_NEGOTIATION, 90, + "initiator_send_HASH_SA_NONCE: IDrc", id, sz)); + if (message_add_payload(msg, ISAKMP_PAYLOAD_ID, id, sz, 1)) { + free(id); + return -1; + } + + local_id = NULL; + remote_id = NULL; + } else { + local_id = conf_get_str(exchange->name, "Local-ID"); + remote_id = conf_get_str(exchange->name, "Remote-ID"); + } if (local_id && remote_id) { id = ipsec_build_id(local_id, &sz); if (!id) @@ -1044,6 +1075,7 @@ initiator_recv_HASH_SA_NONCE(struct mess struct payload *kep = payload_first(msg, ISAKMP_PAYLOAD_KEY_EXCH); struct prf *prf; struct sa *isakmp_sa = msg->isakmp_sa; + int interface = exchange->flags & EXCHANGE_FLAG_INTERFACE; struct ipsec_sa *isa = isakmp_sa->data; struct hash *hash = hash_get(isa->hash); u_int8_t *rest; @@ -1133,7 +1165,7 @@ initiator_recv_HASH_SA_NONCE(struct mess } /* Handle optional client ID payloads. */ - idp = payload_first(msg, ISAKMP_PAYLOAD_ID); + idp = interface ? NULL : payload_first(msg, ISAKMP_PAYLOAD_ID); if (idp) { /* If IDci is there, IDcr must be too. */ if (!TAILQ_NEXT(idp, link)) { Index: isakmpd/ipsec.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v retrieving revision 1.152 diff -u -p -r1.152 ipsec.c --- isakmpd/ipsec.c 16 Jan 2022 14:30:11 -0000 1.152 +++ isakmpd/ipsec.c 3 Apr 2022 09:12:02 -0000 @@ -1501,6 +1501,7 @@ ipsec_decode_attribute(u_int16_t type, u case IPSEC_ATTR_GROUP_DESCRIPTION: isa->group_desc = decode_16(value); break; +#if 0 case IPSEC_ATTR_ENCAPSULATION_MODE: /* * XXX Multiple protocols must have same @@ -1508,6 +1509,7 @@ ipsec_decode_attribute(u_int16_t type, u */ iproto->encap_mode = decode_16(value); break; +#endif case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: iproto->auth = decode_16(value); break; @@ -2217,6 +2219,29 @@ ipsec_build_id(char *section, size_t *sz free(mask); free(addr); return p; +} + +u_int8_t * +ipsec_build_interface_id(size_t *sz) +{ + size_t len = ISAKMP_ID_SZ + 4 + 4; + uint8_t *p; + + p = malloc(len); + if (p == NULL) { + log_print("%s: malloc(%zu) failed", __func__, len); + return 0; + } + + memset(p, 0, len); + + SET_ISAKMP_ID_TYPE(p, IPSEC_ID_IPV4_ADDR_SUBNET); + SET_ISAKMP_ID_DOI_DATA(p, (unsigned char *)"\000\000\000"); + SET_IPSEC_ID_PROTO(p + ISAKMP_ID_DOI_DATA_OFF, IPPROTO_IPIP); + SET_IPSEC_ID_PORT(p + ISAKMP_ID_DOI_DATA_OFF, 0); + + *sz = len; + return (p); } /* Index: isakmpd/ipsec.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/ipsec.h,v retrieving revision 1.27 diff -u -p -r1.27 ipsec.h --- isakmpd/ipsec.h 8 Nov 2017 13:33:49 -0000 1.27 +++ isakmpd/ipsec.h 3 Apr 2022 09:12:02 -0000 @@ -144,6 +144,7 @@ struct ipsec_proto { extern u_int8_t *ipsec_add_hash_payload(struct message *, size_t); extern int ipsec_ah_keylength(struct proto *); extern u_int8_t *ipsec_build_id(char *, size_t *); +extern u_int8_t *ipsec_build_interface_id(size_t *); extern int ipsec_decode_attribute(u_int16_t, u_int8_t *, u_int16_t, void *); extern void ipsec_decode_transform(struct message *, struct sa *, Index: isakmpd/sa.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/sa.c,v retrieving revision 1.125 diff -u -p -r1.125 sa.c --- isakmpd/sa.c 28 Jan 2022 05:24:15 -0000 1.125 +++ isakmpd/sa.c 3 Apr 2022 09:12:02 -0000 @@ -1289,6 +1289,9 @@ sa_flag(char *attr) { "active-only", SA_FLAG_ACTIVE_ONLY }, + { + "interface", SA_FLAG_INTERFACE + }, /* * Below this point are flags that are internal to the Index: isakmpd/sa.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/sa.h,v retrieving revision 1.54 diff -u -p -r1.54 sa.h --- isakmpd/sa.h 15 Jan 2018 09:54:48 -0000 1.54 +++ isakmpd/sa.h 3 Apr 2022 09:12:02 -0000 @@ -244,6 +244,9 @@ struct sa { #define SA_FLAG_NAT_T_ENABLE 0x100 #define SA_FLAG_NAT_T_KEEPALIVE 0x200 +/* Negotiate a TUNNEL, but install TRANSPORT SAs to protect gif(4) traffic */ +#define SA_FLAG_INTERFACE 0x400 + extern void proto_free(struct proto * proto); extern int sa_add_transform(struct sa *, struct payload *, int, struct proto **);