freebsd-ports/net/openbgpd/files/patch-bgpd_pfkey.c
Kurt Jaeger 05f952aaea net/openbgpd: Add patches to allow use of TCPMD5 options
- For additional details, see this post from 2013:
  http://lists.freebsd.org/pipermail/freebsd-net/2013-November/037133.html
- Please note that this patch is used by pfsense
- related changes in the base system have already been integrated, see
  https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=220170

PR:		184545
Submitted by:	anarcat@koumbit.org, eksffa@freebsdbrasil.com.br, garga@FreeBSD.org
Reviewed by:	mykel@mware.ca
Approved by:	hrs (maintainer timeout)
2018-01-12 09:03:49 +00:00

471 lines
12 KiB
C

diff -ur bgpd.orig/pfkey.c bgpd/pfkey.c
--- bgpd.orig/pfkey.c 2013-03-15 12:07:16.000000000 +0000
+++ bgpd/pfkey.c 2013-03-15 12:07:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */
+/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,7 +21,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <net/pfkeyv2.h>
-#include <netinet/ip_ipsp.h>
+//#include <netinet/ip_ipsp.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
@@ -65,15 +65,15 @@
{
struct sadb_msg smsg;
struct sadb_sa sa;
- struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
+ struct sadb_address sa_src, sa_dst;
struct sadb_key sa_akey, sa_ekey;
struct sadb_spirange sa_spirange;
- struct sadb_protocol sa_flowtype, sa_protocol;
struct iovec iov[IOV_CNT];
ssize_t n;
int len = 0;
int iov_cnt;
- struct sockaddr_storage ssrc, sdst, speer, smask, dmask;
+ struct sockaddr_storage ssrc, sdst, smask, dmask;
+ struct sockaddr *saptr;
if (!pid)
pid = getpid();
@@ -81,22 +81,17 @@
/* we need clean sockaddr... no ports set */
bzero(&ssrc, sizeof(ssrc));
bzero(&smask, sizeof(smask));
- switch (src->af) {
- case AF_INET:
- ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4;
- ssrc.ss_len = sizeof(struct sockaddr_in);
- ssrc.ss_family = AF_INET;
+ if ((saptr = addr2sa(src, 0)))
+ memcpy(&ssrc, saptr, sizeof(ssrc));
+ switch (src->aid) {
+ case AID_INET:
memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
break;
- case AF_INET6:
- memcpy(&((struct sockaddr_in6 *)&ssrc)->sin6_addr,
- &src->v6, sizeof(struct in6_addr));
- ssrc.ss_len = sizeof(struct sockaddr_in6);
- ssrc.ss_family = AF_INET6;
+ case AID_INET6:
memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
128/8);
break;
- case 0:
+ case AID_UNSPEC:
ssrc.ss_len = sizeof(struct sockaddr);
break;
default:
@@ -107,22 +102,17 @@
bzero(&sdst, sizeof(sdst));
bzero(&dmask, sizeof(dmask));
- switch (dst->af) {
- case AF_INET:
- ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4;
- sdst.ss_len = sizeof(struct sockaddr_in);
- sdst.ss_family = AF_INET;
+ if ((saptr = addr2sa(dst, 0)))
+ memcpy(&sdst, saptr, sizeof(sdst));
+ switch (dst->aid) {
+ case AID_INET:
memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
break;
- case AF_INET6:
- memcpy(&((struct sockaddr_in6 *)&sdst)->sin6_addr,
- &dst->v6, sizeof(struct in6_addr));
- sdst.ss_len = sizeof(struct sockaddr_in6);
- sdst.ss_family = AF_INET6;
+ case AID_INET6:
memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
128/8);
break;
- case 0:
+ case AID_UNSPEC:
sdst.ss_len = sizeof(struct sockaddr);
break;
default:
@@ -135,7 +125,7 @@
smsg.sadb_msg_version = PF_KEY_V2;
smsg.sadb_msg_seq = ++sadb_msg_seq;
smsg.sadb_msg_pid = pid;
- smsg.sadb_msg_len = sizeof(smsg) / 8;
+ smsg.sadb_msg_len = PFKEY_UNIT64(sizeof(smsg));
smsg.sadb_msg_type = mtype;
smsg.sadb_msg_satype = satype;
@@ -143,7 +133,7 @@
case SADB_GETSPI:
bzero(&sa_spirange, sizeof(sa_spirange));
sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
- sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
+ sa_spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(sa_spirange));
sa_spirange.sadb_spirange_min = 0x100;
sa_spirange.sadb_spirange_max = 0xffffffff;
sa_spirange.sadb_spirange_reserved = 0;
@@ -153,11 +143,12 @@
case SADB_DELETE:
bzero(&sa, sizeof(sa));
sa.sadb_sa_exttype = SADB_EXT_SA;
- sa.sadb_sa_len = sizeof(sa) / 8;
+ sa.sadb_sa_len = PFKEY_UNIT64(sizeof(sa));
sa.sadb_sa_replay = 0;
sa.sadb_sa_spi = spi;
sa.sadb_sa_state = SADB_SASTATE_MATURE;
break;
+#if 0
case SADB_X_ADDFLOW:
case SADB_X_DELFLOW:
bzero(&sa_flowtype, sizeof(sa_flowtype));
@@ -172,35 +163,37 @@
sa_protocol.sadb_protocol_direction = 0;
sa_protocol.sadb_protocol_proto = 6;
break;
+#endif
}
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;
+ sa_src.sadb_address_len = PFKEY_UNIT64(sizeof(sa_src) + ROUNDUP(ssrc.ss_len));
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;
+ sa_dst.sadb_address_len = PFKEY_UNIT64(sizeof(sa_dst) + ROUNDUP(sdst.ss_len));
sa.sadb_sa_auth = aalg;
- sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
+ sa.sadb_sa_encrypt = ealg; /* XXX */
switch (mtype) {
case SADB_ADD:
case SADB_UPDATE:
bzero(&sa_akey, sizeof(sa_akey));
sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH;
- sa_akey.sadb_key_len = (sizeof(sa_akey) +
- ((alen + 7) / 8) * 8) / 8;
+ sa_akey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_akey) +
+ (PFKEY_ALIGN8(alen)));
sa_akey.sadb_key_bits = 8 * alen;
bzero(&sa_ekey, sizeof(sa_ekey));
sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
- sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
- ((elen + 7) / 8) * 8) / 8;
+ sa_ekey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_ekey) +
+ (PFKEY_ALIGN8(elen)));
sa_ekey.sadb_key_bits = 8 * elen;
break;
+#if 0
case SADB_X_ADDFLOW:
case SADB_X_DELFLOW:
/* sa_peer always points to the remote machine */
@@ -220,8 +213,8 @@
sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW;
bzero(&smask, sizeof(smask));
- switch (src->af) {
- case AF_INET:
+ switch (src->aid) {
+ case AID_INET:
smask.ss_len = sizeof(struct sockaddr_in);
smask.ss_family = AF_INET;
memset(&((struct sockaddr_in *)&smask)->sin_addr,
@@ -233,7 +226,7 @@
htons(0xffff);
}
break;
- case AF_INET6:
+ case AID_INET6:
smask.ss_len = sizeof(struct sockaddr_in6);
smask.ss_family = AF_INET6;
memset(&((struct sockaddr_in6 *)&smask)->sin6_addr,
@@ -247,8 +240,8 @@
break;
}
bzero(&dmask, sizeof(dmask));
- switch (dst->af) {
- case AF_INET:
+ switch (dst->aid) {
+ case AID_INET:
dmask.ss_len = sizeof(struct sockaddr_in);
dmask.ss_family = AF_INET;
memset(&((struct sockaddr_in *)&dmask)->sin_addr,
@@ -260,7 +253,7 @@
htons(0xffff);
}
break;
- case AF_INET6:
+ case AID_INET6:
dmask.ss_len = sizeof(struct sockaddr_in6);
dmask.ss_family = AF_INET6;
memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
@@ -284,6 +277,7 @@
sa_dmask.sadb_address_len =
(sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
break;
+#endif
}
iov_cnt = 0;
@@ -310,6 +304,7 @@
smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
iov_cnt++;
break;
+#if 0
case SADB_X_ADDFLOW:
/* sa_peer always points to the remote machine */
iov[iov_cnt].iov_base = &sa_peer;
@@ -351,6 +346,7 @@
smsg.sadb_msg_len += sa_dmask.sadb_address_len;
iov_cnt++;
break;
+#endif
}
/* dest addr */
@@ -380,7 +376,7 @@
iov[iov_cnt].iov_len = sizeof(sa_akey);
iov_cnt++;
iov[iov_cnt].iov_base = akey;
- iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(alen);
smsg.sadb_msg_len += sa_akey.sadb_key_len;
iov_cnt++;
}
@@ -390,14 +386,14 @@
iov[iov_cnt].iov_len = sizeof(sa_ekey);
iov_cnt++;
iov[iov_cnt].iov_base = ekey;
- iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(elen);
smsg.sadb_msg_len += sa_ekey.sadb_key_len;
iov_cnt++;
}
break;
}
- len = smsg.sadb_msg_len * 8;
+ len = PFKEY_UNUNIT64(smsg.sadb_msg_len);
do {
n = writev(sd, iov, iov_cnt);
} while (n == -1 && (errno == EAGAIN || errno == EINTR));
@@ -411,6 +407,33 @@
}
int
+pfkey_read(int sd, struct sadb_msg *h)
+{
+ struct sadb_msg hdr;
+
+ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
+ log_warn("pfkey peek");
+ return (-1);
+ }
+
+ /* XXX: Only one message can be outstanding. */
+ if (hdr.sadb_msg_seq == sadb_msg_seq &&
+ hdr.sadb_msg_pid == pid) {
+ if (h)
+ bcopy(&hdr, h, sizeof(hdr));
+ return (0);
+ }
+
+ /* not ours, discard */
+ if (read(sd, &hdr, sizeof(hdr)) == -1) {
+ log_warn("pfkey read");
+ return (-1);
+ }
+
+ return (1);
+}
+
+int
pfkey_reply(int sd, u_int32_t *spip)
{
struct sadb_msg hdr, *msg;
@@ -418,27 +441,17 @@
struct sadb_sa *sa;
u_int8_t *data;
ssize_t len;
+ int rv;
- for (;;) {
- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
- log_warn("pfkey peek");
- return (-1);
- }
-
- if (hdr.sadb_msg_seq == sadb_msg_seq &&
- hdr.sadb_msg_pid == pid)
- break;
-
- /* not ours, discard */
- if (read(sd, &hdr, sizeof(hdr)) == -1) {
- log_warn("pfkey read");
+ do {
+ rv = pfkey_read(sd, &hdr);
+ if (rv == -1)
return (-1);
- }
- }
+ } while (rv);
if (hdr.sadb_msg_errno != 0) {
errno = hdr.sadb_msg_errno;
- if (errno == ESRCH)
+ if (errno == ESRCH || errno == EEXIST)
return (0);
else {
log_warn("pfkey");
@@ -486,13 +499,8 @@
pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
char *key, u_int32_t *spi)
{
- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
- src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
- return (-1);
- if (pfkey_reply(fd, spi) < 0)
- return (-1);
- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0,
- src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0)
+ if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_ADD, 0,
+ src, dst, *spi, SADB_X_AALG_TCP_MD5, keylen, key, SADB_EALG_NONE, 0, NULL, 0, 0) < 0)
return (-1);
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -503,7 +511,7 @@
pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
{
if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
- src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
+ src, dst, *spi, SADB_X_AALG_TCP_MD5, 0, NULL, 0, 0, NULL, 0, 0) < 0)
return (-1);
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -511,37 +519,37 @@
return (0);
}
+#define TCP_SIG_SPI 0x1000
int
pfkey_md5sig_establish(struct peer *p)
{
sleep(1);
- if (!p->auth.spi_out)
- if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_out) == -1)
- return (-1);
- if (!p->auth.spi_in)
- if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_in) == -1)
- return (-1);
+ p->auth.spi_out = htonl(TCP_SIG_SPI);
+ if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &p->auth.spi_out) == -1)
+ return (-1);
+ p->auth.spi_in = htonl(TCP_SIG_SPI);
+ if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &p->auth.spi_out) == -1)
+ return (-1);
p->auth.established = 1;
return (0);
}
+#undef TCP_SIG_SPI
int
pfkey_md5sig_remove(struct peer *p)
{
- if (p->auth.spi_out)
- if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
- &p->auth.spi_out) == -1)
- return (-1);
- if (p->auth.spi_in)
- if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
- &p->auth.spi_in) == -1)
- return (-1);
+ if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
+ &p->auth.spi_out) == -1)
+ return (-1);
+ if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
+ &p->auth.spi_in) == -1)
+ return (-1);
p->auth.established = 0;
return (0);
@@ -550,6 +558,7 @@
int
pfkey_ipsec_establish(struct peer *p)
{
+#if 0
uint8_t satype = SADB_SATYPE_ESP;
switch (p->auth.method) {
@@ -621,6 +630,9 @@
p->auth.established = 1;
return (0);
+#else
+ return (-1);
+#endif
}
int
@@ -660,6 +672,7 @@
break;
}
+#if 0
if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
&p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
return (-1);
@@ -681,6 +694,7 @@
if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
&p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
return (-1);
+#endif
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -715,9 +729,7 @@
int
pfkey_remove(struct peer *p)
{
- if (!p->auth.established)
- return (0);
- else if (p->auth.method == AUTH_MD5SIG)
+ if (p->auth.method == AUTH_MD5SIG)
return (pfkey_md5sig_remove(p));
else
return (pfkey_ipsec_remove(p));
@@ -730,11 +742,9 @@
if (errno == EPROTONOSUPPORT) {
log_warnx("PF_KEY not available, disabling ipsec");
sysdep->no_pfkey = 1;
- return (0);
- } else {
- log_warn("PF_KEY socket");
return (-1);
- }
+ } else
+ fatal("pfkey setup failed");
}
- return (0);
+ return (fd);
}