Skip to content

Commit

Permalink
lib: add support for extended TCP MD5 auth
Browse files Browse the repository at this point in the history
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 <qlyoung@cumulusnetworks.com>
  • Loading branch information
qlyoung committed Apr 16, 2019
1 parent 0697abe commit b33e466
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
50 changes: 45 additions & 5 deletions lib/sockopt.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
34 changes: 34 additions & 0 deletions lib/sockopt.h
Expand Up @@ -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
Expand Down

0 comments on commit b33e466

Please sign in to comment.