summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-01-26 14:42:48 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-01-26 14:42:48 +0000
commit0b9c28b57c8f95b0c63149241053d1e0dd045b18 (patch)
treea377844c7ec98a0ee26e5af3ebf332a5b8d4a5c0 /usr.sbin
parentdd69137bb7d8747d22ca2e6539f6c80cf3467d08 (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/Makefile4
-rw-r--r--usr.sbin/bgpd/bgpd.h7
-rw-r--r--usr.sbin/bgpd/config.c7
-rw-r--r--usr.sbin/bgpd/parse.y17
-rw-r--r--usr.sbin/bgpd/pfkey.c191
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));
+}