]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
repaired bgp/config.Y, tests are passing with good passwords, failing with wrong
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 19 Feb 2024 11:09:36 +0000 (12:09 +0100)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 19 Feb 2024 11:09:36 +0000 (12:09 +0100)
lib/socket.h
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c
sysdep/linux/sysio.h
sysdep/unix/io.c

index 32a7caed27c3d0a0d128ee902125947f1803c126..044efdcd1571c6dbfe37fe6d32373fd036ec76ac 100644 (file)
@@ -36,6 +36,17 @@ struct ssh_sock {
 };
 #endif
 
+struct ao_key
+{
+  int local_id;
+  int remote_id;
+  const char *cipher;
+  const char *master_key;
+  int requested;
+  struct linpool *lp;
+  struct ao_key *next_key;
+};
+
 typedef struct birdsock {
   resource r;
   pool *pool;                          /* Pool where incoming connections should be allocated (for SK_xxx_PASSIVE) */
@@ -77,6 +88,7 @@ typedef struct birdsock {
   node n;
   void *rbuf_alloc, *tbuf_alloc;
   const char *password;                        /* Password for MD5 authentication */
+  struct ao_key *ao_key;               /* Key for tcp ao authentication */
   const char *err;                     /* Error message */
   struct ssh_sock *ssh;                        /* Used in SK_SSH */
 } sock;
@@ -107,8 +119,11 @@ int sk_setup_broadcast(sock *s);
 int sk_set_ttl(sock *s, int ttl);      /* Set transmit TTL for given socket */
 int sk_set_min_ttl(sock *s, int ttl);  /* Set minimal accepted TTL for given socket */
 int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey);
-int sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int passwd_id_loc, int passwd_id_rem, int setkey);
-void log_tcp_ao_info(int fd);
+
+int sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int passwd_id_loc, int passwd_id_rem, const char *cipher);
+void log_tcp_ao_info(int sock_fd);
+void log_tcp_ao_get_key(int sock_fd);
+void ao_try_change_master(int sock_fd, int next_key_id);
 int sk_set_ipv6_checksum(sock *s, int offset);
 int sk_set_icmp6_filter(sock *s, int p1, int p2);
 void sk_log_error(sock *s, const char *p);
index 6d39b10763fa60a8a30ddb8741b7199920686f01..529076f0e521d08ecc05f1d013012cb95239ceea 100644 (file)
@@ -236,7 +236,7 @@ bgp_close(struct bgp_proto *p)
 static inline int
 bgp_setup_auth(struct bgp_proto *p, int enable)
 {
-  if (p->cf->password)
+  if (p->cf->password || p->cf->ao_key)
   {
     ip_addr prefix = p->cf->remote_ip;
     int pxlen = -1;
@@ -247,10 +247,22 @@ bgp_setup_auth(struct bgp_proto *p, int enable)
       pxlen = net_pxlen(p->cf->remote_range);
     }
     int rv = 0;
-    if (enable)
-      rv = sk_set_ao_auth(p->sock->sk,
+    if (p->cf->ao_key)
+    {
+      log("set ao auth [%s]", p->cf->ao_key->master_key);
+      struct ao_key *key = p->cf->ao_key;
+      do {
+        rv = sk_set_ao_auth(p->sock->sk,
+                            p->cf->local_ip, prefix, pxlen, p->cf->iface,
+                            key->master_key, key->local_id, key->remote_id, key->cipher);
+       key = key->next_key;
+
+      } while(key);
+    }
+    else if (enable)
+      rv = sk_set_md5_auth(p->sock->sk,
                             p->cf->local_ip, prefix, pxlen, p->cf->iface,
-                            p->cf->password, 123, 123, p->cf->setkey);
+                            p->cf->password, p->cf->setkey);
 
     if (rv < 0)
       sk_log_error(p->sock->sk, p->p.name);
@@ -1105,7 +1117,10 @@ bgp_active(struct bgp_proto *p)
 void
 log_ao(int fd)
 {
+  log("the two ao logs");
   log_tcp_ao_info(fd);
+  log_tcp_ao_get_key(fd);
+  ao_try_change_master(fd, 101);
 }
 
 /**
@@ -1136,6 +1151,7 @@ bgp_connect(struct bgp_proto *p)  /* Enter Connect state and start establishing c
   s->tos = IP_PREC_INTERNET_CONTROL;
  // s->password = "abcd1234";/
   s->password = p->cf->password;
+  s->ao_key = p->cf->ao_key;
   s->tx_hook = bgp_connected;
   s->flags = p->cf->free_bind ? SKF_FREEBIND : 0;
   BGP_TRACE(D_EVENTS, "Connecting to %I%J from local address %I%J",
index 840862f6bca719240071bc4db6699fe8f08972da..c57d2327ffb12a6937e7e5802db21f93722152a4 100644 (file)
@@ -134,6 +134,7 @@ struct bgp_config {
   u32 disable_after_cease;             /* Disable it when cease is received, bitfield */
 
   const char *password;                        /* Password used for MD5 authentication */
+  struct ao_key *ao_key;               /* Keys for tcp ao authentication */
   net_addr *remote_range;              /* Allowed neighbor range for dynamic BGP */
   const char *dynamic_name;            /* Name pattern for dynamic BGP */
   int dynamic_name_digits;             /* Minimum number of digits for dynamic names */
index f589fd8402542fba556fc1caec6f2eb9192acf4b..4e3d585649d46a3378389fdf5fdcbb152bb6c761 100644 (file)
@@ -32,7 +32,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
        LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL, SETS,
        DYNAMIC, RANGE, NAME, DIGITS, BGP_AIGP, AIGP, ORIGINATE, COST, ENFORCE,
        FIRST, FREE, VALIDATE, BASE, ROLE, ROLES, PEER, PROVIDER, CUSTOMER,
-       RS_SERVER, RS_CLIENT, REQUIRE, BGP_OTC, GLOBAL)
+       RS_SERVER, RS_CLIENT, REQUIRE, BGP_OTC, GLOBAL, AUTHENTICATE, MANUAL,
+       KEY, MASTER, DEPRECATED, REQUIRED, CIPHER, LOCAL, REMOTE)
 
 %type <i> bgp_nh
 %type <i32> bgp_afi
@@ -191,7 +192,8 @@ bgp_proto:
  | bgp_proto ENABLE EXTENDED MESSAGES bool ';' { BGP_CFG->enable_extended_messages = $5; }
  | bgp_proto ADVERTISE HOSTNAME bool ';' { BGP_CFG->enable_hostname = $4; }
  | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
- | bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
+ | bgp_proto PASSWORD text ';' { log("%s", $3); BGP_CFG->password = $3; }
+ | bgp_proto AUTHENTICATE MANUAL '{' ao_keys '}'
  | bgp_proto SETKEY bool ';' { BGP_CFG->setkey = $3; }
  | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
  | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
@@ -231,6 +233,47 @@ bgp_afi:
  | FLOW6               { $$ = BGP_AF_FLOW6; }
  ;
 
+ao_keys:
+   KEY '{' ao_first_item  ao_key '}' 
+   | KEY '{' ao_first_item ao_key '}' ao_keys
+ ;
+
+ao_key:
+  ao_item 
+  | ao_item ao_key
+;
+
+ao_first_item:
+    LOCAL ID expr ';' {
+      struct linpool *lp;
+      if (BGP_CFG->ao_key)
+        lp = BGP_CFG->ao_key->lp;
+      else
+        lp = lp_new(rp_new(&root_pool, "ao struct pool"));
+      struct ao_key *new_key = lp_alloc(lp, sizeof(struct ao_key));
+      new_key->lp = lp;
+      new_key->next_key = BGP_CFG->ao_key;
+      BGP_CFG->ao_key = new_key;
+      BGP_CFG->ao_key->requested = 0;
+      BGP_CFG->ao_key->local_id = $3;
+    }
+;
+
+ao_item:
+      REMOTE ID expr ';' {log("remote id %i", $3); BGP_CFG->ao_key->remote_id = $3; }
+    | CIPHER text ';' { char *c = lp_alloc(BGP_CFG->ao_key->lp, strlen($2));
+       memcpy(c, $2, strlen($2));
+       BGP_CFG->ao_key->cipher = c;
+       log("ciph[%s]", $2); }
+    | MASTER KEY text ';' {
+       char *k = lp_alloc(BGP_CFG->ao_key->lp, strlen($3));
+       memcpy(k, $3, strlen($3));
+       BGP_CFG->ao_key->master_key = k;
+       log("key[%s]", BGP_CFG->ao_key->master_key);}
+    | DEPRECATED ';' { BGP_CFG->ao_key->requested = -1; }
+    | REQUIRED ';' { BGP_CFG->ao_key->requested = 1; }
+ ;
+
 bgp_channel_start: bgp_afi
 {
   const struct bgp_af_desc *desc = bgp_get_af_desc($1);
index f48ebcdc06a8fe59b89ba5d91baa6bd5f3fdba84..8d963ba81a5f644c8ebe024769d32f4faa4d5c01 100644 (file)
@@ -3423,7 +3423,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
 int
 bgp_rx(sock *sk, uint size)
 {
-  log("......................................got %i", size);
   log_ao(sk->fd);
   struct bgp_conn *conn = sk->data;
   byte *pkt_start = sk->rbuf;
index ad17af9412b9feecca74a8c5f27ba27cc01680e0..09b7d3f32dd7542103b9456555146ca05d90aa51 100644 (file)
@@ -234,14 +234,36 @@ void log_tcp_ao_info(int sock_fd)
      return;
   }
   else
-    log("current key id %i, set current %i, ao required %i ", tmp.current_key, tmp.set_current, tmp.ao_required);
+    log("current key id %i, next key %i,\n set current %i, ao required %i\n good packets %i, bad packets %i",
+                   tmp.current_key, tmp.rnext, tmp.set_current, tmp.ao_required, tmp.pkt_good, tmp.pkt_bad);
+}
+
+void
+log_tcp_ao_get_key(int sock_fd)
+{
+  struct tcp_ao_getsockopt_ext tmp;
+  memset(&tmp, 0, sizeof(struct tcp_ao_getsockopt_ext));
+  socklen_t len = sizeof(tmp);
+  tmp.nkeys = 1;
+  tmp.get_all = 1;
+
+  if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_GET_KEYS, &tmp, &len))
+  {
+     log("log tcp ao get keys failed with err code %i", errno);
+     return;
+  }
+  else
+    log("cipher %s key %s num of keys %i", tmp.alg_name, tmp.key, tmp.nkeys);
+
 }
 
 int
-sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int passwd_id_loc, int passwd_id_rem, int setkey UNUSED)
+sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int passwd_id_loc, int passwd_id_rem, const char* cipher)
 {
   struct tcp_ao_add_ext ao;
   memset(&ao, 0, sizeof(struct tcp_ao_add_ext));
+  log("in sk set ao");
+  log("%s %i %i", passwd, passwd_id_loc, passwd_id_rem);
   log("af %i %I %I (%i or %i) %s %i", s->af, remote, local, AF_INET, AF_INET6, passwd, passwd[0]);
  /* int af;
   if (ipa_is_ip4(remote))
@@ -263,7 +285,7 @@ sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *
   ao.keyflags  = 0;
   ao.ifindex   = 0;
 
-  strncpy(ao.alg_name, DEFAULT_TEST_ALGO, 64);
+  strncpy(ao.alg_name, (cipher) ? cipher : DEFAULT_TEST_ALGO, 64);
 
   ao.keylen    = strlen(passwd);
   memcpy(ao.key, passwd, (strlen(passwd) > TCP_AO_MAXKEYLEN_) ? TCP_AO_MAXKEYLEN_ : strlen(passwd));
@@ -276,6 +298,24 @@ sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *
   return 0;
 }
 
+void
+ao_try_change_master(int sock_fd, int next_master_id )
+{
+  struct tcp_ao_info_opt_ext tmp;
+  memset(&tmp, 0, sizeof(struct tcp_ao_info_opt_ext));
+  socklen_t len = sizeof(tmp);
+  tmp.set_rnext = 1;
+  tmp.rnext = next_master_id;
+
+  if (setsockopt(sock_fd, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
+  {
+     log(" tcp ao change master key failed with err code %i", errno);
+     return;
+  }
+  else
+    log("tried to change master");
+}
+
 void
 save_to_repair(int sock_fd)
 {
@@ -296,20 +336,6 @@ repair_tcp_ao(int sock_fd, struct iface *ifa)
   log("tcp ao repair skiped");
 }
 
-void
-change_ao_keys(sock *s, int passwd_id_loc, int passwd_id_rem )
-{
-  struct tcp_ao_info_opt_ext tmp;
-  tmp.rnext = passwd_id_loc;
-  socklen_t len = sizeof(tmp);
-  if (setsockopt(s->fd, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
-  {
-     log("log tcp ao key change failed with err code %i", errno);
-     return;
-  }
-
-}
-
 static inline int
 sk_set_min_ttl4(sock *s, int ttl)
 {
index 7f51a712574351157c340903c0521b9fe8dc9f19..18d1317269fa72cb527bbcfa2d9201d77bedd23f 100644 (file)
@@ -1460,9 +1460,19 @@ sk_open(sock *s)
   }
   //s->password = "abcd1234";
 
-  if (s->password) //TODO condition if it should be ao or md5
+  if (s->ao_key)
   {
-    log("set ao");
+    log("set ao, %s", s->ao_key->cipher);
+    struct ao_key *key = s->ao_key;
+    do {
+      if (sk_set_ao_auth(s, s->saddr, s->daddr, -1, s->iface, key->master_key, key->local_id, key->remote_id, key->cipher) < 0)
+        goto err;
+      key = key->next_key;
+    } while (key);
+  }
+  if (s->password)
+  {
+    log("set md5");
     if (sk_set_ao_auth(s, s->saddr, s->daddr, -1, s->iface, s->password, 123, 123, 0) < 0)
       goto err;
   }