]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
RPKI: Accept and save BGPsec Router Keys from RPKI
authorPavel Tvrdik <pawel.tvrdik@gmail.com>
Thu, 26 May 2016 11:45:47 +0000 (13:45 +0200)
committerPavel Tvrdik <pawel.tvrdik@gmail.com>
Thu, 26 May 2016 11:57:31 +0000 (13:57 +0200)
Adds support for receiving Router Key PDUs, saving it to disk. The path
save repository is configurable by ./configure or BIRD's configuration file.

Makefile.in
conf/conf.c
conf/conf.h
configure.in
nest/config.Y
proto/rpki/config.Y
proto/rpki/packets.c
proto/rpki/rpki.h

index 0f3cb36f6b432010d9c229bcc2e529963fb28d01..552e7a53650632033a3b3bc1cee7b643f556a489 100644 (file)
@@ -108,6 +108,7 @@ $(objdir)/sysdep/paths.h: Makefile
        echo  >$@ "/* Generated by Makefile, don't edit manually! */"
        echo >>$@ "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
        echo >>$@ "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
+       echo >>$@ "#define PATH_RPKI_STATE_DIR \"@RPKI_STATE_DIR@\""
        if test -n "@iproutedir@" ; then echo >>$@ "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
 
 # Finally include the computed dependencies
index 8d4d28e38e46616eef68ac4fc62b9025aa463f6e..9e9048589bfc89ba1af2f9a1e6ec7581e5eb4eed 100644 (file)
@@ -104,6 +104,7 @@ config_alloc(byte *name)
   c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
   c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
   c->gr_wait = DEFAULT_GR_WAIT;
+  c->rpki_state_dir = PATH_RPKI_STATE_DIR;
 
   return c;
 }
index 03fecd32a024ad7900bd05443ebba065ff58e718..421e2b4589d3b15214869729c4e76ee8730b7706 100644 (file)
@@ -31,6 +31,7 @@ struct config {
   ip_addr listen_bgp_addr;             /* Listening BGP socket should use this address */
   unsigned listen_bgp_port;            /* Listening BGP socket should use this port (0 is default) */
   u32 listen_bgp_flags;                        /* Listening BGP socket should use these flags */
+  const char *rpki_state_dir;          /* File path to save Router Keys for RPKI */
   unsigned proto_default_debug;                /* Default protocol debug mask */
   unsigned proto_default_mrtdump;      /* Default protocol mrtdump mask */
   struct timeformat tf_route;          /* Time format for 'show route' */
index e5e43e1b7ebfece250f31312bfceaa39a544ddca..b7dd0420869af093daaa42c28dc194605ec38de1 100644 (file)
@@ -39,12 +39,15 @@ AC_SUBST(runtimedir)
 if test "$enable_debug" = yes ; then
        CONFIG_FILE="bird.conf"
        CONTROL_SOCKET="bird.ctl"
+       RPKI_STATE_DIR="rpki"
 else
        CONFIG_FILE="\$(sysconfdir)/bird.conf"
        CONTROL_SOCKET="$runtimedir/bird.ctl"
+       RPKI_STATE_DIR="\$(localstatedir)/rpki"
 fi
 AC_SUBST(CONFIG_FILE)
 AC_SUBST(CONTROL_SOCKET)
+AC_SUBST(RPKI_STATE_DIR)
 
 AC_SEARCH_LIBS(clock_gettime, [c rt posix4], ,
        AC_MSG_ERROR([[Function clock_gettime not available.]]))
index 94a676705f518f6960575587733755a34c740e70..04c4415e352ac91ee59d5f5e757cd753800658f6 100644 (file)
@@ -457,7 +457,10 @@ password_item_params:
  | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
  ;
 
+/* Overwrite RPKI State Dir for BGPSEC Router Keys */
 
+CF_ADDTO(conf, rpki_state_dir)
+rpki_state_dir: RPKI STATE DIR text ';' { new_config->rpki_state_dir = $4; }
 
 /* Core commands */
 CF_CLI_HELP(SHOW, ..., [[Show status information]])
index 0811649e84749efe9b6ca30acc058a9eb5967bea..a0af7748e22e1155ad933aeb056ee21887b6a554 100644 (file)
@@ -24,7 +24,7 @@ rpki_check_unused_hostname(void)
 CF_DECLS
 
 CF_KEYWORDS(RPKI, REMOTE, BIRD, PRIVATE, PUBLIC, KEY, SSH, ENCRYPTION, USER,
-           RETRY, REFRESH, EXPIRE)
+           RETRY, REFRESH, EXPIRE, STATE, DIR)
 
 CF_GRAMMAR
 
index 839cddd32341e69789fd55447f1ffc7c3466eb78..f6a5f77bc2e6d30bb0e102739d8ed82a0f29eb52 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <fcntl.h>
 
 #undef LOCAL_DEBUG
 
@@ -142,6 +143,17 @@ struct pdu_error {
   uint8_t rest[];
 };
 
+struct pdu_router_key {
+    uint8_t ver;
+    uint8_t type;
+    uint8_t flags;
+    uint8_t zero;
+    uint32_t len;
+    uint8_t ski[RPKI_SKI_SIZE];
+    uint32_t asn;
+    uint8_t spki[RPKI_SPKI_SIZE];
+};
+
 struct pdu_reset_query {
   uint8_t ver;
   uint8_t type;
@@ -328,6 +340,12 @@ rpki_pdu_body_to_host_byte_order(void *pdu)
   }
 
   case ROUTER_KEY:
+  {
+    struct pdu_router_key *rk = pdu;
+    rk->asn = ntohl(rk->asn);
+    break;
+  }
+
   case SERIAL_QUERY:
   case RESET_QUERY:
   case CACHE_RESPONSE:
@@ -373,6 +391,16 @@ rpki_log_packet(struct rpki_cache *cache, const void *pdu, const size_t len, con
     break;
   }
 
+  case ROUTER_KEY:
+  {
+    const struct pdu_router_key *rk = pdu;
+    bsnprintf(detail, sizeof(detail), "(AS%u %02x", rk->asn, rk->ski[0]);
+    for (const u8 *x = &rk->ski[1]; x < &rk->ski[RPKI_SKI_SIZE]; x++)
+      bsnprintf(detail+strlen(detail), sizeof(detail)-strlen(detail), ":%02x", *x);
+    bsnprintf(detail+strlen(detail), sizeof(detail)-strlen(detail), ")");
+    break;
+  }
+
   default:
     *detail = '\0';
   }
@@ -741,6 +769,43 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const void *pdu)
   return RPKI_SUCCESS;
 }
 
+static void
+rpki_handle_router_key_pdu(struct rpki_cache *cache, const struct pdu_router_key *pdu)
+{
+  char file_name[4096]; /* PATH_MAX? */
+  char ski_hex[41];
+  const char *state_dir = config->rpki_state_dir;
+  int i;
+  int fd = -1;
+
+  for (i = 0; i < 20; i++)
+    bsnprintf(ski_hex + i*2, sizeof(ski_hex) - i*2, "%02X", pdu->ski[i]);
+
+  /* Check buffer size */
+  size_t req_size = strlen(state_dir) + 2*sizeof(pdu->ski) + 2 + strlen(RPKI_ROUTER_KEY_EXT);
+  if (req_size >= sizeof(file_name))
+  {
+    CACHE_TRACE(D_EVENTS, cache, "Buffer too small for %s/%u.%s" RPKI_ROUTER_KEY_EXT, state_dir, pdu->asn, ski_hex);
+    return;
+  }
+
+  bsnprintf(file_name, sizeof(file_name), "%s/%u.%s" RPKI_ROUTER_KEY_EXT, state_dir, pdu->asn, ski_hex);
+
+  fd = open(file_name, O_WRONLY|O_CREAT, 0664);
+  if (fd < 0)
+  {
+    CACHE_TRACE(D_EVENTS, cache, "Cannot open file %s for write router key", file_name);
+    return;
+  }
+
+  if (write(fd, pdu->spki, RPKI_SPKI_SIZE) < 0)
+    CACHE_TRACE(D_EVENTS, cache, "Cannot write into %s", file_name);
+  else
+    CACHE_TRACE(D_EVENTS, cache, "Wrote router key into file %s", file_name);
+
+  close(fd);
+}
+
 static uint
 rpki_check_interval(struct rpki_cache *cache, const char *(check_fn)(uint), uint interval)
 {
@@ -837,6 +902,10 @@ rpki_rx_packet(struct rpki_cache *cache, void *pdu, uint len)
     rpki_handle_prefix_pdu(cache, pdu);
     break;
 
+  case ROUTER_KEY:
+    rpki_handle_router_key_pdu(cache, pdu);
+    break;
+
   case END_OF_DATA:
     rpki_handle_end_of_data_pdu(cache, pdu);
     break;
@@ -853,7 +922,6 @@ rpki_rx_packet(struct rpki_cache *cache, void *pdu, uint len)
     rpki_handle_error_pdu(cache, pdu);
     break;
 
-  case ROUTER_KEY:
   default:
     CACHE_TRACE(D_PACKETS, cache, "Received unsupported type of RPKI PDU: %u", type);
   };
index c0115a92a659c8d9def6695789b37385e63f94a5..7ba14cd3f79c0a25bb88a17b0278a3fa5ea76440 100644 (file)
 #define RPKI_MIN_VERSION               0
 #define RPKI_MAX_VERSION               1
 
+#define RPKI_SKI_SIZE                  20
+#define RPKI_SPKI_SIZE                         91
+#define RPKI_ROUTER_KEY_EXT            ".key"
+
 /*
  * Used in parsing of configuration file
  */