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.
This commit is contained in:
parent
22c3cf955d
commit
757cab18d6
6 changed files with 62 additions and 44 deletions
|
@ -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_setup_broadcast(sock *s);
|
||||||
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
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_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_ipv6_checksum(sock *s, int offset);
|
||||||
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
||||||
void sk_log_error(sock *s, const char *p);
|
void sk_log_error(sock *s, const char *p);
|
||||||
|
|
|
@ -247,8 +247,17 @@ bgp_setup_auth(struct bgp_proto *p, int enable)
|
||||||
{
|
{
|
||||||
if (p->cf->password)
|
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,
|
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);
|
enable ? p->cf->password : NULL, p->cf->setkey);
|
||||||
|
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
|
|
|
@ -63,7 +63,7 @@ setkey_send(struct sadb_msg *msg, uint len)
|
||||||
* operations to implement replace.
|
* operations to implement replace.
|
||||||
*/
|
*/
|
||||||
static int
|
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;
|
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_len = PFKEY_UNIT64(len);
|
||||||
saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
|
saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
|
||||||
saddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
|
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);
|
memcpy(pos + sizeof(struct sadb_address), &src->sa, src->sa.sa_len);
|
||||||
pos += 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_len = PFKEY_UNIT64(len);
|
||||||
daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
|
daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
|
||||||
daddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
|
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);
|
memcpy(pos + sizeof(struct sadb_address), &dst->sa, dst->sa.sa_len);
|
||||||
pos += 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
|
* Manipulation with the IPsec SA/SP database
|
||||||
*/
|
*/
|
||||||
static int
|
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 src, dst;
|
||||||
sockaddr_fill(&src, s->af, local, ifa, 0);
|
sockaddr_fill(&src, s->af, local, ifa, 0);
|
||||||
sockaddr_fill(&dst, s->af, remote, 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)
|
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)
|
if (len > TCP_KEYLEN_MAX)
|
||||||
ERR_MSG("The password for TCP MD5 Signature is too long");
|
ERR_MSG("The password for TCP MD5 Signature is too long");
|
||||||
|
|
||||||
if ((setkey_md5(&src, &dst, pxlen, passwd, SADB_ADD) < 0) ||
|
if ((setkey_md5(&src, slen, &dst, dlen, passwd, SADB_ADD) < 0) ||
|
||||||
(setkey_md5(&dst, &src, pxlen, 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");
|
ERR_MSG("Cannot add TCP-MD5 password into the IPsec SA/SP database");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((setkey_md5(&src, &dst, pxlen, NULL, SADB_DELETE) < 0) ||
|
if ((setkey_md5(&src, slen, &dst, dlen, NULL, SADB_DELETE) < 0) ||
|
||||||
(setkey_md5(&dst, &src, pxlen, 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");
|
ERR_MSG("Cannot delete TCP-MD5 password from the IPsec SA/SP database");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -210,11 +210,11 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
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
|
#ifdef USE_MD5SIG_SETKEY
|
||||||
if (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;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -6,35 +6,28 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* 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
|
#ifndef IPV6_MINHOPCOUNT
|
||||||
#define IPV6_MINHOPCOUNT 73
|
#define IPV6_MINHOPCOUNT 73
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TCP_MD5SIG_EXT
|
||||||
#ifndef TCP_MD5SIG
|
#define TCP_MD5SIG_EXT 32
|
||||||
|
|
||||||
#define TCP_MD5SIG 14
|
|
||||||
#define TCP_MD5SIG_MAXKEYLEN 80
|
|
||||||
|
|
||||||
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) */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TCP_MD5SIG_FLAG_PREFIX
|
||||||
|
#define TCP_MD5SIG_FLAG_PREFIX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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) */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Linux does not care if sa_len is larger than needed */
|
/* Linux does not care if sa_len is larger than needed */
|
||||||
#define SA_LEN(x) sizeof(sockaddr)
|
#define SA_LEN(x) sizeof(sockaddr)
|
||||||
|
@ -169,9 +162,9 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
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));
|
memset(&md5, 0, sizeof(md5));
|
||||||
sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
|
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);
|
memcpy(&md5.tcpm_key, passwd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
|
if (pxlen < 0)
|
||||||
{
|
{
|
||||||
if (errno == ENOPROTOOPT)
|
if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
|
||||||
ERR_MSG("Kernel does not support TCP MD5 signatures");
|
if (errno == ENOPROTOOPT)
|
||||||
else
|
ERR_MSG("Kernel does not support TCP MD5 signatures");
|
||||||
ERR("TCP_MD5SIG");
|
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;
|
return 0;
|
||||||
|
|
|
@ -1442,7 +1442,7 @@ sk_open(sock *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->password)
|
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;
|
goto err;
|
||||||
|
|
||||||
switch (s->type)
|
switch (s->type)
|
||||||
|
|
Loading…
Reference in a new issue