diff --git a/doc/bird.sgml b/doc/bird.sgml index 04db44b5..b864fd58 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -5729,7 +5729,10 @@ protocol rpki [<name>] { refresh [keep] <num>; retry [keep] <num>; expire [keep] <num>; - transport tcp; + transport tcp { + authentication none|md5; + password "<text>"; + }; transport ssh { bird private key "</path/to/id_rsa>"; remote public key "</path/to/known_host>"; @@ -5785,15 +5788,27 @@ specify both channels. instead. This may be useful for implementing loose RPKI check for blackholes. Default: disabled. - transport tcp Unprotected transport over TCP. It's a default - transport. Should be used only on secure private networks. - Default: tcp + transport tcp { Transport over + TCP, it's the default transport. Cannot be combined with a SSH transport. + Default: TCP, no authentication. transport ssh { It enables a SSHv2 transport encryption. Cannot be combined with a TCP transport. Default: off +TCP transport options +

+ + authentication none|md5 + Select authentication method to be used. ). + Default: no authentication. + + password "text" + Use this password for TCP-MD5 authentication of the RPKI-To-Router session. + + SSH transport options

diff --git a/proto/rpki/config.Y b/proto/rpki/config.Y index dc5df048..5dc27e53 100644 --- a/proto/rpki/config.Y +++ b/proto/rpki/config.Y @@ -13,6 +13,7 @@ CF_HDR CF_DEFINES #define RPKI_CFG ((struct rpki_config *) this_proto) +#define RPKI_TR_TCP_CFG ((struct rpki_tr_tcp_config *) RPKI_CFG->tr_config.spec) #define RPKI_TR_SSH_CFG ((struct rpki_tr_ssh_config *) RPKI_CFG->tr_config.spec) static void @@ -32,7 +33,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, NONE, MD5, PASSWORD) %type rpki_keep_interval @@ -109,7 +111,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 ; @@ -120,6 +122,28 @@ 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 NONE { RPKI_TR_TCP_CFG->auth_type = RPKI_TCP_AUTH_NONE; } + | AUTHENTICATION MD5 { RPKI_TR_TCP_CFG->auth_type = RPKI_TCP_AUTH_MD5; } + | PASSWORD text { RPKI_TR_TCP_CFG->password = $2; } + ; + +rpki_transport_tcp_check: +{ + if (!RPKI_TR_TCP_CFG->auth_type != !RPKI_TR_TCP_CFG->password) + cf_error("Authentication and password options should be used together"); +}; + rpki_transport_ssh_init: { #if HAVE_LIBSSH diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 4c19321f..2c8ac44c 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -726,6 +726,24 @@ rpki_reconfigure_cache(struct rpki_proto *p UNUSED, struct rpki_cache *cache, st try_reset = 1; } + if (new->tr_config.type == RPKI_TR_TCP) + { + struct rpki_tr_tcp_config *tcp_old = (void *) old->tr_config.spec; + struct rpki_tr_tcp_config *tcp_new = (void *) new->tr_config.spec; + + if (tcp_old->auth_type != tcp_new->auth_type) + { + CACHE_TRACE(D_EVENTS, cache, "Authentication type changed"); + return NEED_RESTART; + } + + if (bstrcmp(tcp_old->password, tcp_new->password)) + { + CACHE_TRACE(D_EVENTS, cache, "MD5 password changed"); + return NEED_RESTART; + } + } + #if HAVE_LIBSSH else if (new->tr_config.type == RPKI_TR_SSH) { @@ -883,8 +901,12 @@ rpki_show_proto_info(struct proto *P) default_port = RPKI_SSH_PORT; break; #endif - case RPKI_TR_TCP: - transport_name = "Unprotected over TCP"; + case RPKI_TR_TCP:; + struct rpki_tr_tcp_config *tcp_cf = (void *) cf->tr_config.spec; + if (tcp_cf->auth_type == RPKI_TCP_AUTH_MD5) + transport_name = "TCP-MD5"; + else + transport_name = "Unprotected over TCP"; default_port = RPKI_TCP_PORT; break; }; diff --git a/proto/rpki/tcp_transport.c b/proto/rpki/tcp_transport.c index ebb8030f..da0a5927 100644 --- a/proto/rpki/tcp_transport.c +++ b/proto/rpki/tcp_transport.c @@ -24,10 +24,16 @@ static int rpki_tr_tcp_open(struct rpki_tr_sock *tr) { + struct rpki_cache *cache = tr->cache; + struct rpki_config *cf = (void *) cache->p->p.cf; + struct rpki_tr_tcp_config *tcp_cf = (void *) cf->tr_config.spec; sock *sk = tr->sk; sk->type = SK_TCP_ACTIVE; + if (tcp_cf->auth_type == RPKI_TCP_AUTH_MD5) + sk->password = tcp_cf->password; + if (sk_open(sk, tr->cache->p->p.loop) != 0) return RPKI_TR_ERROR; diff --git a/proto/rpki/transport.h b/proto/rpki/transport.h index bb8d41eb..10e9acb7 100644 --- a/proto/rpki/transport.h +++ b/proto/rpki/transport.h @@ -56,6 +56,12 @@ enum rpki_tr_type { #endif }; +/* TCP authentication types */ +enum rpki_tcp_auth { + RPKI_TCP_AUTH_NONE, + RPKI_TCP_AUTH_MD5 +}; + /* Common configure structure for transports */ struct rpki_tr_config { enum rpki_tr_type type; /* RPKI_TR_TCP or RPKI_TR_SSH */ @@ -63,7 +69,8 @@ struct rpki_tr_config { }; struct rpki_tr_tcp_config { - /* No internal configuration data */ + enum rpki_tcp_auth auth_type; /* Authentication type */ + const char *password; /* Password used for authentication */ }; struct rpki_tr_ssh_config {