]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: add support for extended TCP MD5 auth
authorQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 1 Apr 2019 18:16:54 +0000 (18:16 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 16 Apr 2019 15:26:20 +0000 (15:26 +0000)
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>
lib/sockopt.c
lib/sockopt.h

index ea04f2a43ee93ac2c180021f63cfeb9eeae3ad8a..89f3d5b594ed37ee3a018c206611a2453698c65c 100644 (file)
@@ -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);
 }
index 8fa5987cff967c6097820a79d3f13b40e0dddff7..732fec92aad1b7f1105b0990e4df1e20b9e8507f 100644 (file)
@@ -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