diff options
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ping/Makefile | 5 | ||||
-rw-r--r-- | sbin/ping/ping.8 | 8 | ||||
-rw-r--r-- | sbin/ping/ping.c | 71 | ||||
-rw-r--r-- | sbin/setkey/Makefile | 56 | ||||
-rw-r--r-- | sbin/setkey/parse.y | 787 | ||||
-rw-r--r-- | sbin/setkey/sample.cf | 219 | ||||
-rw-r--r-- | sbin/setkey/scriptdump.pl | 54 | ||||
-rw-r--r-- | sbin/setkey/setkey.8 | 550 | ||||
-rw-r--r-- | sbin/setkey/setkey.c | 566 | ||||
-rw-r--r-- | sbin/setkey/test-pfkey.c | 480 | ||||
-rw-r--r-- | sbin/setkey/test-policy.c | 161 | ||||
-rw-r--r-- | sbin/setkey/token.l | 322 | ||||
-rw-r--r-- | sbin/setkey/vchar.h | 35 |
13 files changed, 3309 insertions, 5 deletions
diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile index 1df0d93..2c6b08e 100644 --- a/sbin/ping/Makefile +++ b/sbin/ping/Makefile @@ -8,7 +8,8 @@ COPTS+= -Wall -Wmissing-prototypes .if ${MACHINE_ARCH} == "alpha" COPTS+= -fno-builtin # GCC's builtin memcpy doesn't do unaligned copies .endif -DPADD= ${LIBM} -LDADD= -lm +CFLAGS+=-DIPSEC +DPADD= ${LIBM} ${LIBIPSEC} +LDADD= -lm -lipsec .include <bsd.prog.mk> diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8 index 565a5af..fca80ac 100644 --- a/sbin/ping/ping.8 +++ b/sbin/ping/ping.8 @@ -47,6 +47,7 @@ packets to network hosts .Op Fl i Ar wait .Op Fl l Ar preload .Op Fl p Ar pattern +.Op Fl P Ar policy .Op Fl s Ar packetsize .Op Fl S Ar src_addr .Bo @@ -147,6 +148,13 @@ For example, .Dq Li \-p ff will cause the sent packet to be filled with all ones. +.It Fl P Ar policy +.Ar policy +specifies IPsec policy for the ping session. +For details please refer to +.Xr ipsec 4 +and +.Xr ipsec_set_policy 3 . .It Fl Q Somewhat quiet output. .No Don Ap t diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index 1cd55fa..15bac46 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -92,6 +92,10 @@ static const char rcsid[] = #include <netinet/ip_var.h> #include <arpa/inet.h> +#ifdef IPSEC +#include <netinet6/ipsec.h> +#endif /*IPSEC*/ + #define PHDR_LEN sizeof(struct timeval) #define DEFDATALEN (64 - PHDR_LEN) /* default data length */ #define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */ @@ -124,6 +128,11 @@ int options; #define F_MTTL 0x0800 #define F_MIF 0x1000 #define F_AUDIBLE 0x2000 +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +#define F_POLICY 0x4000 +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ /* * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum @@ -204,6 +213,10 @@ main(argc, argv) struct msghdr msg; struct sockaddr_in from; char ctrl[sizeof(struct cmsghdr) + sizeof(struct timeval)]; +#ifdef IPSEC_POLICY_IPSEC + char *policy_in = NULL; + char *policy_out = NULL; +#endif /* * Do the stuff that we need root priv's for *first*, and @@ -219,7 +232,14 @@ main(argc, argv) preload = 0; datap = &outpack[8 + PHDR_LEN]; - while ((ch = getopt(argc, argv, "I:LQRS:T:c:adfi:l:np:qrs:v")) != -1) { +#ifndef IPSEC + while ((ch = getopt(argc, argv, "I:LQRT:c:adfi:l:np:qrs:v")) != -1) +#else +#ifdef IPSEC_POLICY_IPSEC + while ((ch = getopt(argc, argv, "I:LQRT:c:adfi:l:np:qrs:vP:")) != -1) +#endif /*IPSEC_POLICY_IPSEC*/ +#endif + { switch(ch) { case 'a': options |= F_AUDIBLE; @@ -331,6 +351,19 @@ main(argc, argv) case 'v': options |= F_VERBOSE; break; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + case 'P': + options |= F_POLICY; + if (!strncmp("in", optarg, 2)) + policy_in = strdup(optarg); + else if (!strncmp("out", optarg, 3)) + policy_out = strdup(optarg); + else + errx(1, "invalid security policy"); + break; +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ default: usage(); } @@ -419,6 +452,32 @@ main(argc, argv) if (options & F_SO_DONTROUTE) (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + if (options & F_POLICY) { + char *buf; + if (policy_in != NULL) { + buf = ipsec_set_policy(policy_in, strlen(policy_in)); + if (buf == NULL) + errx(EX_CONFIG, ipsec_strerror()); + if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(EX_CONFIG, "ipsec policy cannot be configured"); + free(buf); + } + + if (policy_out != NULL) { + buf = ipsec_set_policy(policy_out, strlen(policy_out)); + if (buf == NULL) + errx(EX_CONFIG, ipsec_strerror()); + if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) + err(EX_CONFIG, "ipsec policy cannot be configured"); + free(buf); + } + } +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ /* record route option */ if (options & F_RROUTE) { @@ -1326,7 +1385,13 @@ usage() { fprintf(stderr, "%s\n%s\n%s\n", "usage: ping [-QRadfnqrv] [-c count] [-i wait] [-l preload] [-p pattern]", -" [-s packetsize] [-S src_addr]", -" [host | [-L] [-I iface] [-T ttl] mcast-group]"); +" " +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +"[-P policy] " +#endif +#endif +"[-s packetsize] [-S src_addr]", + "[host | [-L] [-I iface] [-T ttl] mcast-group]"); exit(EX_USAGE); } diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile new file mode 100644 index 0000000..918dbf4 --- /dev/null +++ b/sbin/setkey/Makefile @@ -0,0 +1,56 @@ +# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# $FreeBSD$ + +PROG= setkey +SRCS= setkey.c parse.y token.l +CFLAGS+=-g +LDADD+= -ll -ly +CLEANFILES+= y.tab.c y.tab.h key_test.o keytest +YFLAGS+=-d + +SCRIPTS= scriptdump + +BINOWN = root +BINGRP = bin +BINMODE = 555 + +all: ${PROG} scriptdump + +SRCS+=y.tab.h +y.tab.h: parse.y +CFLAGS+=-DIPSEC_DEBUG -DINET6 -DYY_NO_UNPUT -I${.OBJDIR} +LDADD+= -lipsec +CLEANFILES+= scriptdump y.tab.h + +MAN8= setkey.8 +LOCALPREFIX= /usr/local + +scriptdump: scriptdump.pl + sed -e 's#@LOCALPREFIX@#${LOCALPREFIX}#' < $> > scriptdump + +.include <bsd.prog.mk> diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y new file mode 100644 index 0000000..761c34d --- /dev/null +++ b/sbin/setkey/parse.y @@ -0,0 +1,787 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* KAME $Id: parse.y,v 1.7 1999/10/27 17:08:57 sakane Exp $ */ + +%{ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/route.h> +#include <netinet/in.h> +#include <net/pfkeyv2.h> +#include <netkey/key_var.h> +#include <netinet6/ipsec.h> +#include <arpa/inet.h> + +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> + +#include "vchar.h" + +#define ATOX(c) \ + (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) + +u_int p_type; +u_int32_t p_spi; +struct sockaddr *p_src, *p_dst; +u_int p_prefs, p_prefd, p_upper; +u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode; +u_int p_key_enc_len, p_key_auth_len; +caddr_t p_key_enc, p_key_auth; +time_t p_lt_hard, p_lt_soft; + +u_int p_policy_len; +char *p_policy; + +/* temporary buffer */ +static struct sockaddr *pp_addr; +static u_int pp_prefix; +static u_int pp_port; +static caddr_t pp_key; + +extern u_char m_buf[BUFSIZ]; +extern int m_len; +extern char cmdarg[8192]; +extern int f_debug; + +int setkeymsg __P((void)); +static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int)); +void parse_init __P((void)); +void free_buffer __P((void)); + +extern int setkeymsg __P((void)); +extern int sendkeymsg __P((void)); + +extern int yylex __P((void)); +extern void yyerror __P((char *)); +%} + +%union { + unsigned long num; + vchar_t val; +} + +%token EOT +%token ADD GET DELETE FLUSH DUMP +%token IP4_ADDRESS IP6_ADDRESS PREFIX PORT PORTANY +%token UP_PROTO PR_ESP PR_AH PR_IPCOMP +%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI +%token F_MODE MODE +%token F_EXT EXTENSION +%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP +%token F_LIFETIME_HARD F_LIFETIME_SOFT +%token DECSTRING QUOTEDSTRING HEXSTRING ANY + /* SPD management */ +%token SPDADD SPDDELETE SPDDUMP SPDFLUSH +%token F_POLICY PL_REQUESTS + +%% +commands + : /*NOTHING*/ + | commands command + { + if (f_debug) { + printf("cmdarg:\n%s\n", cmdarg); + } else { + setkeymsg(); + sendkeymsg(); + } + free_buffer(); + parse_init(); + } + ; + +command + : add_command + | get_command + | delete_command + | flush_command + | dump_command + | spdadd_command + | spddelete_command + | spddump_command + | spdflush_command + ; + /* commands concerned with management, there is in tail of this file. */ + + /* add command */ +add_command + : ADD { p_type = SADB_ADD; } + sa_selector_spec extension_spec algorithm_spec EOT + ; + + /* delete */ +delete_command + : DELETE { p_type = SADB_DELETE; } + sa_selector_spec extension_spec EOT + ; + + /* get command */ +get_command + : GET { p_type = SADB_GET; } + sa_selector_spec extension_spec EOT + ; + + /* flush */ +flush_command + : FLUSH { p_type = SADB_FLUSH; } + protocol_spec EOT + ; + + /* dump */ +dump_command + : DUMP { p_type = SADB_DUMP; } + protocol_spec EOT + ; + + /* sa_selector_spec */ +sa_selector_spec + : ipaddress { p_src = pp_addr; } + ipaddress { p_dst = pp_addr; } + protocol_spec spi + ; + +protocol_spec + : /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; } + | PR_ESP + { + p_satype = SADB_SATYPE_ESP; + if ($1.num == 1) + p_ext |= SADB_X_EXT_OLD; + else + p_ext &= ~SADB_X_EXT_OLD; + } + | PR_AH + { + p_satype = SADB_SATYPE_AH; + if ($1.num == 1) + p_ext |= SADB_X_EXT_OLD; + else + p_ext &= ~SADB_X_EXT_OLD; + } + | PR_IPCOMP + { + p_satype = SADB_X_SATYPE_IPCOMP; + } + ; + +spi + : DECSTRING { p_spi = $1.num; } + | HEXSTRING + { + caddr_t bp; + caddr_t yp = $1.val.buf; + char buf0[4], buf[4]; + int i, j; + + /* sanity check */ + if ($1.val.len > 4) { + yyerror("SPI too big."); + free($1.val.buf); + return -1; + } + + bp = buf0; + while (*yp) { + *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); + yp += 2, bp++; + } + + /* initialize */ + for (i = 0; i < 4; i++) buf[i] = 0; + + for (j = $1.val.len - 1, i = 3; j >= 0; j--, i--) + buf[i] = buf0[j]; + + /* XXX: endian */ + p_spi = ntohl(*(u_int32_t *)buf); + + free($1.val.buf); + } + ; + +algorithm_spec + : esp_spec + | ah_spec + | ipcomp_spec + ; + +esp_spec + : F_ENC enc_alg enc_key F_AUTH auth_alg auth_key + | F_ENC enc_alg enc_key + ; + +ah_spec + : F_AUTH auth_alg auth_key + ; + +ipcomp_spec + : F_COMP ALG_COMP { p_alg_enc = $2.num; } + | F_COMP ALG_COMP { p_alg_enc = $2.num; } + F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; } + ; + +enc_alg + : ALG_ENC { p_alg_enc = $1.num; } + | ALG_ENC_DESDERIV + { + p_alg_enc = $1.num; + if (p_ext & SADB_X_EXT_OLD) { + yyerror("algorithm mismatched."); + return -1; + } + p_ext |= SADB_X_EXT_DERIV; + } + | ALG_ENC_DES32IV + { + p_alg_enc = $1.num; + if (!(p_ext & SADB_X_EXT_OLD)) { + yyerror("algorithm mismatched."); + return -1; + } + p_ext |= SADB_X_EXT_IV4B; + } + ; + +enc_key + : /*NOTHING*/ + { + if (p_alg_enc != SADB_EALG_NULL) { + yyerror("no key found."); + return -1; + } + } + | key_string + { + p_key_enc_len = $1.val.len; + p_key_enc = pp_key; + + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, + PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + yyerror(ipsec_strerror()); + return -1; + } + } + ; + +auth_alg + : ALG_AUTH { p_alg_auth = $1.num; } + ; + +auth_key + : /*NOTHING*/ + { + if (p_alg_auth != SADB_AALG_NULL) { + yyerror("no key found."); + return -1; + } + } + | key_string + { + p_key_auth_len = $1.val.len; + p_key_auth = pp_key; + + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH, + p_alg_auth, + PFKEY_UNUNIT64(p_key_auth_len)) < 0) { + yyerror(ipsec_strerror()); + return -1; + } + } + ; + +key_string + : QUOTEDSTRING + { + pp_key = $1.val.buf; + /* free pp_key later */ + } + | HEXSTRING + { + caddr_t bp; + caddr_t yp = $1.val.buf; + + if ((pp_key = malloc($1.val.len)) == 0) { + free($1.val.buf); + yyerror(strerror(errno)); + return -1; + } + memset(pp_key, 0, $1.val.len); + + bp = pp_key; + while (*yp) { + *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); + yp += 2, bp++; + } + + free($1.val.buf); + } + ; + +extension_spec + : /*NOTHING*/ + | extension_spec extension + ; + +extension + : F_EXT EXTENSION { p_ext |= $1.num; } + | F_MODE MODE { p_mode = $2.num; } + | F_MODE ANY { p_mode = IPSEC_MODE_ANY; } + | F_REPLAY DECSTRING + { + if (p_ext & SADB_X_EXT_OLD) { + yyerror("replay prevention " + "only use on new spec."); + return -1; + } + p_replay = $2.num; + } + | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2.num; } + | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2.num; } + ; + + /* definition about command for SPD management */ + /* spdadd */ +spdadd_command + : SPDADD + { + p_type = SADB_X_SPDADD; + p_satype = SADB_SATYPE_UNSPEC; + } + sp_selector_spec policy_spec EOT + ; + +spddelete_command: + SPDDELETE + { + p_type = SADB_X_SPDDELETE; + p_satype = SADB_SATYPE_UNSPEC; + } + sp_selector_spec EOT + ; + +spddump_command: + SPDDUMP + { + p_type = SADB_X_SPDDUMP; + p_satype = SADB_SATYPE_UNSPEC; + } + EOT + ; + +spdflush_command: + SPDFLUSH + { + p_type = SADB_X_SPDFLUSH; + p_satype = SADB_SATYPE_UNSPEC; + } + EOT + ; + + /* sp_selector_spec */ +sp_selector_spec + : ipaddress { p_src = pp_addr; } + prefix { p_prefs = pp_prefix; } + port { _INPORTBYSA(p_src) = htons(pp_port); } + ipaddress { p_dst = pp_addr; } + prefix { p_prefd = pp_prefix; } + port { _INPORTBYSA(p_dst) = htons(pp_port); } + upper_spec + ; + +ipaddress + : IP4_ADDRESS + { + struct sockaddr_in *in; + u_int sa_len = $1.val.len; + + if ((in = (struct sockaddr_in *)malloc(sa_len)) == 0) { + yyerror(strerror(errno)); + free($1.val.buf); + return -1; + } + memset((caddr_t)in, 0, sa_len); + + in->sin_family = PF_INET; + in->sin_len = sa_len; + in->sin_port = IPSEC_PORT_ANY; + (void)inet_pton(PF_INET, $1.val.buf, &in->sin_addr); + + pp_addr = (struct sockaddr *)in; + free($1.val.buf); + } + | IP6_ADDRESS + { +#ifdef INET6 + struct sockaddr_in6 *in6; + u_int sa_len = $1.val.len; + struct addrinfo hints, *res; + int ret_gai; + + if ((in6 = (struct sockaddr_in6 *)malloc(sa_len)) == 0) { + free($1.val.buf); + yyerror(strerror(errno)); + return -1; + } + memset((caddr_t)in6, 0, sa_len); + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_INET6; + ret_gai = getaddrinfo($1.val.buf, NULL, &hints, &res); + if (ret_gai) { + free($1.val.buf); + free(in6); + yyerror(gai_strerror(ret_gai)); + if (ret_gai == EAI_SYSTEM) + yyerror(strerror(errno)); + return -1; + } + (void)memcpy(in6, res->ai_addr, res->ai_addrlen); + + /* + * XXX: If the scope of the destination is link-local, + * embed the scope-id(in this case, interface index) + * into the address. + */ + if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr) && + in6->sin6_scope_id != 0) + *(u_short *)&in6->sin6_addr.s6_addr[2] = + htons(in6->sin6_scope_id & 0xffff); + + freeaddrinfo(res); + + pp_addr = (struct sockaddr *)in6; +#else + yyerror("IPv6 address not supported"); +#endif + free($1.val.buf); + } + ; + +prefix + : /*NOTHING*/ { pp_prefix = ~0; } + | PREFIX { pp_prefix = $1.num; } + ; + +port + : /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; } + | PORT { pp_port = $1.num; } + | PORTANY { pp_port = IPSEC_PORT_ANY; } + ; + +upper_spec + : DECSTRING { p_upper = $1.num; } + | UP_PROTO { p_upper = $1.num; } + | PR_ESP { p_upper = IPPROTO_ESP; }; + | PR_AH { p_upper = IPPROTO_AH; }; + | PR_IPCOMP { p_upper = IPPROTO_IPCOMP; }; + | ANY { p_upper = IPSEC_ULPROTO_ANY; } + ; + +policy_spec + : F_POLICY policy_requests + { + p_policy = ipsec_set_policy($2.val.buf, $2.val.len); + if (p_policy == NULL) { + free($2.val.buf); + p_policy = NULL; + yyerror(ipsec_strerror()); + return -1; + } + + p_policy_len = ipsec_get_policylen(p_policy); + + free($2.val.buf); + } + ; + +policy_requests: + /*NOTHING*/ + | PL_REQUESTS { $$ = $1; } + ; + +%% + +int +setkeymsg() +{ + struct sadb_msg m_msg; + + m_msg.sadb_msg_version = PF_KEY_V2; + m_msg.sadb_msg_type = p_type; + m_msg.sadb_msg_errno = 0; + m_msg.sadb_msg_satype = p_satype; + m_msg.sadb_msg_mode = p_mode; + m_msg.sadb_msg_reserved = 0; + m_msg.sadb_msg_seq = 0; + m_msg.sadb_msg_pid = getpid(); + + m_len = sizeof(struct sadb_msg); + memcpy(m_buf, &m_msg, m_len); + + switch (p_type) { + case SADB_FLUSH: + case SADB_DUMP: + break; + + case SADB_ADD: + /* set encryption algorithm, if present. */ + if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) { + struct sadb_key m_key; + + m_key.sadb_key_len = + PFKEY_UNIT64(sizeof(m_key) + + PFKEY_ALIGN8(p_key_enc_len)); + m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; + m_key.sadb_key_bits = p_key_enc_len * 8; + m_key.sadb_key_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_key, sizeof(m_key), + (caddr_t)p_key_enc, p_key_enc_len); + } + + /* set authentication algorithm, if present. */ + if (p_alg_auth != SADB_AALG_NONE) { + struct sadb_key m_key; + + m_key.sadb_key_len = + PFKEY_UNIT64(sizeof(m_key) + + PFKEY_ALIGN8(p_key_auth_len)); + m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; + m_key.sadb_key_bits = p_key_auth_len * 8; + m_key.sadb_key_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_key, sizeof(m_key), + (caddr_t)p_key_auth, p_key_auth_len); + } + + /* set lifetime for HARD */ + if (p_lt_hard != 0) { + struct sadb_lifetime m_lt; + u_int len = sizeof(struct sadb_lifetime); + + m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); + m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; + m_lt.sadb_lifetime_allocations = 0; + m_lt.sadb_lifetime_bytes = 0; + m_lt.sadb_lifetime_addtime = p_lt_hard; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(m_buf + m_len, &m_lt, len); + m_len += len; + } + + /* set lifetime for SOFT */ + if (p_lt_soft != 0) { + struct sadb_lifetime m_lt; + u_int len = sizeof(struct sadb_lifetime); + + m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); + m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; + m_lt.sadb_lifetime_allocations = 0; + m_lt.sadb_lifetime_bytes = 0; + m_lt.sadb_lifetime_addtime = p_lt_soft; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(m_buf + m_len, &m_lt, len); + m_len += len; + } + /* FALLTHROUGH */ + + case SADB_DELETE: + case SADB_GET: + { + struct sadb_sa m_sa; + struct sadb_address m_addr; + u_int len; + + len = sizeof(struct sadb_sa); + m_sa.sadb_sa_len = PFKEY_UNIT64(len); + m_sa.sadb_sa_exttype = SADB_EXT_SA; + m_sa.sadb_sa_spi = htonl(p_spi); + m_sa.sadb_sa_replay = p_replay; + m_sa.sadb_sa_state = 0; + m_sa.sadb_sa_auth = p_alg_auth; + m_sa.sadb_sa_encrypt = p_alg_enc; + m_sa.sadb_sa_flags = p_ext; + + memcpy(m_buf + m_len, &m_sa, len); + m_len += len; + + /* set src */ + m_addr.sadb_address_len = + PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(p_src->sa_len)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = + _INALENBYAF(p_src->sa_family) << 3; + m_addr.sadb_address_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_addr, sizeof(m_addr), + (caddr_t)p_src, p_src->sa_len); + + /* set dst */ + m_addr.sadb_address_len = + PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(p_dst->sa_len)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = + _INALENBYAF(p_dst->sa_family) << 3; + m_addr.sadb_address_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_addr, sizeof(m_addr), + (caddr_t)p_dst, p_dst->sa_len); + } + break; + + /* for SPD management */ + case SADB_X_SPDFLUSH: + case SADB_X_SPDDUMP: + break; + + case SADB_X_SPDADD: + { + memcpy(m_buf + m_len, p_policy, p_policy_len); + m_len += p_policy_len; + free(p_policy); + p_policy = NULL; + } + /* FALLTHROUGH */ + + case SADB_X_SPDDELETE: + { + struct sadb_address m_addr; + + /* set src */ + m_addr.sadb_address_len = + PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(p_src->sa_len)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + m_addr.sadb_address_proto = p_upper; + m_addr.sadb_address_prefixlen = + (p_prefs != ~0 ? p_prefs : + _INALENBYAF(p_src->sa_family) << 3); + m_addr.sadb_address_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_addr, sizeof(m_addr), + (caddr_t)p_src, p_src->sa_len); + + /* set dst */ + m_addr.sadb_address_len = + PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(p_dst->sa_len)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + m_addr.sadb_address_proto = p_upper; + m_addr.sadb_address_prefixlen = + (p_prefd != ~0 ? p_prefd : + _INALENBYAF(p_dst->sa_family) << 3); + m_addr.sadb_address_reserved = 0; + + setvarbuf(&m_len, + (struct sadb_ext *)&m_addr, sizeof(m_addr), + (caddr_t)p_dst, p_dst->sa_len); + } + break; + } + + ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); + + return 0; +} + +static int +setvarbuf(off, ebuf, elen, vbuf, vlen) + caddr_t vbuf; + struct sadb_ext *ebuf; + int *off, elen, vlen; +{ + memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len)); + memcpy(m_buf + *off, (caddr_t)ebuf, elen); + memcpy(m_buf + *off + elen, vbuf, vlen); + (*off) += PFKEY_ALIGN8(elen + vlen); + + return 0; +} + +void +parse_init() +{ + p_type = 0; + p_spi = 0; + + p_src = 0, p_dst = 0; + pp_prefix = p_prefs = p_prefd = ~0; + pp_port = IPSEC_PORT_ANY; + p_upper = 0; + + p_satype = 0; + p_ext = SADB_X_EXT_NONE; + p_alg_enc = SADB_EALG_NONE; + p_alg_auth = SADB_AALG_NONE; + p_mode = IPSEC_MODE_ANY; + p_replay = 4; + p_key_enc_len = p_key_auth_len = 0; + p_key_enc = p_key_auth = 0; + p_lt_hard = p_lt_soft = 0; + + p_policy_len = 0; + p_policy = NULL; + + memset(cmdarg, 0, sizeof(cmdarg)); + + return; +} + +void +free_buffer() +{ + if (p_src) free(p_src); + if (p_dst) free(p_dst); + if (p_key_enc) free(p_key_enc); + if (p_key_auth) free(p_key_auth); + + return; +} + diff --git a/sbin/setkey/sample.cf b/sbin/setkey/sample.cf new file mode 100644 index 0000000..886c449 --- /dev/null +++ b/sbin/setkey/sample.cf @@ -0,0 +1,219 @@ +# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +# There are sample scripts for IPsec configuration by manual keying. +# A security association is uniquely identified by a triple consisting +# of a Security Parameter Index (SPI), an IP Destination Address, and a +# security protocol (AH or ESP) identifier. You must take care of these +# parameters when you configure by manual keying. + +# ESP transport mode is recommended for TCP port number 110 between +# Host-A and Host-B. Encryption algorithm is blowfish-cbc whose key +# is "kamekame", and authentication algorithm is hmac-sha1 whose key +# is "this is the test key". +# +# ============ ESP ============ +# | | +# Host-A Host-B +# fec0::10 -------------------- fec0::11 +# +# At Host-A and Host-B, +spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec + esp/transport/fec0::10-fec0::11/use ; +spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec + esp/transport/fec0::11-fec0::10/use ; +add fec0::10 fec0::11 esp 0x10001 + -m transport + -E blowfish-cbc "kamekame" + -A hmac-sha1 "this is the test key" ; +add fec0::11 fec0::10 esp 0x10002 + -m transport + -E blowfish-cbc "kamekame" + -A hmac-sha1 "this is the test key" ; + +# "[any]" is wildcard of port number. Note that "[0]" is the number of +# zero in port number. + +# Security protocol is old AH tunnel mode, i.e. RFC1826, with keyed-md5 +# whose key is "this is the test" as authentication algorithm. +# That protocol takes place between Gateway-A and Gateway-B. +# +# ======= AH ======= +# | | +# Network-A Gateway-A Gateway-B Network-B +# 10.0.1.0/24 ---- 172.16.0.1 ----- 172.16.0.2 ---- 10.0.2.0/24 +# +# At Gateway-A: +spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec + ah/tunnel/172.16.0.1-172.16.0.2/require ; +spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec + ah/tunnel/172.16.0.2-172.16.0.1/require ; +add 172.16.0.1 172.16.0.2 ah-old 0x10003 + -m any + -A keyed-md5 "this is the test" ; +add 172.16.0.2 172.16.0.1 ah-old 0x10004 + -m any + -A keyed-md5 "this is the test" ; + +# If port number field is omitted such above then "[any]" is employed. +# -m specifies the mode of SA to be used. "-m any" means wildcard of +# mode of security protocol. You can use this SAs for both tunnel and +# transport mode. + +# At Gateway-B. Attention to the selector and peer's IP address for tunnel. +spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec + ah/tunnel/172.16.0.2-172.16.0.1/require ; +spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec + ah/tunnel/172.16.0.1-172.16.0.2/require ; +add 172.16.0.1 172.16.0.2 ah-old 0x10003 + -m tunnel + -A keyed-md5 "this is the test" ; +add 172.16.0.2 172.16.0.1 ah-old 0x10004 + -m tunnel + -A keyed-md5 "this is the test" ; + +# AH transport mode followed by ESP tunnel mode is required between +# Gateway-A and Gateway-B. +# Encryption algorithm is 3des-cbc, and authentication algorithm for ESP +# is hmac-sha1. Authentication algorithm for AH is hmac-md5. +# +# ========== AH ========= +# | ======= ESP ===== | +# | | | | +# Network-A Gateway-A Gateway-B Network-B +# fec0:0:0:1::/64 --- fec0:0:0:1::1 ---- fec0:0:0:2::1 --- fec0:0:0:2::/64 +# +# At Gateway-A: +spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec + esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require + ah/transport/fec0:0:0:1::1-fec0:0:0:2::1/require ; +spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec + esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require + ah/transport/fec0:0:0:2::1-fec0:0:0:1::1/require ; +add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001 + -m tunnel + -E 3des-cbc "kamekame12341234kame1234" + -A hmac-sha1 "this is the test key" ; +add fec0:0:0:1::1 fec0:0:0:2::1 ah 0x10001 + -m transport + -A hmac-md5 "this is the test" ; +add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10001 + -m tunnel + -E 3des-cbc "kamekame12341234kame1234" + -A hmac-sha1 "this is the test key" ; +add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001 + -m transport + -A hmac-md5 "this is the test" ; + +# ESP tunnel mode is required between Host-A and Gateway-A. +# Encryption algorithm is cast128-cbc, and authentication algorithm +# for ESP is hmac-sha1. +# ESP transport mode is recommended between Host-A and Host-B. +# Encryption algorithm is rc5-cbc, and authentication algorithm +# for ESP is hmac-md5. +# +# ================== ESP ================= +# | ======= ESP ======= | +# | | | | +# Host-A Gateway-A Host-B +# fec0:0:0:1::1 ---- fec0:0:0:2::1 ---- fec0:0:0:2::2 +# +# At Host-A: +spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec + esp/transport/fec0:0:0:1::1-fec0:0:0:2::2/use + esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ; +spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec + esp/transport/fec0:0:0:2::2-fec0:0:0:1::1/use + esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ; +add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001 + -m transport + -E cast128-cbc "12341234" + -A hmac-sha1 "this is the test key" ; +add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10002 + -E rc5-cbc "kamekame" + -A hmac-md5 "this is the test" ; +add fec0:0:0:2::2 fec0:0:0:1::1 esp 0x10003 + -m transport + -E cast128-cbc "12341234" + -A hmac-sha1 "this is the test key" ; +add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004 + -E rc5-cbc "kamekame" + -A hmac-md5 "this is the test" ; + +# By "get" command, you can get a entry of either SP or SA. +get fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; + +# Also delete command, you can delete a entry of either SP or SA. +spddelete out fec0:0:0:1::/64 fec0:0:0:2:/64 any ; +delete fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; + +# By dump command, you can dump all entry of either SP or SA. +dump ; +spddump ; +dump esp ; +flush esp ; + +# By flush command, you can flush all entry of either SP or SA. +flush ; +spdflush ; + +# "flush" and "dump" commands can specify a security protocol. +dump esp ; +flush ah ; + +# XXX +add ::1 ::1 esp 10001 -m transport -E simple ; +add ::1 ::1 esp 10002 -m transport -E des-deriv "12341234" ; +add ::1 ::1 esp-old 10003 -m transport -E des-32iv "12341234" ; +add ::1 ::1 esp 10004 -m transport -E simple -A null ; +add ::1 ::1 esp 10005 -m transport -E simple -A hmac-md5 "1234123412341234" ; +add ::1 ::1 esp 10006 -m tunnel -E simple -A hmac-sha1 "12341234123412341234" ; +add ::1 ::1 esp 10007 -m transport -E simple -A keyed-md5 "1234123412341234" ; +add ::1 ::1 esp 10008 -m any -E simple -A keyed-sha1 "12341234123412341234" ; +add ::1 ::1 esp 10009 -m transport -E des-cbc "testtest" ; +add ::1 ::1 esp 10010 -m transport -E 3des-cbc "testtest12341234testtest" ; +add ::1 ::1 esp 10011 -m tunnel -E cast128-cbc "testtest1234" ; +add ::1 ::1 esp 10012 -m tunnel -E blowfish-cbc "testtest1234" ; +add ::1 ::1 esp 10013 -m tunnel -E rc5-cbc "testtest1234" ; +add ::1 ::1 esp 10014 -m any -E rc5-cbc "testtest1234" ; +add ::1 ::1 esp 10015 -m transport -f zero-pad -E simple ; +add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E simple ; +add ::1 ::1 esp 10017 -m transport -f seq-pad -f cyclic-seq -E simple ; +add ::1 ::1 esp 10018 -m transport -E simple ; +#add ::1 ::1 ah 20000 -m transport -A null ; +add ::1 ::1 ah 20001 -m any -A hmac-md5 "1234123412341234"; +add ::1 ::1 ah 20002 -m tunnel -A hmac-sha1 "12341234123412341234"; +add ::1 ::1 ah 20003 -m transport -A keyed-md5 "1234123412341234"; +add ::1 ::1 ah-old 20004 -m transport -A keyed-md5 "1234123412341234"; +add ::1 ::1 ah 20005 -m transport -A keyed-sha1 "12341234123412341234"; +#add ::1 ::1 ipcomp 30000 -C oui ; +add ::1 ::1 ipcomp 30001 -C deflate ; +#add ::1 ::1 ipcomp 30002 -C lzs ; + +# enjoy. diff --git a/sbin/setkey/scriptdump.pl b/sbin/setkey/scriptdump.pl new file mode 100644 index 0000000..5df9b4f --- /dev/null +++ b/sbin/setkey/scriptdump.pl @@ -0,0 +1,54 @@ +#! @LOCALPREFIX@/bin/perl +# $FreeBSD$ + +if ($< != 0) { + print STDERR "must be root to invoke this\n"; + exit 1; +} + +$mode = 'add'; +while ($i = shift @ARGV) { + if ($i eq '-d') { + $mode = 'delete'; + } else { + print STDERR "usage: scriptdump [-d]\n"; + exit 1; + } +} + +open(IN, "setkey -D |") || die; +foreach $_ (<IN>) { + if (/^[^\t]/) { + ($src, $dst) = split(/\s+/, $_); + } elsif (/^\t(esp|ah) mode=(\S+) spi=(\d+).*replay=(\d+)/) { + ($proto, $ipsecmode, $spi, $replay) = ($1, $2, $3, $4); + } elsif (/^\tE: (\S+) (.*)/) { + $ealgo = $1; + $ekey = $2; + $ekey =~ s/\s//g; + $ekey =~ s/^/0x/g; + } elsif (/^\tA: (\S+) (.*)/) { + $aalgo = $1; + $akey = $2; + $akey =~ s/\s//g; + $akey =~ s/^/0x/g; + } elsif (/^\tstate=/) { + print "$mode $src $dst $proto $spi -m $ipsecmode"; + print " -r $replay" if $replay; + if ($mode eq 'add') { + if ($proto eq 'esp') { + print " -E $ealgo $ekey" if $ealgo; + print " -A $aalgo $akey" if $aalgo; + } elsif ($proto eq 'ah') { + print " -A $aalgo $akey" if $aalgo; + } + } + print ";\n"; + + $src = $dst = $upper = $proxy = ''; + $ealgo = $ekey = $aalgo = $akey = ''; + } +} +close(IN); + +exit 0; diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 new file mode 100644 index 0000000..1f6f33c --- /dev/null +++ b/sbin/setkey/setkey.8 @@ -0,0 +1,550 @@ +.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the project nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: setkey.8,v 1.14 1999/10/27 17:08:58 sakane Exp $ +.\" $FreeBSD$ +.\" +.Dd May 17, 1998 +.Dt SETKEY 8 +.Os KAME +.\" +.Sh NAME +.Nm setkey +.Nd manually manipulate the SA/SP database. +.\" +.Sh SYNOPSIS +.Nm setkey +.Op Fl dv +.Fl c +.Nm setkey +.Op Fl dv +.Fl f Ar filename +.Nm setkey +.Op Fl adPlv +.Fl D +.Nm setkey +.Op Fl dPv +.Fl F +.Nm setkey +.Op Fl h +.Fl x +.\" +.Sh DESCRIPTION +.Nm +updates, or lists the content of, Security Association Database (SAD) entries +in the kernel as well as Security Policy Database (SPD) entries. +.Pp +.Nm +takes a series of operation from standard input +.Po +if invoked with +.Fl c +.Pc +or file named +.Ar filename +.Po +if invoked with +.Fl f Ar filename +.Pc . +.Bl -tag -width Ds +.It Fl D +Dump the SAD entries. +If with +.Fl P , +the SPD entries are dumped. +.It Fl F +Flush the SAD. +If with +.Fl P , +the SPD are flushed. +.It Fl a +.Nm +usually do not display dead SAD entries on +.Fl D . +With +.Fl a , +dead SAD entries will be displayed as well. +Dead SAD entries are kept in the kernel, +when they are referenced from any of SPD entries in the kernel. +.It Fl d +Enable debugging messages. +.It Fl x +Loop forever and dump all the messages transmitted to +.Dv PF_KEY +socket. +.It Fl h +Add hexadecimal dump on +.Fl x +mode. The order is significant. +.It Fl l +Loop forever with short output on +.Fl D . +.It Fl v +Be verbose. +.Dv PF_KEY +socket +.Po +including messages sent from other processes +.Pc . +.El +.Pp +Operation has the following grammar. Note that lines, that start with a +hashmark ('#') are treated as comment lines. +Description of meta-arguments follows. +.Bl -tag -width Ds +.It Xo +.Li add +.Ar src Ar dst Ar protocol Ar spi +.Op Ar extensions +.Ar algorithm... +.Li ; +.Xc +Add a SAD entry. +.\" +.It Xo +.Li get +.Ar src Ar dst Ar protocol Ar spi +.Op Ar mode +.Li ; +.Xc +Show a SAD entry. +.\" +.It Xo +.Li delete +.Ar src Ar dst Ar protocol Ar spi +.Op Ar mode +.Li ; +.Xc +Remove a SAD entry. +.\" +.It Xo +.Li flush +.Op Ar protocol +.Li ; +.Xc +Clear all SAD entries that matches the options. +.\" +.It Xo +.Li dump +.Op Ar protocol +.Li ; +.Xc +Dumps all SAD entries that matches the options. +.\" +.It Xo +.Li spdadd +.Ar src_range Ar dst_range Ar upperspec Ar policy +.Li ; +.Xc +Add a SPD entry. +.\" +.It Xo +.Li spddelete +.Ar src_range Ar dst_range Ar upperspec +.Li ; +.Xc +Delete a SPD entry. +.\" +.It Xo +.Li spdflush +.Li ; +.Xc +Clear all SPD entries. +.\" +.It Xo +.Li spddump +.Li ; +.Xc +Dumps all SAD entries. +.El +.\" +.Pp +Meta-arguments are as follows: +.Bl -tag -compact -width Ds +.It Ar src +.It Ar dst +Source/destination of the secure communication is specified as +IPv4/v6 address. +.Nm +does not consult hostname-to-address for arguments +.Ar src +and +.Ar dst . +They must be in numeric form. +.\" +.Pp +.It Ar protocol +.Ar protocol +is one of following: +.Bl -tag -width Fl -compact +.It Li esp +ESP based on rfc2405 +.It Li esp-old +ESP based on rfc1827 +.It Li ah +AH based on rfc2402 +.It Li ah-old +AH based on rfc1826 +.It Li ipcomp +IPCOMP +.El +.\" +.Pp +.It Ar spi +Security Parameter Index (SPI) for the SA and SPD. +It must be decimal number or hexadecimal number +.Po +with +.Li 0x +attached +.Pc . +.\" +.Pp +.It Ar extensions +takes some of the following: +.Bl -tag -width Fl -compact +.It Fl m Ar mode +Specify an security protocol mode for use. By default, +.Li any . +.Ar mode +is one of following: +.Li transport , tunnel +or +.Li any . +.It Fl r Ar size +Specify window size of bytes for replay prevention. +.Ar size +must be decimal number in 32-bit word. If +.Ar size +is zero or not specified, replay check don't take place. +.It Fl f Ar pad_option +.Ar pad_option +is one of following: +.Li zero-pad , random-pad +or +.Li seq-pad +.It Fl f Li cyclic-seq +Allow cyclic sequence number. +.It Fl lh Ar time +.It Fl ls Ar time +Specify hard/soft lifetime. +.El +.\" +.Pp +.It Ar algorithm +.Bl -tag -width Fl -compact +.It Fl E Ar ealgo Ar key +Specify encryption algorithm. +.It Fl A Ar ealgo Ar key +Specify authentication algorithm. +If +.Fl A +is used for esp, it will be treated as ESP payload authentication algorithm. +.It Fl C Ar calgo Op Fl R +Specify compression algorithm. +If +.Fl R +is specified with +.Li ipcomp +line, the kernel will use well-known IPComp CPI +.Pq compression parameter index +on IPComp CPI field on packets, and +.Ar spi +field will be ignored. +.Ar spi +field is only for kernel internal use in this case. +.\"Therefore, compression protocol number will appear on IPComp CPI field. +If +.Fl R +is not used, +the value on +.Ar spi +field will appear on IPComp CPI field on outgoing packets. +.Ar spi +field needs to be smaller than +.Li 0x10000 +in this case. +.El +.Pp +.Li esp +SAs accept +.Fl E +and +.Fl A . +.Li esp-old +SAs accept +.Fl E +only. +.Li ah +and +.Li ah-old +SAs accept +.Fl A +only. +.Li ipcomp +SAs accept +.Fl C +only. +.Pp +.Ar key +must be double-quoted character string or a series of hexadecimal digits. +.Pp +Possible values for +.Ar ealgo , +.Ar aalgo +and +.Ar calgo +are specified in separate section. +.\" +.It Ar src_range +.It Ar dst_range +These are selection of the secure communication is specified as +IPv4/v6 address or IPv4/v6 address range, and it may accompany +TCP/UDP port specification. +This takes the following form: +.Bd -literal -offset +.Ar address +.Ar address/prefixlen +.Ar address[port] +.Ar address/prefixlen[port] +.Ed +.Pp +.Ar prefixlen +and +.Ar port +must be decimal number. +The square bracket around +.Ar port +is really necessary. +They are not manpage metacharacters. +.Pp +.Nm +does not consult hostname-to-address for arguments +.Ar src +and +.Ar dst . +They must be in numeric form. +.\" +.It Ar upperspec +Upper-layer protocol to be used. +Currently +.Li tcp , +.Li udp +and +.Li any +can be specified. +.Li any +stands for +.Dq any protocol . +.Pp +NOTE: +.Ar upperspec +does not work against forwarding case at this moment, +as it requires extra reassembly at forwarding node +.Pq not implemented as this moment . +.\" +.It Ar policy +.Ar policy +is the one of following: +.Bd -literal -offset +.Xo +.Fl P +.Ar direction +.Li discard +.Xc +.Xo +.Fl P +.Ar direction +.Li none +.Xc +.Xo +.Fl P +.Ar direction +.Li ipsec +.Ar protocol/mode/src-dst/level +.Xc +.Ed +.Pp +You must specify the direction of its policy as +.Ar direction . +Either +.Li out +or +.Li in +are used. +.Li discard +means the packet matching indexes will be discarded. +.Li none +means that IPsec operation will not take place onto the packet. +.Li ipsec +means that IPsec operation will take place onto the packet. +Either +.Li ah , +.Li esp +or +.Li ipcomp +is to be set as +.Ar protocol . +.Ar mode +is either +.Li transport +or +.Li tunnel . +You must specify the end-points addresses of the SA as +.Ar src +and +.Ar dst +with +.Sq - +between these addresses which is used to specify the SA to use. +.Ar level +is to be one of the following: +.Li default , use +or +.Li require . +.Li default +means kernel consults to the system wide default against protocol you +specified, e.g. +.Li esp_trans_deflev +sysctl variable, when kernel processes the packet. +.Li use +means that kernel use a SA if it's available, +otherwise kernel keeps normal operation. +.Li require +means SA is required whenever kernel deals with the packet. +Note that +.Dq Li discard +and +.Dq Li none +are not in the syntax described in +.Xr ipsec_set_policy 3 . +There are little differences in the syntax. +See +.Xr ipsec_set_policy 3 +for detail. +.Pp +.El +.Pp +.\" +.Sh ALGORITHMS +The following list shows the supported algorithms. +.Sy protocol +and +.Sy algorithm +are almost orthogonal. +Following are the list of authentication algorithms that can be used as +.Ar aalgo +in +.Fl A Ar aalgo +of +.Ar protocol +parameter: +.Pp +.Bd -literal -offset indent +algorithm keylen (bits) comment +hmac-md5 128 ah: rfc2403 + 128 ah-old: rfc2085 +hmac-sha1 160 ah: rfc2404 + 160 ah-old: 128bit ICV (no document) +keyed-md5 128 ah: 96bit ICV (no document) + 128 ah-old: rfc1828 +keyed-sha1 160 ah: 96bit ICV (no document) + 160 ah-old: 128bit ICV (no document) +null 0 to 2048 for debugging +.Ed +.Pp +Following are the list of encryption algorithms that can be used as +.Ar ealgo +in +.Fl E Ar ealgo +of +.Ar protocol +parameter: +.Pp +.Bd -literal -offset indent +algorithm keylen (bits) comment +des-cbc 64 esp-old: rfc1829, esp: rfc2405 +3des-cbc 192 rfc2451 +simple 0 to 2048 rfc2410 +blowfish-cbc 40 to 448 rfc2451 +cast128-cbc 40 to 128 rfc2451 +rc5-cbc 40 to 2040 rfc2451 +des-deriv 64 ipsec-ciph-des-derived-01 (expired) +3des-deriv 192 no document +.Ed +.Pp +Following are the list of compression algorithms that can be used as +.Ar calgo +in +.Fl C Ar calgo +of +.Ar protocol +parameter: +.Pp +.Bd -literal -offset indent +algorithm comment +deflate rfc2394 +lzs rfc2395 +.Ed +.\" +.Sh EXAMPLES +.Bd -literal -offset +add 3ffe:501:4819::1 3ffe:501:481d::1 esp 123457 + -E des-cbc "ESP SA!!" + +add 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 + -A hmac-sha1 "AH SA configuration!" ; + +add 10.0.11.41 10.0.11.33 esp 0x10001 + -E des-cbc "ESP with" + -A hmac-md5 "authentication!!" ; + +get 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 ; + +flush ; + +dump esp ; + +spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any + -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ; + +.Ed +.\" +.Sh RETURN VALUES +The command exits with 0 on success, and non-zero on errors. +.\" +.Sh SEE ALSO +.Xr ipsec_set_policy 3 , +.Xr sysctl 8 +.\" +.Sh HISTORY +The +.Nm +command first appeared in WIDE Hydrangea IPv6 protocol stack kit. +The command was completely re-designed in June 1998. +.\" +.\" .Sh BUGS diff --git a/sbin/setkey/setkey.c b/sbin/setkey/setkey.c new file mode 100644 index 0000000..73edc3f --- /dev/null +++ b/sbin/setkey/setkey.c @@ -0,0 +1,566 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* KAME $Id: setkey.c,v 1.5 1999/10/26 09:39:37 sakane Exp $ */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <err.h> +#include <net/route.h> +#include <netinet/in.h> +#include <net/pfkeyv2.h> +#include <netkey/keydb.h> +#include <netkey/key_debug.h> +#include <netinet6/ipsec.h> + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <errno.h> +#include <netdb.h> + +void Usage __P((void)); +int main __P((int, char **)); +int get_supported __P((void)); +void sendkeyshort __P((u_int)); +void promisc __P((void)); +int sendkeymsg __P((void)); +int postproc __P((struct sadb_msg *, int)); +const char *numstr __P((int)); +void shortdump_hdr __P((void)); +void shortdump __P((struct sadb_msg *)); + +#define MODE_SCRIPT 1 +#define MODE_CMDDUMP 2 +#define MODE_CMDFLUSH 3 + +int so; + +int f_forever = 0; +int f_all = 0; +int f_debug = 0; +int f_verbose = 0; +int f_mode = 0; +int f_cmddump = 0; +int f_policy = 0; +int f_promisc = 0; +int f_hexdump = 0; +char *pname; + +u_char m_buf[BUFSIZ]; +u_int m_len; + +extern int lineno; + +extern int parse __P((FILE **)); + +void +Usage() +{ + printf("Usage:\t%s [-dv] -c\n", pname); + printf("\t%s [-dv] -f (file)\n", pname); + printf("\t%s [-Padlv] -D\n", pname); + printf("\t%s [-Pdv] -F\n", pname); + printf("\t%s [-h] -x\n", pname); + pfkey_close(so); + exit(0); +} + +int +main(ac, av) + int ac; + char **av; +{ + FILE *fp = stdin; + int c; + + pname = *av; + + if (ac == 1) Usage(); + + while ((c = getopt(ac, av, "acdf:hlvxDFP")) != EOF) { + switch (c) { + case 'c': + f_mode = MODE_SCRIPT; + fp = stdin; + break; + case 'f': + f_mode = MODE_SCRIPT; + if ((fp = fopen(optarg, "r")) == NULL) { + err(-1, "fopen"); + /*NOTREACHED*/ + } + break; + case 'D': + f_mode = MODE_CMDDUMP; + break; + case 'F': + f_mode = MODE_CMDFLUSH; + break; + case 'a': + f_all = 1; + break; + case 'l': + f_forever = 1; + break; + case 'h': + f_hexdump = 1; + break; + case 'x': + f_promisc = 1; + promisc(); + /*NOTREACHED*/ + case 'P': + f_policy = 1; + break; + case 'd': + f_debug = 1; + break; + case 'v': + f_verbose = 1; + break; + default: + Usage(); + /*NOTREACHED*/ + } + } + + switch (f_mode) { + case MODE_CMDDUMP: + sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP); + break; + case MODE_CMDFLUSH: + sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); + pfkey_close(so); + break; + case MODE_SCRIPT: + if (get_supported() < 0) { + errx(-1, "%s", ipsec_strerror()); + /*NOTREACHED*/ + } + parse(&fp); + break; + default: + Usage(); + } + + exit(0); +} + +int +get_supported() +{ + int so; + + if ((so = pfkey_open()) < 0) { + perror("pfkey_open"); + return -1; + } + + /* debug mode ? */ + if (f_debug) + return 0; + + if (pfkey_send_register(so, PF_UNSPEC) < 0) + return -1; + + if (pfkey_recv_register(so) < 0) + return -1; + + return 0; +} + +void +sendkeyshort(type) + u_int type; +{ + struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; + + m_len = sizeof(struct sadb_msg); + + m_msg->sadb_msg_version = PF_KEY_V2; + m_msg->sadb_msg_type = type; + m_msg->sadb_msg_errno = 0; + m_msg->sadb_msg_satype = SADB_SATYPE_UNSPEC; + m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); + m_msg->sadb_msg_reserved = 0; + m_msg->sadb_msg_reserved = 0; + m_msg->sadb_msg_seq = 0; + m_msg->sadb_msg_pid = getpid(); + + sendkeymsg(); + + return; +} + +void +promisc() +{ + struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; + u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ + int so, len; + + m_len = sizeof(struct sadb_msg); + + m_msg->sadb_msg_version = PF_KEY_V2; + m_msg->sadb_msg_type = SADB_X_PROMISC; + m_msg->sadb_msg_errno = 0; + m_msg->sadb_msg_satype = 1; + m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); + m_msg->sadb_msg_reserved = 0; + m_msg->sadb_msg_reserved = 0; + m_msg->sadb_msg_seq = 0; + m_msg->sadb_msg_pid = getpid(); + + if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { + err(1, "socket(PF_KEY)"); + /*NOTREACHED*/ + } + + if ((len = send(so, m_buf, m_len, 0)) < 0) { + err(1, "send"); + /*NOTREACHED*/ + } + + while (1) { + struct sadb_msg *base; + + if ((len = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { + err(1, "recv"); + /*NOTREACHED*/ + } + + if (len != sizeof(*base)) + continue; + + base = (struct sadb_msg *)rbuf; + if ((len = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), + 0)) < 0) { + err(1, "recv"); + /*NOTREACHED*/ + } + if (f_hexdump) { + int i; + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("%08x: ", i); + printf("%02x ", rbuf[i] & 0xff); + if (i % 16 == 15) + printf("\n"); + } + if (len % 16) + printf("\n"); + } + /* adjust base pointer for promisc mode */ + if (base->sadb_msg_type == SADB_X_PROMISC) { + if (sizeof(*base) < len) + base++; + else + base = NULL; + } + if (base) { + kdebug_sadb(base); + printf("\n"); + fflush(stdout); + } + } +} + +int +sendkeymsg() +{ + int so; + + u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ + int len; + struct sadb_msg *msg; + + if ((so = pfkey_open()) < 0) { + perror("pfkey_open"); + return -1; + } + + { + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt"); + goto end; + } + } + + if (f_forever) + shortdump_hdr(); +again: + if (f_verbose) + kdebug_sadb((struct sadb_msg *)m_buf); + + if ((len = send(so, m_buf, m_len, 0)) < 0) { + perror("send"); + goto end; + } + + msg = (struct sadb_msg *)rbuf; + do { + if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { + perror("recv"); + goto end; + } + + if (PFKEY_UNUNIT64(msg->sadb_msg_len) != len) { + warnx("invalid keymsg length"); + break; + } + + if (f_verbose) + kdebug_sadb((struct sadb_msg *)rbuf); + if (postproc(msg, len) < 0) + break; + } while (msg->sadb_msg_errno || msg->sadb_msg_seq); + + if (f_forever) { + fflush(stdout); + sleep(1); + goto again; + } + +end: + pfkey_close(so); + return(0); +} + +int +postproc(msg, len) + struct sadb_msg *msg; + int len; +{ + + if (msg->sadb_msg_errno != 0) { + char inf[80]; + char *errmsg = NULL; + + if (f_mode == MODE_SCRIPT) + snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); + else + inf[0] = '\0'; + + switch (msg->sadb_msg_errno) { + case ENOENT: + switch (msg->sadb_msg_type) { + case SADB_DELETE: + case SADB_GET: + case SADB_X_SPDDELETE: + errmsg = "No entry"; + break; + case SADB_DUMP: + errmsg = "No SAD entries"; + break; + case SADB_X_SPDDUMP: + errmsg = "No SPD entries"; + break; + } + break; + default: + errmsg = strerror(msg->sadb_msg_errno); + } + printf("%s%s.\n", inf, errmsg); + return(-1); + } + + switch (msg->sadb_msg_type) { + case SADB_GET: + pfkey_sadump(msg); + break; + + case SADB_DUMP: + /* filter out DEAD SAs */ + if (!f_all) { + caddr_t mhp[SADB_EXT_MAX + 1]; + struct sadb_sa *sa; + pfkey_align(msg, mhp); + pfkey_check(mhp); + if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { + if (sa->sadb_sa_state == SADB_SASTATE_DEAD) + break; + } + } + if (f_forever) + shortdump(msg); + else + pfkey_sadump(msg); + msg = (struct sadb_msg *)((caddr_t)msg + + PFKEY_UNUNIT64(msg->sadb_msg_len)); + if (f_verbose) + kdebug_sadb((struct sadb_msg *)msg); + break; + + case SADB_X_SPDDUMP: + pfkey_spdump(msg); + if (msg->sadb_msg_seq == 0) break; + msg = (struct sadb_msg *)((caddr_t)msg + + PFKEY_UNUNIT64(msg->sadb_msg_len)); + if (f_verbose) + kdebug_sadb((struct sadb_msg *)msg); + break; + } + + return(0); +} + +/*------------------------------------------------------------*/ +static char *satype[] = { + NULL, NULL, "ah", "esp" +}; +static char *sastate[] = { + "L", "M", "D", "d" +}; +static char *ipproto[] = { +/*0*/ "ip", "icmp", "igmp", "ggp", "ip4", + NULL, "tcp", NULL, "egp", NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "udp", NULL, NULL, +/*20*/ NULL, NULL, "idp", NULL, NULL, + NULL, NULL, NULL, NULL, "tp", +/*30*/ NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, +/*40*/ NULL, "ip6", NULL, "rt6", "frag6", + NULL, "rsvp", "gre", NULL, NULL, +/*50*/ "esp", "ah", NULL, NULL, NULL, + NULL, NULL, NULL, "icmp6", "none", +/*60*/ "dst6", +}; + +#define STR_OR_ID(x, tab) \ + (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) + +const char * +numstr(x) + int x; +{ + static char buf[20]; + snprintf(buf, sizeof(buf), "#%d", x); + return buf; +} + +void +shortdump_hdr() +{ + printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", + "time", "p", "s", "spi", "ltime", "src", "dst"); +} + +void +shortdump(msg) + struct sadb_msg *msg; +{ + caddr_t mhp[SADB_EXT_MAX + 1]; + char buf[1024], pbuf[10]; + struct sadb_sa *sa; + struct sadb_address *saddr; + struct sadb_lifetime *lts, *lth, *ltc; + struct sockaddr *s; + u_int t; + time_t cur = time(0); + + pfkey_align(msg, mhp); + pfkey_check(mhp); + + printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); + + printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); + + if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { + printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); + printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); + } else + printf("%-1s %-8s", "?", "?"); + + lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; + lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; + ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; + if (lts && lth && ltc) { + if (ltc->sadb_lifetime_addtime == 0) + t = (u_long)0; + else + t = (u_long)(cur - ltc->sadb_lifetime_addtime); + if (t >= 1000) + strcpy(buf, " big/"); + else + snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); + printf("%s", buf); + + t = (u_long)lth->sadb_lifetime_addtime; + if (t >= 1000) + strcpy(buf, "big"); + else + snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); + printf("%s", buf); + } else + printf(" ???/???"); + + printf(" "); + + if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { + if (saddr->sadb_address_proto) + printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); + s = (struct sockaddr *)(saddr + 1); + getnameinfo(s, s->sa_len, buf, sizeof(buf), + pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); + if (strcmp(pbuf, "0") != 0) + printf("%s[%s]", buf, pbuf); + else + printf("%s", buf); + } else + printf("?"); + + printf(" -> "); + + if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { + if (saddr->sadb_address_proto) + printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); + + s = (struct sockaddr *)(saddr + 1); + getnameinfo(s, s->sa_len, buf, sizeof(buf), + pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); + if (strcmp(pbuf, "0") != 0) + printf("%s[%s]", buf, pbuf); + else + printf("%s", buf); + } else + printf("?"); + + printf("\n"); +} diff --git a/sbin/setkey/test-pfkey.c b/sbin/setkey/test-pfkey.c new file mode 100644 index 0000000..849aba3 --- /dev/null +++ b/sbin/setkey/test-pfkey.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* KAME $Id: test-pfkey.c,v 1.2 1999/10/26 08:09:17 itojun Exp $ */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <net/route.h> +#include <net/pfkeyv2.h> +#include <netinet/in.h> +#include <netkey/keydb.h> +#include <netkey/key_var.h> +#include <netkey/key_debug.h> + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <errno.h> + +u_char m_buf[BUFSIZ]; +u_int m_len; +char *pname; + +void Usage __P((void)); +int sendkeymsg __P((void)); +void key_setsadbmsg __P((u_int)); +void key_setsadbsens __P((void)); +void key_setsadbprop __P((void)); +void key_setsadbid __P((u_int, caddr_t)); +void key_setsadblft __P((u_int, u_int)); +void key_setspirange __P((void)); +void key_setsadbkey __P((u_int, caddr_t)); +void key_setsadbsa __P((void)); +void key_setsadbaddr __P((u_int, u_int, caddr_t)); +void key_setsadbextbuf __P((caddr_t, int, caddr_t, int, caddr_t, int)); + +void +Usage() +{ + printf("Usage:\t%s number\n", pname); + exit(0); +} + +int +main(ac, av) + int ac; + char **av; +{ + pname = *av; + + if (ac == 1) Usage(); + + key_setsadbmsg(atoi(*(av+1))); + sendkeymsg(); + + exit(0); +} + +/* %%% */ +int +sendkeymsg() +{ + u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ + int so, len; + + if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { + perror("socket(PF_KEY)"); + goto end; + } + + pfkey_sadump((struct sadb_msg *)m_buf); + + if ((len = send(so, m_buf, m_len, 0)) < 0) { + perror("send"); + goto end; + } + + if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { + perror("recv"); + goto end; + } + + pfkey_sadump((struct sadb_msg *)rbuf); + +end: + (void)close(so); + return(0); +} + +void +key_setsadbmsg(type) + u_int type; +{ + struct sadb_msg m_msg; + + m_msg.sadb_msg_version = PF_KEY_V2; + m_msg.sadb_msg_type = type; + m_msg.sadb_msg_errno = 0; + m_msg.sadb_msg_satype = SADB_SATYPE_ESP; + m_msg.sadb_msg_reserved = 0; + m_msg.sadb_msg_seq = 0; + m_msg.sadb_msg_pid = getpid(); + + m_len = sizeof(struct sadb_msg); + memcpy(m_buf, &m_msg, m_len); + + switch (type) { + case SADB_GETSPI: + /*<base, address(SD), SPI range>*/ + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1"); + key_setspirange(); + /*<base, SA(*), address(SD)>*/ + break; + + case SADB_ADD: + /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) + key(AE), (identity(SD),) (sensitivity)> */ + key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); + case SADB_UPDATE: + key_setsadbsa(); + key_setsadblft(SADB_EXT_LIFETIME_HARD, 10); + key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5); + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); + /* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */ + key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678"); + key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678"); + key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com"); + key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net"); + key_setsadbsens(); + /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) + (identity(SD),) (sensitivity)> */ + break; + + case SADB_DELETE: + /* <base, SA(*), address(SDP)> */ + key_setsadbsa(); + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); + key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); + /* <base, SA(*), address(SDP)> */ + break; + + case SADB_GET: + /* <base, SA(*), address(SDP)> */ + key_setsadbsa(); + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); + key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); + /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) + key(AE), (identity(SD),) (sensitivity)> */ + break; + + case SADB_ACQUIRE: + /* <base, address(SD), (address(P),) (identity(SD),) + (sensitivity,) proposal> */ + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); + key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); + key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com"); + key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net"); + key_setsadbsens(); + key_setsadbprop(); + /* <base, address(SD), (address(P),) (identity(SD),) + (sensitivity,) proposal> */ + break; + + case SADB_REGISTER: + /* <base> */ + /* <base, supported> */ + break; + + case SADB_EXPIRE: + case SADB_FLUSH: + break; + + case SADB_DUMP: + break; + + case SADB_X_PROMISC: + /* <base> */ + /* <base, base(, others)> */ + break; + + case SADB_X_PCHANGE: + break; + + /* for SPD management */ + case SADB_X_SPDFLUSH: + case SADB_X_SPDDUMP: + break; + + case SADB_X_SPDADD: + case SADB_X_SPDDELETE: + key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); + key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); + break; + } + + ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); + + return; +} + +void +key_setsadbsens() +{ + struct sadb_sens m_sens; + u_char buf[64]; + u_int s, i, slen, ilen, len; + + /* make sens & integ */ + s = htonl(0x01234567); + i = htonl(0x89abcdef); + slen = sizeof(s); + ilen = sizeof(i); + memcpy(buf, &s, slen); + memcpy(buf + slen, &i, ilen); + + len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen); + m_sens.sadb_sens_len = PFKEY_UNIT64(len); + m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY; + m_sens.sadb_sens_dpd = 1; + m_sens.sadb_sens_sens_level = 2; + m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen); + m_sens.sadb_sens_integ_level = 3; + m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen); + m_sens.sadb_sens_reserved = 0; + + key_setsadbextbuf(m_buf, m_len, + (caddr_t)&m_sens, sizeof(struct sadb_sens), + buf, slen + ilen); + m_len += len; + + return; +} + +void +key_setsadbprop() +{ + struct sadb_prop m_prop; + struct sadb_comb *m_comb; + u_char buf[256]; + u_int len = sizeof(m_prop) + sizeof(m_comb) * 2; + + /* make prop & comb */ + m_prop.sadb_prop_len = PFKEY_UNIT64(len); + m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL; + m_prop.sadb_prop_replay = 0; + m_prop.sadb_prop_reserved[0] = 0; + m_prop.sadb_prop_reserved[1] = 0; + m_prop.sadb_prop_reserved[2] = 0; + + /* the 1st is ESP DES-CBC HMAC-MD5 */ + m_comb = (struct sadb_comb *)buf; + m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC; + m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC; + m_comb->sadb_comb_flags = 0; + m_comb->sadb_comb_auth_minbits = 8; + m_comb->sadb_comb_auth_maxbits = 96; + m_comb->sadb_comb_encrypt_minbits = 64; + m_comb->sadb_comb_encrypt_maxbits = 64; + m_comb->sadb_comb_reserved = 0; + m_comb->sadb_comb_soft_allocations = 0; + m_comb->sadb_comb_hard_allocations = 0; + m_comb->sadb_comb_soft_bytes = 0; + m_comb->sadb_comb_hard_bytes = 0; + m_comb->sadb_comb_soft_addtime = 0; + m_comb->sadb_comb_hard_addtime = 0; + m_comb->sadb_comb_soft_usetime = 0; + m_comb->sadb_comb_hard_usetime = 0; + + /* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */ + m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb)); + m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC; + m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; + m_comb->sadb_comb_flags = 0; + m_comb->sadb_comb_auth_minbits = 8; + m_comb->sadb_comb_auth_maxbits = 96; + m_comb->sadb_comb_encrypt_minbits = 64; + m_comb->sadb_comb_encrypt_maxbits = 64; + m_comb->sadb_comb_reserved = 0; + m_comb->sadb_comb_soft_allocations = 0; + m_comb->sadb_comb_hard_allocations = 0; + m_comb->sadb_comb_soft_bytes = 0; + m_comb->sadb_comb_hard_bytes = 0; + m_comb->sadb_comb_soft_addtime = 0; + m_comb->sadb_comb_hard_addtime = 0; + m_comb->sadb_comb_soft_usetime = 0; + m_comb->sadb_comb_hard_usetime = 0; + + key_setsadbextbuf(m_buf, m_len, + (caddr_t)&m_prop, sizeof(struct sadb_prop), + buf, sizeof(*m_comb) * 2); + m_len += len; + + return; +} + +void +key_setsadbid(ext, str) + u_int ext; + caddr_t str; +{ + struct sadb_ident m_id; + u_int idlen = strlen(str), len; + + len = sizeof(m_id) + PFKEY_ALIGN8(idlen); + m_id.sadb_ident_len = PFKEY_UNIT64(len); + m_id.sadb_ident_exttype = ext; + m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN; + m_id.sadb_ident_reserved = 0; + m_id.sadb_ident_id = getpid(); + + key_setsadbextbuf(m_buf, m_len, + (caddr_t)&m_id, sizeof(struct sadb_ident), + str, idlen); + m_len += len; + + return; +} + +void +key_setsadblft(ext, time) + u_int ext, time; +{ + struct sadb_lifetime m_lft; + + m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft)); + m_lft.sadb_lifetime_exttype = ext; + m_lft.sadb_lifetime_allocations = 0x2; + m_lft.sadb_lifetime_bytes = 0x1000; + m_lft.sadb_lifetime_addtime = time; + m_lft.sadb_lifetime_usetime = 0x0020; + + memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime)); + m_len += sizeof(struct sadb_lifetime); + + return; +} + +void +key_setspirange() +{ + struct sadb_spirange m_spi; + + m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi)); + m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE; + m_spi.sadb_spirange_min = 0x00001000; + m_spi.sadb_spirange_max = 0x00002000; + m_spi.sadb_spirange_reserved = 0; + + memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange)); + m_len += sizeof(struct sadb_spirange); + + return; +} + +void +key_setsadbkey(ext, str) + u_int ext; + caddr_t str; +{ + struct sadb_key m_key; + u_int keylen = strlen(str); + u_int len; + + len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); + m_key.sadb_key_len = PFKEY_UNIT64(len); + m_key.sadb_key_exttype = ext; + m_key.sadb_key_bits = keylen * 8; + m_key.sadb_key_reserved = 0; + + key_setsadbextbuf(m_buf, m_len, + (caddr_t)&m_key, sizeof(struct sadb_key), + str, keylen); + m_len += len; + + return; +} + +void +key_setsadbsa() +{ + struct sadb_sa m_sa; + + m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); + m_sa.sadb_sa_exttype = SADB_EXT_SA; + m_sa.sadb_sa_spi = htonl(0x12345678); + m_sa.sadb_sa_replay = 4; + m_sa.sadb_sa_state = 0; + m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC; + m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC; + m_sa.sadb_sa_flags = 0; + + memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa)); + m_len += sizeof(struct sadb_sa); + + return; +} + +void +key_setsadbaddr(ext, af, str) + u_int ext, af; + caddr_t str; +{ + struct sadb_address m_addr; + u_char abuf[64]; + struct sockaddr *a = (struct sockaddr *)abuf; + u_int len; + + /* make sockaddr buffer */ + memset(abuf, 0, sizeof(abuf)); + a->sa_len = _SALENBYAF(af); + a->sa_family = af; + _INPORTBYSA(a) = + (ext == SADB_EXT_ADDRESS_PROXY ? 0 : htons(0x1234)); + if (inet_pton(af, str, _INADDRBYSA(a)) != 1) + ; /* XXX do something */ + + len = sizeof(struct sadb_address) + PFKEY_ALIGN8(a->sa_len); + m_addr.sadb_address_len = PFKEY_UNIT64(len); + m_addr.sadb_address_exttype = ext; + m_addr.sadb_address_proto = + (ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP); + m_addr.sadb_address_prefixlen = _INALENBYAF(af); + m_addr.sadb_address_reserved = 0; + + key_setsadbextbuf(m_buf, m_len, + (caddr_t)&m_addr, sizeof(struct sadb_address), + abuf, a->sa_len); + m_len += len; + + return; +} + +void +key_setsadbextbuf(dst, off, ebuf, elen, vbuf, vlen) + caddr_t dst, ebuf, vbuf; + int off, elen, vlen; +{ + memset(dst + off, 0, elen + vlen); + memcpy(dst + off, (caddr_t)ebuf, elen); + memcpy(dst + off + elen, vbuf, vlen); + + return; +} + diff --git a/sbin/setkey/test-policy.c b/sbin/setkey/test-policy.c new file mode 100644 index 0000000..27cd478 --- /dev/null +++ b/sbin/setkey/test-policy.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet6/in6.h> +#include <netkey/keyv2.h> +#include <stdlib.h> +#include <string.h> + +#include <netinet6/ipsec.h> + +char *requests[] = { +"must_error", /* must be error */ +"ipsec must_error", /* must be error */ +"ipsec esp/must_error", /* must be error */ +"discard", +"none", +"entrust", +"bypass", /* may be error */ +"ipsec esp", /* must be error */ +"ipsec ah/require", +"ipsec ah/use/", +"ipsec esp/require ah/default/203.178.141.194", +"ipsec ah/use/203.178.141.195 esp/use/203.178.141.194", +"ipsec esp/elf.wide.ydc.co.jp esp/www.wide.ydc.co.jp" +" +ipsec esp/require ah/use esp/require/10.0.0.1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 +ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1ah/use/3ffe:501:481d::1 +", +}; + +u_char *p_secpolicy; + +int test(char *buf, int family); +char *setpolicy(char *req); + +main() +{ + int i; + char *buf; + + for (i = 0; i < sizeof(requests)/sizeof(requests[0]); i++) { + printf("* requests:[%s]\n", requests[i]); + if ((buf = setpolicy(requests[i])) == NULL) + continue; + printf("\tsetlen:%d\n", PFKEY_EXTLEN(buf)); + + printf("\tPF_INET:\n"); + test(buf, PF_INET); + + printf("\tPF_INET6:\n"); + test(buf, PF_INET6); + free(buf); + } +} + +int test(char *policy, int family) +{ + int so, proto, optname; + int len; + char getbuf[1024]; + + switch (family) { + case PF_INET: + proto = IPPROTO_IP; + optname = IP_IPSEC_POLICY; + break; + case PF_INET6: + proto = IPPROTO_IPV6; + optname = IPV6_IPSEC_POLICY; + break; + } + + if ((so = socket(family, SOCK_DGRAM, 0)) < 0) + perror("socket"); + + if (setsockopt(so, proto, optname, policy, PFKEY_EXTLEN(policy)) < 0) + perror("setsockopt"); + + len = sizeof(getbuf); + memset(getbuf, 0, sizeof(getbuf)); + if (getsockopt(so, proto, optname, getbuf, &len) < 0) + perror("getsockopt"); + + { + char *buf = NULL; + + printf("\tgetlen:%d\n", len); + + if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) + ipsec_strerror(); + else + printf("\t[%s]\n", buf); + + free(buf); + } + + close (so); +} + +char *setpolicy(char *req) +{ + int len; + char *buf; + + if ((len = ipsec_get_policylen(req)) < 0) { + printf("ipsec_get_policylen: %s\n", ipsec_strerror()); + return NULL; + } + + if ((buf = malloc(len)) == NULL) { + perror("malloc"); + return NULL; + } + + if ((len = ipsec_set_policy(buf, len, req)) < 0) { + printf("ipsec_set_policy: %s\n", ipsec_strerror()); + free(buf); + return NULL; + } + + return buf; +} diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l new file mode 100644 index 0000000..b75fd45 --- /dev/null +++ b/sbin/setkey/token.l @@ -0,0 +1,322 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +%{ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <net/route.h> +#include <net/pfkeyv2.h> +#include <netkey/keydb.h> +#include <netkey/key_debug.h> +#include <netinet/in.h> +#include <netinet6/ipsec.h> + +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include "vchar.h" +#include "y.tab.h" + +#define DECHO \ + if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); } + +#define CMDARG \ +{ \ + char *__buf__ = strdup(yytext), *__p__; \ + for (__p__ = __buf__; *__p__ != NULL; __p__++) \ + if (*__p__ == '\n' || *__p__ == '\t') \ + *__p__ = ' '; \ + strcat(cmdarg, __buf__); \ + free(__buf__); \ +} + +#define PREPROC DECHO CMDARG + +int lineno = 1; +char cmdarg[8192]; /* XXX: BUFSIZ is the better ? */ + +extern u_char m_buf[BUFSIZ]; +extern u_int m_len; +extern int f_debug; + +int yylex __P((void)); +void yyerror __P((char *s)); +extern void parse_init __P((void)); +int parse __P((FILE **)); +int yyparse __P((void)); + +%} + +/* common section */ +nl \n +ws [ \t]+ +digit [0-9] +letter [0-9A-Za-z] +hexdigit [0-9A-Fa-f] +/*octet (([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5])))*/ +special [()+\|\?\*,] +dot \. +comma \, +hyphen \- +colon \: +slash \/ +bcl \{ +ecl \} +blcl \[ +elcl \] +percent \% +semi \; +usec {dot}{digit}{1,6} +comment \#.* +ccomment "/*" +bracketstring \<[^>]*\> +quotedstring \"[^"]*\" +decstring {digit}+ +hexpair {hexdigit}{hexdigit} +hexstring 0[xX]{hexdigit}+ +octetstring {octet}({dot}{octet})+ +ipaddress {ipv4addr}|{ipv6addr} +ipv4addr {digit}{1,3}({dot}{digit}{1,3}){0,3} +ipv6addr {hexdigit}{0,4}({colon}{hexdigit}{0,4}){2,7}(@{letter}{letter}+)? +ipaddrmask {slash}{digit}{1,3} +ipaddrport {blcl}{decstring}{elcl} +keyword {letter}{letter}+ +name {letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))* +hostname {name}(({dot}{name})+{dot}?)? + +%s S_PL + +%% + +add { PREPROC; return(ADD); } +delete { PREPROC; return(DELETE); } +get { PREPROC; return(GET); } +flush { PREPROC; return(FLUSH); } +dump { PREPROC; return(DUMP); } + + /* for management SPD */ +spdadd { PREPROC; return(SPDADD); } +spddelete { PREPROC; return(SPDDELETE); } +spddump { PREPROC; return(SPDDUMP); } +spdflush { PREPROC; return(SPDFLUSH); } +{hyphen}P { BEGIN S_PL; PREPROC; return(F_POLICY); } +<S_PL>[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.\-_/ \n\t]* { + yymore(); + + /* count up for nl */ + { + char *p; + for (p = yytext; *p != NULL; p++) + if (*p == '\n') + lineno++; + } + + yylval.val.len = strlen(yytext); + yylval.val.buf = strdup(yytext); + + return(PL_REQUESTS); +} +<S_PL>{semi} { PREPROC; BEGIN INITIAL; return(EOT); } + + /* security protocols */ +ah { PREPROC; yylval.num = 0; return(PR_AH); } +esp { PREPROC; yylval.num = 0; return(PR_ESP); } +ah-old { PREPROC; yylval.num = 1; return(PR_AH); } +esp-old { PREPROC; yylval.num = 1; return(PR_ESP); } +ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); } + + /* authentication alogorithm */ +{hyphen}A { PREPROC; return(F_AUTH); } +hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); } +hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); } +keyed-md5 { PREPROC; yylval.num = SADB_AALG_MD5; return(ALG_AUTH); } +keyed-sha1 { PREPROC; yylval.num = SADB_AALG_SHA; return(ALG_AUTH); } +null { PREPROC; yylval.num = SADB_AALG_NULL; return(ALG_AUTH); } + + /* encryption alogorithm */ +{hyphen}E { PREPROC; return(F_ENC); } +des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); } +3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); } +simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); } +blowfish-cbc { PREPROC; yylval.num = SADB_EALG_BLOWFISHCBC; return(ALG_ENC); } +cast128-cbc { PREPROC; yylval.num = SADB_EALG_CAST128CBC; return(ALG_ENC); } +rc5-cbc { PREPROC; yylval.num = SADB_EALG_RC5CBC; return(ALG_ENC); } +des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); } +des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); } + + /* compression algorithms */ +{hyphen}C { PREPROC; return(F_COMP); } +oui { PREPROC; yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); } +deflate { PREPROC; yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); } +lzs { PREPROC; yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); } +{hyphen}R { PREPROC; return(F_RAWCPI); } + + /* extension */ +{hyphen}m { PREPROC; return(F_MODE); } +transport { PREPROC; yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } +tunnel { PREPROC; yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } +{hyphen}f { PREPROC; return(F_EXT); } +random-pad { PREPROC; yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); } +seq-pad { PREPROC; yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); } +zero-pad { PREPROC; yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); } +cyclic-seq { PREPROC; yylval.num = SADB_X_EXT_CYCSEQ; return(EXTENSION); } +{hyphen}r { PREPROC; return(F_REPLAY); } +{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); } +{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); } + + + /* upper layer protocols */ +icmp { PREPROC; yylval.num = IPPROTO_ICMP; return(UP_PROTO); } +icmp6 { PREPROC; yylval.num = IPPROTO_ICMPV6; return(UP_PROTO); } +tcp { PREPROC; yylval.num = IPPROTO_TCP; return(UP_PROTO); } +udp { PREPROC; yylval.num = IPPROTO_UDP; return(UP_PROTO); } + + /* ... */ +any { PREPROC; return(ANY); } +{ws} { PREPROC; } +{nl} { lineno++; } +{comment} +{semi} { PREPROC; return(EOT); } + + /* parameter */ +{decstring} { + char *bp; + + PREPROC; + yylval.num = strtol(yytext, &bp, 10); + return(DECSTRING); + } + +{ipv4addr} { + /* + * I can't supprt the type without dot, + * because it's umbiguous against {decstring}. + * e.g. 127 + */ + PREPROC; + + yylval.val.len = sizeof(struct sockaddr_in); + yylval.val.buf = strdup(yytext); + + return(IP4_ADDRESS); + } + +{ipv6addr} { +#ifdef INET6 + PREPROC; + + yylval.val.len = sizeof(struct sockaddr_in6); + yylval.val.buf = strdup(yytext); + + return(IP6_ADDRESS); +#else + yyerror("IPv6 address not supported"); +#endif + } + +{ipaddrmask} { + PREPROC; + yytext++; + yylval.num = atoi(yytext); + return(PREFIX); + } + +{ipaddrport} { + char *p = yytext; + PREPROC; + while (*++p != ']') ; + *p = NULL; + yytext++; + yylval.num = atoi(yytext); + return(PORT); + } + +{blcl}any{elcl} { + char *p = yytext; + PREPROC; + return(PORTANY); + } + +{hexstring} { + int len = yyleng - 2; /* (str - "0x") */ + PREPROC; + yylval.val.len = (len & 1) + (len / 2); + /* fixed string if length is odd. */ + if (len & 1) { + yytext[1] = '0'; + yylval.val.buf = strdup(yytext + 1); + } else + yylval.val.buf = strdup(yytext + 2); + + return(HEXSTRING); + } + +{quotedstring} { + char *p = yytext; + PREPROC; + while (*++p != '"') ; + *p = NULL; + yytext++; + yylval.val.len = yyleng - 2; + yylval.val.buf = strdup(yytext); + + return(QUOTEDSTRING); + } + +. { yyerror("Syntax error"); } + +%% + +void +yyerror(char *s) +{ + printf("line %d: %s at [%s]\n", lineno, s, yytext); +} + +int +parse(fp) + FILE **fp; +{ + yyin = *fp; + + parse_init(); + + if (yyparse()) { + printf("parse failed, line %d.\n", lineno); + return(-1); + } + + return(0); +} + diff --git a/sbin/setkey/vchar.h b/sbin/setkey/vchar.h new file mode 100644 index 0000000..977f5f0 --- /dev/null +++ b/sbin/setkey/vchar.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +typedef struct { + u_int len; + caddr_t buf; +} vchar_t; |