[patch] Add TCP-MD5 authentication option for RPKI protocol

Job Snijders job at fastly.com
Wed Oct 2 19:56:50 CEST 2024


Dear Ondrej,

On Wed, Oct 02, 2024 at 03:40:11AM +0200, Ondrej Zajicek wrote:
> Please, use sub-block here:
> 
> transport tcp {
>   authentication md5;
>   password "test";
> };

Sure

> > +  if (old->password != new->password)
> > +  {
> > +    CACHE_TRACE(D_EVENTS, cache, "MD5 authentication changed");
> > +    return NEED_RESTART;
> > +  }
> 
> I think you need bstrcmp(old->password, new->password) here.

ah, yes. Thanks for catching that :-)

How about the below?

diff --git a/doc/bird.sgml b/doc/bird.sgml
index e2050c13..df086445 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -5735,7 +5735,10 @@ protocol rpki [<name>] {
         refresh [keep] <num>;
         retry [keep] <num>;
         expire [keep] <num>;
-        transport tcp;
+        transport tcp {
+                authentication md5;
+                password "<text>";
+        };
         transport ssh {
                 bird private key "</path/to/id_rsa>";
                 remote public key "</path/to/known_host>";
@@ -5791,15 +5794,26 @@ specify both channels.
 	instead. This may be useful for implementing loose RPKI check for
 	blackholes. Default: disabled.
 
-        <tag>transport tcp</tag> Unprotected transport over TCP. It's a default
-        transport. Should be used only on secure private networks.
-        Default: tcp
+        <tag>transport tcp { <m/TCP transport options.../ }</tag> Transport over
+        TCP, it's the default transport. Cannot be combined with a SSH transport.
+        Default: TCP, no authentication.
 
         <tag>transport ssh { <m/SSH transport options.../ }</tag> It enables a
         SSHv2 transport encryption. Cannot be combined with a TCP transport.
         Default: off
 </descrip>
 
+<sect3>TCP transport options
+<p>
+<descrip>
+	<tag>authentication md5</tag>
+        Enable TCP-MD5 authentication (<rfc id="2385">) on the TCP transport.
+
+	<tag>password "<m>text</m>"</tag>
+	Use this password for TCP-MD5 authentication of the RPKI-To-Router session.
+	Default: no authentication.
+</descrip>
+
 <sect3>SSH transport options
 <p>
 <descrip>
diff --git a/proto/rpki/config.Y b/proto/rpki/config.Y
index 769ebb2c..56dfe966 100644
--- a/proto/rpki/config.Y
+++ b/proto/rpki/config.Y
@@ -32,7 +32,8 @@ rpki_check_unused_transport(void)
 CF_DECLS
 
 CF_KEYWORDS(RPKI, REMOTE, BIRD, PRIVATE, PUBLIC, KEY, TCP, SSH, TRANSPORT, USER,
-	    RETRY, REFRESH, EXPIRE, KEEP, IGNORE, MAX, LENGTH, LOCAL, ADDRESS)
+	    RETRY, REFRESH, EXPIRE, KEEP, IGNORE, MAX, LENGTH, LOCAL, ADDRESS,
+	    AUTHENTICATION, MD5, PASSWORD)
 
 %type <i> rpki_keep_interval
 
@@ -108,7 +109,7 @@ rpki_cache_addr: text_or_ipa
 };
 
 rpki_transport:
-   TCP rpki_transport_tcp_init
+   TCP rpki_transport_tcp_init rpki_transport_tcp_opts_list rpki_transport_tcp_check
  | SSH rpki_transport_ssh_init '{' rpki_transport_ssh_opts '}' rpki_transport_ssh_check
  ;
 
@@ -119,6 +120,29 @@ rpki_transport_tcp_init:
   RPKI_CFG->tr_config.type = RPKI_TR_TCP;
 };
 
+rpki_transport_tcp_opts_list:
+    /* empty */
+  | '{' rpki_transport_tcp_opts '}'
+  ;
+
+rpki_transport_tcp_opts:
+   /* empty */
+ | rpki_transport_tcp_opts rpki_transport_tcp_item ';'
+ ;
+
+rpki_transport_tcp_item:
+   AUTHENTICATION MD5     { RPKI_CFG->authtype = RPKI_TRANSPORT_TCP_MD5; }
+ | PASSWORD text          { RPKI_CFG->password = $2; }
+ ;
+
+rpki_transport_tcp_check:
+{
+  if (RPKI_CFG->password != NULL && RPKI_CFG->authtype != ALG_MD5)
+    cf_error("Only TCP-MD5 authentication is supported for TCP transport");
+  if (RPKI_CFG->authtype == ALG_MD5 && RPKI_CFG->password == NULL)
+    cf_error("TCP-MD5 authentication password must be set");
+};
+
 rpki_transport_ssh_init:
 {
 #if HAVE_LIBSSH
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index 4ec48e3b..a5ff5ff1 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -673,6 +673,12 @@ rpki_reconfigure_cache(struct rpki_proto *p UNUSED, struct rpki_cache *cache, st
     return NEED_RESTART;
   }
 
+  if (bstrcmp(old->password, new->password))
+  {
+    CACHE_TRACE(D_EVENTS, cache, "MD5 authentication changed");
+    return NEED_RESTART;
+  }
+
   if (old->tr_config.type != new->tr_config.type)
   {
     CACHE_TRACE(D_EVENTS, cache, "Transport type changed");
@@ -843,7 +849,10 @@ rpki_show_proto_info(struct proto *P)
       break;
 #endif
     case RPKI_TR_TCP:
-      transport_name = "Unprotected over TCP";
+      if (cf->authtype == RPKI_TRANSPORT_TCP_MD5)
+        transport_name = "TCP-MD5";
+      else
+        transport_name = "Unprotected over TCP";
       default_port = RPKI_TCP_PORT;
       break;
     };
diff --git a/proto/rpki/rpki.h b/proto/rpki/rpki.h
index e67eb0e3..0905e271 100644
--- a/proto/rpki/rpki.h
+++ b/proto/rpki/rpki.h
@@ -31,6 +31,10 @@
 #define RPKI_VERSION_1		1
 #define RPKI_MAX_VERSION 	RPKI_VERSION_1
 
+enum transportauth {
+  RPKI_TRANSPORT_TCP_PLAIN,
+  RPKI_TRANSPORT_TCP_MD5
+};
 
 /*
  * 	RPKI Cache
@@ -127,6 +131,8 @@ struct rpki_config {
   u8 keep_retry_interval:1;		/* Do not overwrite retry interval by cache server update */
   u8 keep_expire_interval:1;		/* Do not overwrite expire interval by cache server update */
   u8 ignore_max_length:1;		/* Ignore received max length and use MAX_PREFIX_LENGTH instead */
+  enum transportauth authtype;		/* Authentication type */
+  const char *password;			/* Password used for authentication */
 };
 
 void rpki_check_config(struct rpki_config *cf);
diff --git a/proto/rpki/transport.c b/proto/rpki/transport.c
index 26571977..9932ad32 100644
--- a/proto/rpki/transport.c
+++ b/proto/rpki/transport.c
@@ -88,6 +88,9 @@ rpki_tr_open(struct rpki_tr_sock *tr)
   sk->tos = IP_PREC_INTERNET_CONTROL;
   sk->vrf = cache->p->p.vrf;
 
+  if (cf->tr_config.type == RPKI_TR_TCP && cf->authtype == RPKI_TRANSPORT_TCP_MD5 && cf->password != NULL)
+    sk->password = cf->password;
+
   if (ipa_zero(sk->daddr) && sk->host)
   {
     const char *err_msg;


More information about the Bird-users mailing list