summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2020-02-27 16:16:48 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2020-02-27 17:29:17 +0100
commit757cab18d6427d9246618ce48c158f2b05183838 (patch)
tree3dc5a4d2923be9e5e54f374f9788635428269423
parent22c3cf955dbbb65aa29e322efa70dabb749f0232 (diff)
BGP: Support for MD5SIG together with remote range
When dynamic BGP with remote range is configured, MD5SIG needs to use newer socket option (TCP_MD5SIG_EXT) to specify remote addres range for listening socket. Thanks to Adam KuĊ‚agowski for the suggestion.
-rw-r--r--lib/socket.h2
-rw-r--r--proto/bgp/bgp.c11
-rw-r--r--sysdep/bsd/setkey.h20
-rw-r--r--sysdep/bsd/sysio.h4
-rw-r--r--sysdep/linux/sysio.h63
-rw-r--r--sysdep/unix/io.c2
6 files changed, 60 insertions, 42 deletions
diff --git a/lib/socket.h b/lib/socket.h
index 03c15dcd..f2b0c042 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -106,7 +106,7 @@ int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface
int sk_setup_broadcast(sock *s);
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
-int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey);
+int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, char *passwd, int setkey);
int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp6_filter(sock *s, int p1, int p2);
void sk_log_error(sock *s, const char *p);
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 83105a68..b9ed6c78 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -247,8 +247,17 @@ bgp_setup_auth(struct bgp_proto *p, int enable)
{
if (p->cf->password)
{
+ ip_addr prefix = p->cf->remote_ip;
+ int pxlen = -1;
+
+ if (p->cf->remote_range)
+ {
+ prefix = net_prefix(p->cf->remote_range);
+ pxlen = net_pxlen(p->cf->remote_range);
+ }
+
int rv = sk_set_md5_auth(p->sock->sk,
- p->cf->local_ip, p->cf->remote_ip, p->cf->iface,
+ p->cf->local_ip, prefix, pxlen, p->cf->iface,
enable ? p->cf->password : NULL, p->cf->setkey);
if (rv < 0)
diff --git a/sysdep/bsd/setkey.h b/sysdep/bsd/setkey.h
index 8a1bc9ad..40564cf1 100644
--- a/sysdep/bsd/setkey.h
+++ b/sysdep/bsd/setkey.h
@@ -63,7 +63,7 @@ setkey_send(struct sadb_msg *msg, uint len)
* operations to implement replace.
*/
static int
-setkey_md5(sockaddr *src, sockaddr *dst, uint pxlen, char *passwd, uint type)
+setkey_md5(sockaddr *src, uint slen, sockaddr *dst, uint dlen, char *passwd, uint type)
{
uint passwd_len = passwd ? strlen(passwd) : 0;
@@ -122,7 +122,7 @@ setkey_md5(sockaddr *src, sockaddr *dst, uint pxlen, char *passwd, uint type)
saddr->sadb_address_len = PFKEY_UNIT64(len);
saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
saddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
- saddr->sadb_address_prefixlen = pxlen;
+ saddr->sadb_address_prefixlen = slen;
memcpy(pos + sizeof(struct sadb_address), &src->sa, src->sa.sa_len);
pos += len;
@@ -132,7 +132,7 @@ setkey_md5(sockaddr *src, sockaddr *dst, uint pxlen, char *passwd, uint type)
daddr->sadb_address_len = PFKEY_UNIT64(len);
daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
daddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
- daddr->sadb_address_prefixlen = pxlen;
+ daddr->sadb_address_prefixlen = dlen;
memcpy(pos + sizeof(struct sadb_address), &dst->sa, dst->sa.sa_len);
pos += len;
@@ -146,13 +146,15 @@ setkey_md5(sockaddr *src, sockaddr *dst, uint pxlen, char *passwd, uint type)
* Manipulation with the IPsec SA/SP database
*/
static int
-sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd)
+sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, char *passwd)
{
sockaddr src, dst;
sockaddr_fill(&src, s->af, local, ifa, 0);
sockaddr_fill(&dst, s->af, remote, ifa, 0);
- uint pxlen = (s->af == AF_INET) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
+ uint maxlen = (s->af == AF_INET) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
+ uint slen = maxlen;
+ uint dlen = (pxlen < 0) ? maxlen : pxlen;
if (passwd && *passwd)
{
@@ -160,14 +162,14 @@ sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, struct iface *ifa,
if (len > TCP_KEYLEN_MAX)
ERR_MSG("The password for TCP MD5 Signature is too long");
- if ((setkey_md5(&src, &dst, pxlen, passwd, SADB_ADD) < 0) ||
- (setkey_md5(&dst, &src, pxlen, passwd, SADB_ADD) < 0))
+ if ((setkey_md5(&src, slen, &dst, dlen, passwd, SADB_ADD) < 0) ||
+ (setkey_md5(&dst, dlen, &src, slen, passwd, SADB_ADD) < 0))
ERR_MSG("Cannot add TCP-MD5 password into the IPsec SA/SP database");
}
else
{
- if ((setkey_md5(&src, &dst, pxlen, NULL, SADB_DELETE) < 0) ||
- (setkey_md5(&dst, &src, pxlen, NULL, SADB_DELETE) < 0))
+ if ((setkey_md5(&src, slen, &dst, dlen, NULL, SADB_DELETE) < 0) ||
+ (setkey_md5(&dst, dlen, &src, slen, NULL, SADB_DELETE) < 0))
ERR_MSG("Cannot delete TCP-MD5 password from the IPsec SA/SP database");
}
return 0;
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h
index a5d161ba..929bfaf6 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -210,11 +210,11 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
#endif
int
-sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
+sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, int pxlen UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
{
#ifdef USE_MD5SIG_SETKEY
if (setkey)
- if (sk_set_md5_in_sasp_db(s, local, remote, ifa, passwd) < 0)
+ if (sk_set_md5_in_sasp_db(s, local, remote, pxlen, ifa, passwd) < 0)
return -1;
#endif
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index b1cc25dc..8c3efd6e 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -6,35 +6,28 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
-
-#ifndef IP_MINTTL
-#define IP_MINTTL 21
-#endif
-
-#ifndef IPV6_TCLASS
-#define IPV6_TCLASS 67
-#endif
-
#ifndef IPV6_MINHOPCOUNT
#define IPV6_MINHOPCOUNT 73
#endif
+#ifndef TCP_MD5SIG_EXT
+#define TCP_MD5SIG_EXT 32
+#endif
-#ifndef TCP_MD5SIG
-
-#define TCP_MD5SIG 14
-#define TCP_MD5SIG_MAXKEYLEN 80
+#ifndef TCP_MD5SIG_FLAG_PREFIX
+#define TCP_MD5SIG_FLAG_PREFIX 1
+#endif
-struct tcp_md5sig {
- struct sockaddr_storage tcpm_addr; /* address associated */
- u16 __tcpm_pad1; /* zero */
- u16 tcpm_keylen; /* key length */
- u32 __tcpm_pad2; /* zero */
- u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
+/* We redefine the tcp_md5sig structure with different name to avoid collision with older headers */
+struct tcp_md5sig_ext {
+ struct sockaddr_storage tcpm_addr; /* Address associated */
+ u8 tcpm_flags; /* Extension flags */
+ u8 tcpm_prefixlen; /* Address prefix */
+ u16 tcpm_keylen; /* Key length */
+ u32 __tcpm_pad2; /* Zero */
+ u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary) */
};
-#endif
-
/* Linux does not care if sa_len is larger than needed */
#define SA_LEN(x) sizeof(sockaddr)
@@ -169,9 +162,9 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
*/
int
-sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED)
+sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct iface *ifa, char *passwd, int setkey UNUSED)
{
- struct tcp_md5sig md5;
+ struct tcp_md5sig_ext md5;
memset(&md5, 0, sizeof(md5));
sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
@@ -187,12 +180,26 @@ sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa
memcpy(&md5.tcpm_key, passwd, len);
}
- if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
+ if (pxlen < 0)
{
- if (errno == ENOPROTOOPT)
- ERR_MSG("Kernel does not support TCP MD5 signatures");
- else
- ERR("TCP_MD5SIG");
+ if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG");
+ }
+ else
+ {
+ md5.tcpm_flags = TCP_MD5SIG_FLAG_PREFIX;
+ md5.tcpm_prefixlen = pxlen;
+
+ if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG_EXT, &md5, sizeof(md5)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support extended TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG_EXT");
+ }
}
return 0;
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 5e4d9573..f4e45a5f 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -1442,7 +1442,7 @@ sk_open(sock *s)
}
if (s->password)
- if (sk_set_md5_auth(s, s->saddr, s->daddr, s->iface, s->password, 0) < 0)
+ if (sk_set_md5_auth(s, s->saddr, s->daddr, -1, s->iface, s->password, 0) < 0)
goto err;
switch (s->type)