From b33e46666d390dbbbe4b5434b11df0100da94ed4 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 1 Apr 2019 18:16:54 +0000 Subject: [PATCH] lib: add support for extended TCP MD5 auth MD5 auth on TCP is supported for prefixes in recent versions of Linux; add complementary support for FRR. This is a reworked version of Donald's commit to keep library compatibility and obviate the need for changes in daemons that don't need to support this themselves. Signed-off-by: Quentin Young --- lib/sockopt.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- lib/sockopt.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/lib/sockopt.c b/lib/sockopt.c index ea04f2a43e..89f3d5b594 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -587,10 +587,30 @@ int sockopt_tcp_rtt(int sock) #endif } -int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) +int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen, + const char *password) { +#ifndef HAVE_DECL_TCP_MD5SIG + /* + * We have been asked to enable MD5 auth for an address, but our + * platform doesn't support that + */ + return -2; +#endif + +#ifndef TCP_MD5SIG_EXT + /* + * We have been asked to enable MD5 auth for a prefix, but our platform + * doesn't support that + */ + if (prefixlen > 0) + return -2; +#endif + #if HAVE_DECL_TCP_MD5SIG int ret; + + int optname = TCP_MD5SIG; #ifndef GNU_LINUX /* * XXX Need to do PF_KEY operation here to add/remove an SA entry, @@ -643,12 +663,29 @@ int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) memset(&md5sig, 0, sizeof(md5sig)); memcpy(&md5sig.tcpm_addr, su2, sizeof(*su2)); + md5sig.tcpm_keylen = keylen; if (keylen) memcpy(md5sig.tcpm_key, password, keylen); sockunion_free(susock); + + /* + * Handle support for MD5 signatures on prefixes, if available and + * requested. Technically the #ifdef check below is not needed because + * if prefixlen > 0 and we don't have support for this feature we would + * have already returned by now, but leaving it there to be explicit. + */ +#ifdef TCP_MD5SIG_EXT + if (prefixlen > 0) { + md5sig.tcpm_prefixlen = prefixlen; + md5sig.tcpm_flags = TCP_MD5SIG_FLAG_PREFIX; + optname = TCP_MD5SIG_EXT; + } +#endif /* TCP_MD5SIG_EXT */ + #endif /* GNU_LINUX */ - if ((ret = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, + + if ((ret = setsockopt(sock, IPPROTO_TCP, optname, &md5sig, sizeof md5sig)) < 0) { /* ENOENT is harmless. It is returned when we clear a password @@ -663,7 +700,10 @@ int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) sock, safe_strerror(errno)); } return ret; -#else /* HAVE_TCP_MD5SIG */ - return -2; -#endif /* !HAVE_TCP_MD5SIG */ +#endif /* HAVE_TCP_MD5SIG */ +} + +int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) +{ + return sockopt_tcp_signature_ext(sock, su, 0, password); } diff --git a/lib/sockopt.h b/lib/sockopt.h index 8fa5987cff..732fec92aa 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -100,9 +100,43 @@ extern void sockopt_iphdrincl_swab_htosys(struct ip *iph); extern void sockopt_iphdrincl_swab_systoh(struct ip *iph); extern int sockopt_tcp_rtt(int); + +/* + * TCP MD5 signature option. This option allows TCP MD5 to be enabled on + * addresses. + * + * sock + * Socket to enable option on. + * + * su + * Sockunion specifying address to enable option on. + * + * password + * MD5 auth password + */ extern int sockopt_tcp_signature(int sock, union sockunion *su, const char *password); +/* + * Extended TCP MD5 signature option. This option allows TCP MD5 to be enabled + * on prefixes. + * + * sock + * Socket to enable option on. + * + * su + * Sockunion specifying address (or prefix) to enable option on. + * + * prefixlen + * 0 - su is an address; fall back to non-extended mode + * Else - su is a prefix; prefixlen is the mask length + * + * password + * MD5 auth password + */ +extern int sockopt_tcp_signature_ext(int sock, union sockunion *su, + uint16_t prefixlen, const char *password); + #ifdef __cplusplus } #endif -- 2.39.5