diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-01-26 14:42:48 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-01-26 14:42:48 +0000 |
commit | 0b9c28b57c8f95b0c63149241053d1e0dd045b18 (patch) | |
tree | a377844c7ec98a0ee26e5af3ebf332a5b8d4a5c0 /usr.sbin | |
parent | dd69137bb7d8747d22ca2e6539f6c80cf3467d08 (diff) |
first cut at tcpmd5 setup seupport from within bgpd. works so far.
with help from hshoexer@ and markus@
ok claudio@ hshoexer@ markus@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/config.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 17 | ||||
-rw-r--r-- | usr.sbin/bgpd/pfkey.c | 191 |
5 files changed, 221 insertions, 5 deletions
diff --git a/usr.sbin/bgpd/Makefile b/usr.sbin/bgpd/Makefile index fa370813bb0..08683bee9a6 100644 --- a/usr.sbin/bgpd/Makefile +++ b/usr.sbin/bgpd/Makefile @@ -1,11 +1,11 @@ -# $OpenBSD: Makefile,v 1.12 2004/01/05 02:55:28 espie Exp $ +# $OpenBSD: Makefile,v 1.13 2004/01/26 14:42:47 henning Exp $ .PATH: ${.CURDIR}/.. PROG= bgpd SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \ rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \ - control.c + control.c pfkey.c CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CLFAGS+= -Wmissing-declarations -Wredundant-decls diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 6d84eb1cf4d..787d897790d 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.79 2004/01/23 21:17:51 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.80 2004/01/26 14:42:47 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -33,6 +33,7 @@ #define CONFFILE "/etc/bgpd.conf" #define BGPD_USER "_bgpd" #define PEER_DESCR_LEN 32 +#define TCP_SIGN_KEY_LEN 32 #define MAX_PKTSIZE 4096 #define MIN_HOLDTIME 3 @@ -136,6 +137,7 @@ struct peer_config { u_int16_t holdtime; u_int16_t min_holdtime; enum announce_type announce_type; + char tcp_sign_key[TCP_SIGN_KEY_LEN]; enum reconf_action reconf_action; }; @@ -322,4 +324,7 @@ int control_init(void); void control_cleanup(void); int control_imsg_relay(struct imsg *); +/* pfkey.c */ +int pfkey_signature(struct sockaddr *, struct sockaddr *, char *); + #endif /* __BGPD_H__ */ diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c index 380ee3cc3f9..e88b20eed1e 100644 --- a/usr.sbin/bgpd/config.c +++ b/usr.sbin/bgpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.19 2004/01/24 17:38:30 henning Exp $ */ +/* $OpenBSD: config.c,v 1.20 2004/01/26 14:42:47 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -55,6 +55,11 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, p->conf.ebgp = (p->conf.remote_as != conf->as); if (!p->conf.id) p->conf.id = get_id(p); + if (p->conf.tcp_sign_key[0] && + pfkey_signature((struct sockaddr *)&p->conf.local_addr, + (struct sockaddr *)&p->conf.remote_addr, + p->conf.tcp_sign_key) == -1) + return (1); } memcpy(xconf, conf, sizeof(struct bgpd_config)); diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 96a38c7cba0..93f39a3c4a8 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.39 2004/01/24 19:43:37 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.40 2004/01/26 14:42:47 henning Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -92,6 +92,7 @@ typedef struct { %token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX ANNOUNCE %token DUMP MSG IN TABLE %token LOG UPDATES +%token TCP SIGNATURE KEY %token ERROR %token <v.string> STRING %type <v.number> number optnumber yesno @@ -347,6 +348,17 @@ peeropts : REMOTEAS number { | MAXPREFIX number { curpeer->conf.max_prefix = $2; } + | TCP SIGNATURE KEY string { + unsigned i; + + for (i = 0; i < strlen($4); i++) + if (!isxdigit($4[i])) { + yyerror("key should be in hex"); + YYERROR; + } + strlcpy(curpeer->conf.tcp_sign_key, $4, + sizeof(curpeer->conf.tcp_sign_key)); + } ; %% @@ -391,6 +403,7 @@ lookup(char *s) { "group", GROUP}, { "holdtime", HOLDTIME}, { "in", IN}, + { "key", KEY}, { "listen", LISTEN}, { "local-address", LOCALADDR}, { "log", LOG}, @@ -404,7 +417,9 @@ lookup(char *s) { "passive", PASSIVE}, { "remote-as", REMOTEAS}, { "router-id", ROUTERID}, + { "signature", SIGNATURE}, { "table", TABLE}, + { "tcp", TCP}, { "updates", UPDATES}, }; const struct keywords *p; diff --git a/usr.sbin/bgpd/pfkey.c b/usr.sbin/bgpd/pfkey.c new file mode 100644 index 00000000000..4804e12cb65 --- /dev/null +++ b/usr.sbin/bgpd/pfkey.c @@ -0,0 +1,191 @@ +/* $OpenBSD: pfkey.c,v 1.1 2004/01/26 14:42:47 henning Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <net/pfkeyv2.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "bgpd.h" + +#define ROUNDUP(x) (((x) + sizeof(u_int64_t) - 1) & ~(sizeof(u_int64_t) - 1)) +#define IOV_CNT 8 + +static u_int32_t sadb_msg_seq = 1; + +int send_sa_msg(struct iovec *, int, int); + +int +send_sa_msg(struct iovec *iov, int cnt, int len) +{ + struct sadb_msg sm; + int sd; + ssize_t n; + + if ((sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1) { + if (errno == EPROTONOSUPPORT) + log_warnx("no kernel support for PF_KEY"); + else + log_warn("socket"); + return (-1); + } + + if ((n = writev(sd, iov, cnt)) == -1) { + log_warn("write"); + return (-1); + } + + if (n != len) { + log_warn("writev: should=%d has=%d", len, n); + return (-1); + } + + if (read(sd, &sm, sizeof(sm)) != sizeof(sm)) { + log_warn("read"); + return (-1); + } + if (sm.sadb_msg_errno != 0) { + errno = sm.sadb_msg_errno; + log_warn("pfkey"); + return (-1); + } + close(sd); + return (0); +} + +int +pfkey_signature(struct sockaddr *src, struct sockaddr *dst, char *key) +{ + struct sadb_msg smsg; + struct sadb_sa sa; + struct sadb_address sa_src, sa_dst; + struct sadb_key sa_key; + struct iovec iov[IOV_CNT]; + int klen = 0; + int i; + char realkey[TCP_SIGN_KEY_LEN]; + char s[3]; + struct sockaddr_storage ssrc, sdst; + + /* we need clean sockaddr... no ports set */ + bzero(&ssrc, sizeof(ssrc)); + if (src->sa_family == AF_INET) { + ((struct sockaddr_in *)&ssrc)->sin_addr.s_addr = + ((struct sockaddr_in *)src)->sin_addr.s_addr; + ssrc.ss_len = sizeof(struct sockaddr_in); + ssrc.ss_family = AF_INET; + } else if (src->sa_family == AF_INET6) { + memcpy(&((struct sockaddr_in6 *)&ssrc)->sin6_addr, + &((struct sockaddr_in6 *)src)->sin6_addr, + sizeof(struct in6_addr)); + ssrc.ss_len = sizeof(struct sockaddr_in6); + ssrc.ss_family = AF_INET6; + } + + bzero(&sdst, sizeof(sdst)); + if (dst->sa_family == AF_INET) { + ((struct sockaddr_in *)&sdst)->sin_addr.s_addr = + ((struct sockaddr_in *)dst)->sin_addr.s_addr; + sdst.ss_len = sizeof(struct sockaddr_in); + sdst.ss_family = AF_INET; + } else if (dst->sa_family == AF_INET6) { + memcpy(&((struct sockaddr_in6 *)&sdst)->sin6_addr, + &((struct sockaddr_in6 *)dst)->sin6_addr, + sizeof(struct in6_addr)); + sdst.ss_len = sizeof(struct sockaddr_in6); + sdst.ss_family = AF_INET6; + } + + bzero(&smsg, sizeof(smsg)); + smsg.sadb_msg_version = PF_KEY_V2; + smsg.sadb_msg_seq = sadb_msg_seq++; + smsg.sadb_msg_pid = getpid(); + smsg.sadb_msg_len = sizeof(smsg) / 8; + smsg.sadb_msg_type = SADB_ADD; + smsg.sadb_msg_satype = SADB_X_SATYPE_TCPSIGNATURE; + + bzero(&sa, sizeof(sa)); + sa.sadb_sa_exttype = SADB_EXT_SA; + sa.sadb_sa_len = sizeof(sa) / 8; + sa.sadb_sa_replay = 0; + sa.sadb_sa_spi = 0; + sa.sadb_sa_state = SADB_SASTATE_MATURE; + + bzero(&sa_src, sizeof(sa_src)); + sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8; + + bzero(&sa_dst, sizeof(sa_dst)); + sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8; + + bzero(&sa_key, sizeof(sa_key)); + klen = strlen(key) / 2; + sa_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; + sa_key.sadb_key_len = (sizeof(sa_key) + ((klen + 7) / 8) * 8) / 8; + sa_key.sadb_key_bits = 8 * klen; + + for (i = 0; i < klen; i++) { + s[0] = key[2*i]; + s[1] = key[2*i + 1]; + s[2] = 0; + if (!isxdigit(s[0]) || !isxdigit(s[1])) { + log_warnx("espkey must be specified in hex"); + return (-1); + } + realkey[i] = strtoul(s, NULL, 16); + } + + /* msghdr */ + iov[0].iov_base = &smsg; + iov[0].iov_len = sizeof(smsg); + + /* SA hdr */ + iov[1].iov_base = &sa; + iov[1].iov_len = sizeof(sa); + smsg.sadb_msg_len += sa.sadb_sa_len; + + /* dest addr */ + iov[2].iov_base = &sa_dst; + iov[2].iov_len = sizeof(sa_dst); + iov[3].iov_base = &sdst; + iov[3].iov_len = ROUNDUP(sdst.ss_len); + smsg.sadb_msg_len += sa_dst.sadb_address_len; + + /* src addr */ + iov[4].iov_base = &sa_src; + iov[4].iov_len = sizeof(sa_src); + iov[5].iov_base = &ssrc; + iov[5].iov_len = ROUNDUP(ssrc.ss_len); + smsg.sadb_msg_len += sa_src.sadb_address_len; + + /* auth key */ + iov[6].iov_base = &sa_key; + iov[6].iov_len = sizeof(sa_key); + iov[7].iov_base = realkey; + iov[7].iov_len = ((klen + 7) / 8) * 8; + smsg.sadb_msg_len += sa_key.sadb_key_len; + + return (send_sa_msg(iov, IOV_CNT, smsg.sadb_msg_len * 8)); +} |