diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2006-03-30 12:44:21 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2006-03-30 12:44:21 +0000 |
commit | 83b85debd5c8628d50897246c6639bafeb73e261 (patch) | |
tree | 78da9591258454546269eea10881033d358be860 /sbin/ipsecctl | |
parent | 51def059c38d8d7e87cd814ba4489e9a2e0f29a3 (diff) |
allow specification of outer local ips in flows (SADB_EXT_ADDRESS_SRC); ok hshoexer, reyk
Diffstat (limited to 'sbin/ipsecctl')
-rw-r--r-- | sbin/ipsecctl/ipsec.conf.5 | 14 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.c | 14 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.h | 3 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 38 | ||||
-rw-r--r-- | sbin/ipsecctl/pfkey.c | 64 |
5 files changed, 105 insertions, 28 deletions
diff --git a/sbin/ipsecctl/ipsec.conf.5 b/sbin/ipsecctl/ipsec.conf.5 index 90d1517964b..4b5ad686a6a 100644 --- a/sbin/ipsecctl/ipsec.conf.5 +++ b/sbin/ipsecctl/ipsec.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ipsec.conf.5,v 1.33 2006/03/22 16:01:23 reyk Exp $ +.\" $OpenBSD: ipsec.conf.5,v 1.34 2006/03/30 12:44:20 markus Exp $ .\" .\" Copyright (c) 2004 Mathieu Sauve-Frankel All rights reserved. .\" @@ -112,6 +112,8 @@ Thus packets in both directions will be matched. .Aq Ar src .Ar to .Aq Ar dst +.Ar local +.Aq Ar localip .Ar peer .Aq Ar remote .Xc @@ -124,8 +126,12 @@ The keyword .Ar any will match any address (i.e. 0.0.0.0/0). The +.Ar local +parameter specifies the address of the local endpoint of this particular +flow and can be usually left out. +The .Ar peer -parameter specifies the address of the remote endpoint of this particular +parameter specifies the address of the remote endpoint of this flow. For host-to-host connections where .Aq Ar dst @@ -526,6 +532,10 @@ flow esp from 192.168.7.0/24 to 192.168.8.0/24 peer 192.168.3.12 flow esp out from 192.168.7.0/24 to 192.168.8.0/24 peer 192.168.3.12 flow esp in from 192.168.8.0/24 to 192.168.7.0/24 peer 192.168.3.12 +# Same as above, but explicitly specifying the local gateway ip +flow esp from 192.168.7.0/24 to 192.168.8.0/24 \e + local 192.168.1.1 peer 192.168.3.12 + # Set up IPsec SAs for flows between 192.168.3.14 and 192.168.3.12 esp from 192.168.3.14 to 192.168.3.12 spi 0xdeadbeef:0xbeefdead \e auth hmac-sha2-256 enc aesctr authkey file "auth14:auth12" \e diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c index 6a055c6d2b7..4291691484d 100644 --- a/sbin/ipsecctl/ipsecctl.c +++ b/sbin/ipsecctl/ipsecctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.c,v 1.43 2006/03/22 16:01:23 reyk Exp $ */ +/* $OpenBSD: ipsecctl.c,v 1.44 2006/03/30 12:44:20 markus Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -167,6 +167,10 @@ ipsecctl_commit(int action, struct ipsecctl *ipsec) free(rp->dst->name); free(rp->dst); + if (rp->local) { + free(rp->local->name); + free(rp->local); + } if (rp->peer) { free(rp->peer->name); free(rp->peer); @@ -249,6 +253,10 @@ ipsecctl_print_flow(struct ipsec_rule *r, int opts) ipsecctl_print_addr(r->src); printf(" to "); ipsecctl_print_addr(r->dst); + if (r->local) { + printf(" local "); + ipsecctl_print_addr(r->local); + } if (r->peer) { printf(" peer "); ipsecctl_print_addr(r->peer); @@ -423,6 +431,10 @@ ipsecctl_show_flows(int opts) free(rp->src); free(rp->dst->name); free(rp->dst); + if (rp->local) { + free(rp->local->name); + free(rp->local); + } if (rp->peer) { free(rp->peer->name); free(rp->peer); diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h index 455e72acd47..4854a95453e 100644 --- a/sbin/ipsecctl/ipsecctl.h +++ b/sbin/ipsecctl/ipsecctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.h,v 1.29 2006/03/22 16:01:23 reyk Exp $ */ +/* $OpenBSD: ipsecctl.h,v 1.30 2006/03/30 12:44:20 markus Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -134,6 +134,7 @@ struct ipsec_rule { struct ipsec_addr_wrap *src; struct ipsec_addr_wrap *dst; + struct ipsec_addr_wrap *local; struct ipsec_addr_wrap *peer; struct ipsec_auth *auth; struct ike_auth *ikeauth; diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y index 25b7bc281ef..97d544f2007 100644 --- a/sbin/ipsecctl/parse.y +++ b/sbin/ipsecctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.53 2006/03/22 16:01:23 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.54 2006/03/30 12:44:20 markus Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -132,8 +132,9 @@ struct ipsec_rule *create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *, struct ipsec_rule *reverse_sa(struct ipsec_rule *, u_int32_t, struct ipsec_key *, struct ipsec_key *); struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr_wrap *, struct - ipsec_addr_wrap *, struct ipsec_addr_wrap *, - u_int8_t, char *, char *, u_int8_t); + ipsec_addr_wrap *, struct ipsec_addr_wrap *, struct + ipsec_addr_wrap *, u_int8_t, char *, char *, + u_int8_t); struct ipsec_rule *reverse_rule(struct ipsec_rule *); struct ipsec_rule *create_ike(struct ipsec_addr_wrap *, struct ipsec_addr_wrap *, struct ipsec_addr_wrap *, @@ -155,6 +156,7 @@ typedef struct { struct ipsec_addr_wrap *src; struct ipsec_addr_wrap *dst; } hosts; + struct ipsec_addr_wrap *local; struct ipsec_addr_wrap *peer; struct ipsec_addr_wrap *host; struct { @@ -192,7 +194,7 @@ typedef struct { %token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI %token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE %token ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC -%token TYPE DENY BYPASS +%token TYPE DENY BYPASS LOCAL %token <v.string> STRING %type <v.string> string %type <v.dir> dir @@ -200,6 +202,7 @@ typedef struct { %type <v.tmode> tmode %type <v.number> number %type <v.hosts> hosts +%type <v.local> local %type <v.peer> peer %type <v.host> host %type <v.ids> ids @@ -297,11 +300,11 @@ sarule : protocol tmode hosts spispec transforms authkeyspec } ; -flowrule : FLOW protocol dir hosts peer ids type { +flowrule : FLOW protocol dir hosts local peer ids type { struct ipsec_rule *r; - r = create_flow($3, $4.src, $4.dst, $5, $2, $6.srcid, - $6.dstid, $7); + r = create_flow($3, $4.src, $4.dst, $5, $6, $2, + $7.srcid, $7.dstid, $8); if (r == NULL) YYERROR; r->nr = ipsec->rule_nr++; @@ -310,7 +313,7 @@ flowrule : FLOW protocol dir hosts peer ids type { errx(1, "flowrule: ipsecctl_add_rule"); /* Create and add reverse flow rule. */ - if ($7 == TYPE_UNKNOWN && $3 == IPSEC_INOUT) { + if ($8 == TYPE_UNKNOWN && $3 == IPSEC_INOUT) { r = reverse_rule(r); r->nr = ipsec->rule_nr++; @@ -372,6 +375,17 @@ peer : /* empty */ { $$ = NULL; } } ; +local : /* empty */ { $$ = NULL; } + | LOCAL STRING { + if (($$ = host($2)) == NULL) { + free($2); + yyerror("could not parse host specification"); + YYERROR; + } + free($2); + } + ; + host : STRING { if (($$ = host($1)) == NULL) { free($1); @@ -684,6 +698,7 @@ lookup(char *s) { "in", IN }, { "ipcomp", IPCOMP }, { "ipip", IPIP }, + { "local", LOCAL }, { "main", MAIN }, { "out", OUT }, { "passive", PASSIVE }, @@ -1506,8 +1521,8 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey, struct ipsec_rule * create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap - *dst, struct ipsec_addr_wrap *peer, u_int8_t proto, char *srcid, char - *dstid, u_int8_t type) + *dst, struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer, + u_int8_t proto, char *srcid, char *dstid, u_int8_t type) { struct ipsec_rule *r; @@ -1536,6 +1551,7 @@ create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap else r->flowtype = TYPE_REQUIRE; + r->local = local; if (peer == NULL) { /* Set peer to remote host. Must be a host address. */ if (r->direction == IPSEC_IN) { @@ -1596,6 +1612,8 @@ reverse_rule(struct ipsec_rule *rule) reverse->src = copyhost(rule->dst); reverse->dst = copyhost(rule->src); + if (rule->local) + reverse->local = copyhost(rule->local); reverse->peer = copyhost(rule->peer); reverse->proto = (u_int8_t)rule->proto; diff --git a/sbin/ipsecctl/pfkey.c b/sbin/ipsecctl/pfkey.c index 1e3e3c91104..c4d169e12dd 100644 --- a/sbin/ipsecctl/pfkey.c +++ b/sbin/ipsecctl/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.33 2006/03/07 00:30:28 reyk Exp $ */ +/* $OpenBSD: pfkey.c,v 1.34 2006/03/30 12:44:20 markus Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org> @@ -43,7 +43,8 @@ static u_int32_t sadb_msg_seq = 1; static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t, struct ipsec_addr_wrap *, struct ipsec_addr_wrap *, - struct ipsec_addr_wrap *, struct ipsec_auth *, u_int8_t); + struct ipsec_addr_wrap *, struct ipsec_addr_wrap *, + struct ipsec_auth *, u_int8_t); static int pfkey_sa(int, u_int8_t, u_int8_t, u_int32_t, struct ipsec_addr_wrap *, struct ipsec_addr_wrap *, struct ipsec_transforms *, struct ipsec_key *, @@ -57,13 +58,15 @@ int pfkey_init(void); static int pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst, - struct ipsec_addr_wrap *peer, struct ipsec_auth *auth, u_int8_t flowtype) + struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer, + struct ipsec_auth *auth, u_int8_t flowtype) { struct sadb_msg smsg; - struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask; + struct sadb_address sa_src, sa_dst, sa_local, sa_peer, sa_smask, + sa_dmask; struct sadb_protocol sa_flowtype, sa_protocol; struct sadb_ident *sa_srcid, *sa_dstid; - struct sockaddr_storage ssrc, sdst, speer, smask, dmask; + struct sockaddr_storage ssrc, sdst, slocal, speer, smask, dmask; struct iovec iov[IOV_CNT]; ssize_t n; int iov_cnt, len, ret = 0; @@ -104,6 +107,22 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction, dmask.ss_family = sdst.ss_family; dmask.ss_len = sdst.ss_len; + bzero(&slocal, sizeof(slocal)); + if (local) { + switch (local->af) { + case AF_INET: + ((struct sockaddr_in *)&slocal)->sin_addr = + local->address.v4; + slocal.ss_len = sizeof(struct sockaddr_in); + slocal.ss_family = AF_INET; + break; + case AF_INET6: + default: + warnx("unsupported address family %d", local->af); + return -1; + } + } + bzero(&speer, sizeof(speer)); if (peer) { switch (peer->af) { @@ -116,7 +135,7 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction, case AF_INET6: default: warnx("unsupported address family %d", peer->af); - return -1; + return -1; } } @@ -175,10 +194,18 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction, sa_dmask.sadb_address_len = (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8; - bzero(&sa_peer, sizeof(sa_peer)); - sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - sa_peer.sadb_address_len = - (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8; + if (local) { + bzero(&sa_local, sizeof(sa_local)); + sa_local.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + sa_local.sadb_address_len = + (sizeof(sa_local) + ROUNDUP(slocal.ss_len)) / 8; + } + if (peer) { + bzero(&sa_peer, sizeof(sa_peer)); + sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + sa_peer.sadb_address_len = + (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8; + } if (auth && auth->srcid) { len = ROUNDUP(strlen(auth->srcid) + 1) + sizeof(*sa_srcid); @@ -222,6 +249,17 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction, smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len; iov_cnt++; + /* local ip */ + if (local) { + iov[iov_cnt].iov_base = &sa_local; + iov[iov_cnt].iov_len = sizeof(sa_local); + iov_cnt++; + iov[iov_cnt].iov_base = &slocal; + iov[iov_cnt].iov_len = ROUNDUP(slocal.ss_len); + smsg.sadb_msg_len += sa_local.sadb_address_len; + iov_cnt++; + } + /* remote peer */ if (peer) { iov[iov_cnt].iov_base = &sa_peer; @@ -599,7 +637,6 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule) ext->sadb_ext_len * PFKEYV2_CHUNK)) { switch (ext->sadb_ext_type) { case SADB_EXT_ADDRESS_SRC: -#ifdef notyet saddr = (struct sadb_address *)ext; sa = (struct sockaddr *)(saddr + 1); @@ -618,7 +655,6 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule) default: return (1); } -#endif break; @@ -865,12 +901,12 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r) switch (action) { case ACTION_ADD: ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW, direction, - r->src, r->dst, r->peer, r->auth, r->flowtype); + r->src, r->dst, r->local, r->peer, r->auth, r->flowtype); break; case ACTION_DELETE: /* No peer for flow deletion. */ ret = pfkey_flow(fd, satype, SADB_X_DELFLOW, direction, - r->src, r->dst, NULL, NULL, r->flowtype); + r->src, r->dst, NULL, NULL, NULL, r->flowtype); break; default: return -1; |