diff options
-rw-r--r-- | sbin/ipsecadm/ipsecadm.8 | 25 | ||||
-rw-r--r-- | sbin/ipsecadm/ipsecadm.c | 230 |
2 files changed, 228 insertions, 27 deletions
diff --git a/sbin/ipsecadm/ipsecadm.8 b/sbin/ipsecadm/ipsecadm.8 index a2a065e6994..482045d811f 100644 --- a/sbin/ipsecadm/ipsecadm.8 +++ b/sbin/ipsecadm/ipsecadm.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ipsecadm.8,v 1.27 2000/09/19 03:18:11 angelos Exp $ +.\" $OpenBSD: ipsecadm.8,v 1.28 2000/09/19 08:38:40 angelos Exp $ .\" .\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> .\" All rights reserved. @@ -127,6 +127,16 @@ Allowed modifiers are: .Fl key , and .Fl keyfile . +.It group +Group two SAs together. +Allowed modifiers are: +.Fl dst , +.Fl spi , +.Fl proto , +.Fl dst2 , +.Fl spi2 , +and +.Fl proto2 . .It ip4 Setup an SA which uses the IP-in-IP encapsulation protocol. This mode @@ -268,6 +278,9 @@ For outgoing SAs, this field is used to fill in the source address when doing tunneling. .It Fl dst The destination IP address for the SA. +.It Fl dst2 +The second IP address used by +.Nm group . .It Fl proxy This IP address, if provided, is checked against the inner IP address when doing tunneling to a firewall, to prevent source spoofing attacks. @@ -281,6 +294,9 @@ the incoming SA should be C. This option is not necessary for outgoing SAs. .It Fl spi The Security Parameter Index (SPI). +.It Fl spi2 +The second SPI used by +.Nm group . .It Fl tunnel This option has been deprecated. The arguments are ignored, and it otherwise has the same effect as the @@ -410,6 +426,13 @@ and 4 .Nm ( IPPROTO_IP ) . One can also specify the symbolic names "esp", "ah", and "ip4", case insensitive. +.It Fl proto2 +The second security protocol used by +.Nm group . +It defaults to +.Nm IPPROTO_AH , +otherwise takes the same values as +.Fl proto . .It Fl addr The source address, source network mask, destination address and destination network mask against which packets need to match to use the specified diff --git a/sbin/ipsecadm/ipsecadm.c b/sbin/ipsecadm/ipsecadm.c index 6d3082375a0..7c428a1da1f 100644 --- a/sbin/ipsecadm/ipsecadm.c +++ b/sbin/ipsecadm/ipsecadm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecadm.c,v 1.39 2000/09/19 03:18:11 angelos Exp $ */ +/* $OpenBSD: ipsecadm.c,v 1.40 2000/09/19 08:38:41 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -73,6 +73,7 @@ #define XF_ENC 0x10 #define XF_AUTH 0x20 #define DEL_SPI 0x30 +#define GRP_SPI 0x40 #define FLOW 0x50 #define FLUSH 0x70 #define ENC_IP 0x80 @@ -107,7 +108,7 @@ xf_set(struct iovec *iov, int cnt, int len) { struct sadb_msg sm; int sd; - + sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); if (sd < 0) { @@ -212,6 +213,7 @@ usage() "\t -in\t\t\t\tspecify incoming-packet policy\n" "\t -out\t\t\t\tspecify outgoing-packet policy\n" "\t -[ah|esp|ip4]\t\t\tflush a particular protocol\n" + "\talso: dst2, spi2, proto2\n" ); } @@ -219,9 +221,9 @@ int main(int argc, char **argv) { int auth = 0, enc = 0, klen = 0, alen = 0, mode = ESP_NEW, i = 0; - int proto = IPPROTO_ESP, proto2 = IPPROTO_AH; + int proto = IPPROTO_ESP, proto2 = IPPROTO_AH, sproto2 = SADB_SATYPE_AH; int dport = -1, sport = -1, tproto = -1; - u_int32_t spi = SPI_LOCAL_USE; + u_int32_t spi = SPI_LOCAL_USE, spi2 = SPI_LOCAL_USE; union sockaddr_union *src, *dst, *dst2, *osrc, *odst, *osmask; union sockaddr_union *odmask, *proxy; u_char srcbuf[256], dstbuf[256], dst2buf[256], osrcbuf[256]; @@ -232,7 +234,7 @@ main(int argc, char **argv) struct servent *svp; char *transportproto = NULL; struct sadb_msg smsg; - struct sadb_sa sa; + struct sadb_sa sa, sa2; struct sadb_address sad1; /* src */ struct sadb_address sad2; /* dst */ struct sadb_address sad3; /* proxy */ @@ -261,6 +263,7 @@ main(int argc, char **argv) /* Zero out */ bzero(&smsg, sizeof(smsg)); bzero(&sa, sizeof(sa)); + bzero(&sa2, sizeof(sa2)); bzero(&skey1, sizeof(skey1)); bzero(&skey2, sizeof(skey2)); bzero(&sad1, sizeof(sad1)); @@ -307,10 +310,18 @@ main(int argc, char **argv) sa.sadb_sa_replay = 0; sa.sadb_sa_state = SADB_SASTATE_MATURE; + sa2.sadb_sa_exttype = SADB_X_EXT_SA2; + sa2.sadb_sa_len = sizeof(sa) / 8; + sa2.sadb_sa_replay = 0; + sa2.sadb_sa_state = SADB_SASTATE_MATURE; + sprotocol2.sadb_protocol_len = 1; sprotocol2.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE; sprotocol2.sadb_protocol_direction = IPSP_DIRECTION_OUT; + sprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; + sprotocol.sadb_protocol_len = 1; + if (!strcmp(argv[1], "new") && argc > 3) { if (!strcmp(argv[2], "esp")) @@ -372,37 +383,45 @@ main(int argc, char **argv) i++; } else - if (!strcmp(argv[1], "flow")) + if (!strcmp(argv[1], "group")) { - /* It may not be ADDFLOW, but never mind that for now */ - smsg.sadb_msg_type = SADB_X_ADDFLOW; + smsg.sadb_msg_type = SADB_X_GRPSPIS; smsg.sadb_msg_satype = SADB_SATYPE_ESP; - mode = FLOW; + mode = GRP_SPI; i++; } else - if (!strcmp(argv[1], "flush")) + if (!strcmp(argv[1], "flow")) { - mode = FLUSH; - smsg.sadb_msg_type = SADB_FLUSH; - smsg.sadb_msg_satype = SADB_SATYPE_UNSPEC; + /* It may not be ADDFLOW, but never mind that for now */ + smsg.sadb_msg_type = SADB_X_ADDFLOW; + smsg.sadb_msg_satype = SADB_SATYPE_ESP; + mode = FLOW; i++; } - else - if (!strcmp(argv[1], "ip4")) + else + if (!strcmp(argv[1], "flush")) { - mode = ENC_IP; - smsg.sadb_msg_type = SADB_ADD; - smsg.sadb_msg_satype = SADB_X_SATYPE_IPIP; + mode = FLUSH; + smsg.sadb_msg_type = SADB_FLUSH; + smsg.sadb_msg_satype = SADB_SATYPE_UNSPEC; i++; } - else - { - fprintf(stderr, "%s: unknown command: %s\n", argv[0], - argv[1]); - usage(); - exit(1); - } + else + if (!strcmp(argv[1], "ip4")) + { + mode = ENC_IP; + smsg.sadb_msg_type = SADB_ADD; + smsg.sadb_msg_satype = SADB_X_SATYPE_IPIP; + i++; + } + else + { + fprintf(stderr, "%s: unknown command: %s\n", argv[0], + argv[1]); + usage(); + exit(1); + } for (i++; i < argc; i++) { @@ -636,6 +655,60 @@ main(int argc, char **argv) continue; } + if (!strcmp(argv[i] + 1, "spi2") && spi2 == SPI_LOCAL_USE && + iscmd(mode, GRP_SPI) && (i + 1 < argc)) + { + spi2 = htonl(strtoul(argv[i + 1], NULL, 16)); + if (spi2 == SPI_LOCAL_USE || + (spi2 >= SPI_RESERVED_MIN && spi2 <= SPI_RESERVED_MAX)) + { + fprintf(stderr, "%s: invalid spi2 %s\n", argv[0], argv[i + 1]); + exit(1); + } + + sa2.sadb_sa_spi = spi2; + i++; + continue; + } + + + if (!strcmp(argv[i] + 1, "dst2") && + iscmd(mode, GRP_SPI) && (i + 1 < argc)) + { + sad8.sadb_address_exttype = SADB_X_EXT_DST2; +#ifdef INET6 + if (strchr(argv[i + 1], ':')) + { + sad8.sadb_address_len = (sizeof(sad8) + + ROUNDUP(sizeof(struct sockaddr_in6))) + / 8; + dst2->sin6.sin6_family = AF_INET6; + dst2->sin6.sin6_len = sizeof(struct sockaddr_in6); + dst2set = inet_pton(AF_INET6, argv[i + 1], + &dst2->sin6.sin6_addr) != -1 ? 1 : 0; + } + else +#endif /* INET6 */ + { + sad8.sadb_address_len = (sizeof(sad8) + + sizeof(struct sockaddr_in)) / 8; + dst2->sin.sin_family = AF_INET; + dst2->sin.sin_len = sizeof(struct sockaddr_in); + dst2set = inet_pton(AF_INET, argv[i + 1], + &dst2->sin.sin_addr) != -1 ? 1 : 0; + } + + if (dst2set == 0) + { + fprintf(stderr, + "%s: Warning: destination address2 %s is not valid\n", + argv[0], argv[i + 1]); + exit(1); + } + i++; + continue; + } + if (!strcmp(argv[i] + 1, "src") && (i + 1 < argc)) { sad1.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; @@ -1060,8 +1133,66 @@ main(int argc, char **argv) continue; } + if (!strcmp(argv[i] + 1, "proto2") && + iscmd(mode, GRP_SPI) && (i + 1 < argc)) + { + if (isalpha(argv[i + 1][0])) + { + if (!strcasecmp(argv[i + 1], "esp")) + { + sprotocol.sadb_protocol_proto = sproto2 = SADB_SATYPE_ESP; + proto2 = IPPROTO_ESP; + } + else + if (!strcasecmp(argv[i + 1], "ah")) + { + sprotocol.sadb_protocol_proto = sproto2 = SADB_SATYPE_AH; + proto2 = IPPROTO_AH; + } + else + if (!strcasecmp(argv[i + 1], "ip4")) + { + sprotocol.sadb_protocol_proto = sproto2 = SADB_X_SATYPE_IPIP; + proto2 = IPPROTO_IPIP; + } + else + { + fprintf(stderr, + "%s: unknown security protocol2 type %s\n", + argv[0], argv[i+1]); + exit(1); + } + } + else + { + proto2 = atoi(argv[i + 1]); + + if (proto2 != IPPROTO_ESP && proto2 != IPPROTO_AH && + proto2 != IPPROTO_IPIP) + { + fprintf(stderr, + "%s: unknown security protocol2 %d\n", + argv[0], proto2); + exit(1); + } + + if (proto2 == IPPROTO_ESP) + sprotocol.sadb_protocol_proto = sproto2 = SADB_SATYPE_ESP; + else + if (proto2 == IPPROTO_AH) + sprotocol.sadb_protocol_proto = sproto2 = SADB_SATYPE_AH; + else + if (proto2 == IPPROTO_IPIP) + sprotocol.sadb_protocol_proto = sproto2 = SADB_X_SATYPE_IPIP; + } + + i++; + continue; + } + if (!strcmp(argv[i] + 1, "proto") && (i + 1 < argc) && - ((iscmd(mode, FLOW) && !bypass && !deny) || iscmd(mode, DEL_SPI))) + ((iscmd(mode, FLOW) && !bypass && !deny) || iscmd(mode, DEL_SPI) || + iscmd(mode, GRP_SPI))) { if (isalpha(argv[i + 1][0])) { @@ -1130,6 +1261,12 @@ main(int argc, char **argv) exit(1); } + if (iscmd(mode, GRP_SPI) && spi2 == SPI_LOCAL_USE) + { + fprintf(stderr, "%s: no SPI2 specified\n", argv[0]); + exit(1); + } + if ((mode & (AH_NEW | AH_OLD)) && auth == 0) { fprintf(stderr, "%s: no authentication algorithm specified\n", @@ -1178,6 +1315,12 @@ main(int argc, char **argv) fprintf(stderr, "%s: no transport protocol supplied with source/destination ports\n", argv[0]); exit(1); } + + if (iscmd(mode, GRP_SPI) && !dst2set) + { + fprintf(stderr, "%s: no destination address2 specified\n", argv[0]); + exit(1); + } if ((klen > 2 * 8100) || (alen > 2 * 8100)) { @@ -1270,6 +1413,41 @@ main(int argc, char **argv) { switch(mode & CMD_MASK) { + case GRP_SPI: + /* SA header */ + iov[cnt].iov_base = &sa; + iov[cnt++].iov_len = sizeof(sa); + smsg.sadb_msg_len += sa.sadb_sa_len; + + /* Destination address header */ + iov[cnt].iov_base = &sad2; + iov[cnt++].iov_len = sizeof(sad2); + /* Destination address */ + iov[cnt].iov_base = dst; + iov[cnt++].iov_len = ROUNDUP(dst->sa.sa_len); + smsg.sadb_msg_len += sad2.sadb_address_len; + + /* SA header */ + iov[cnt].iov_base = &sa2; + iov[cnt++].iov_len = sizeof(sa2); + smsg.sadb_msg_len += sa2.sadb_sa_len; + + /* Destination2 address header */ + iov[cnt].iov_base = &sad8; + iov[cnt++].iov_len = sizeof(sad8); + /* Destination2 address */ + iov[cnt].iov_base = dst2; + iov[cnt++].iov_len = ROUNDUP(dst2->sa.sa_len); + smsg.sadb_msg_len += sad8.sadb_address_len; + + sprotocol.sadb_protocol_proto = sproto2; + + /* Protocol2 */ + iov[cnt].iov_base = &sprotocol; + iov[cnt++].iov_len = sizeof(sprotocol); + smsg.sadb_msg_len += sprotocol.sadb_protocol_len; + break; + case DEL_SPI: /* SA header */ iov[cnt].iov_base = &sa; |