]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
documentation, beautify
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Fri, 8 Mar 2024 10:31:01 +0000 (11:31 +0100)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Fri, 8 Mar 2024 11:13:46 +0000 (12:13 +0100)
doc/bird.sgml
proto/bgp/bgp.c
proto/bgp/packets.c
sysdep/linux/sysio.h

index 09da89df5fc36252d05ce6d5f1960a27992e20cb..a48500c3d1ed189f74a2aa5e0248f17217346e97 100644 (file)
@@ -2433,6 +2433,38 @@ protocol bfd [&lt;name&gt;] {
        offers better resistance to replay attacks but may require more
        computation.
 
+       <tag>authentication keyed tcp AO</tag>
+       This authentication is similar to md5, but enables changing keys on living connection.
+       Key change is done via reconfiguring.
+
+       Key configuration of one key consists of two ids - one for local and one for remote machine.
+       The ids may, but does not have to be the same and must be in range 0 - 255. Among keys
+       on one protocol the local ids must be unique and the remote ids must be unique.
+
+       Used cryphtographic algorithm must be specified for each key.
+       Possible ciphers are "cmac(aes128)", "hmac(md5)" "hmac(sha1)", "hmac(sha224)",
+       "hmac(sha256)", "hmac(sha384)" and "hmac(sha512)". And, of course, there must
+       be specified a string password.
+
+       One key must be marked as "required". This key will be send as rnext key.
+       That means, if the other site know the required key, it uses the key for next packet.
+
+       In order to delete a currently used key (key which is required by the other site),
+       it is possible to mark the key as "deprecated". This key will be deleted first time
+       the other site requires another key.
+
+       Deleting a curently used key in config causes restart of the protocol.
+       The problem of directly deleting current key is, that we could treat such deleted key as deprecated,
+       but only until the protocol restarts. If it restarts, key is lost.
+       For example, connection is established. Then one side decides to remove current key and requires a newly added key.
+       The other side does not know the new key yet. For now, this is not problem, they still use the old key.
+       But, at this moment, some unexpected error occures at the first site.
+       It restarts, but it does not have the old key in config. One site does not have old key,
+       the other new key and triing other keys than required ones is not supported.
+
+       Editing existing keys (except of marking them "required" or "deprecated")
+       is not reccomended and leads to restarting protocol.
+
        <tag>password "<M>text</M>"</tag>
        Specifies a password used for authentication. See <ref id="proto-pass"
        name="password"> common option for detailed description. Note that
index 2d1ea8d3a05e95a8afb121d5228aad0fc22d6fdf..147ffd2f4136f17d5d85a8ceaa36b744c02ed17b 100644 (file)
@@ -1296,19 +1296,23 @@ bgp_incoming_connection(sock *sk, uint dummy UNUSED)
 
   if (p->ao_key)
   {
-     if (check_ao_keys_id(sk->fd, p->ao_key) == 0)
-     {
-       sk->use_ao = 1;
-       for (struct bgp_ao_key *key = p->ao_key; key; key = key->next_key)
-       {
-        key->activ_alive = key->passiv_alive;
-        if (key->key.required == 1)
-        {
-          sk->desired_ao_key = key->key.remote_id;
-           ao_try_change_master(sk, key->key.local_id, key->key.remote_id);
-        }
-       }
-     }
+    if (check_ao_keys_id(sk->fd, p->ao_key) == 0)
+    {
+      sk->use_ao = 1;
+      for (struct bgp_ao_key *key = p->ao_key; key; key = key->next_key)
+      {
+        key->activ_alive = key->passiv_alive;
+        if (key->key.required == 1)
+        {
+          sk->desired_ao_key = key->key.remote_id;
+          ao_try_change_master(sk, key->key.local_id, key->key.remote_id);
+        }
+        else if (key->key.required == -1)
+        {
+          sk->proto_del_ao_key = p;
+        }
+      }
+    }
   }
   if (p->cf->enable_extended_messages)
   {
@@ -2272,14 +2276,16 @@ int reconfigure_tcp_ao(struct bgp_proto *old_proto, struct bgp_config new)
         if (compare_aos(&old_ao->key, &cf_ao->key))
           return 0;
         if (old_ao->activ_alive == 0 && cf_ao->key.required >= 0)
-       {
-          if (sk_set_ao_auth(s_activ, old_proto->local_ip, old_proto->remote_ip, -1, s_activ->iface, old_ao->key.master_key, old_ao->key.local_id, old_ao->key.remote_id, old_ao->key.cipher, 0))
+        {
+          if (sk_set_ao_auth(s_activ, old_proto->local_ip, old_proto->remote_ip, -1, s_activ->iface,
+                                old_ao->key.master_key, old_ao->key.local_id, old_ao->key.remote_id, old_ao->key.cipher, 0))
             return 0;
          old_ao->activ_alive = 1;
-       }
+        }
         if (old_ao->passiv_alive == 0 && cf_ao->key.required >= 0)
        {
-          if (sk_set_ao_auth(s_passiv, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface, old_ao->key.master_key, old_ao->key.local_id, old_ao->key.remote_id, old_ao->key.cipher, 0))
+          if (sk_set_ao_auth(s_passiv, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface,
+                                 old_ao->key.master_key, old_ao->key.local_id, old_ao->key.remote_id, old_ao->key.cipher, 0))
             return 0;
          old_ao->passiv_alive = 1;
        }
@@ -2290,11 +2296,12 @@ int reconfigure_tcp_ao(struct bgp_proto *old_proto, struct bgp_config new)
           s_passiv->desired_ao_key = old_ao->key.remote_id;
           ao_try_change_master(s_activ, old_ao->key.local_id, old_ao->key.remote_id);
           if (old_proto->conn->hold_timer->expires != 0)
-            bgp_schedule_packet(old_proto->conn, NULL, PKT_KEEPALIVE); // We might send this keepalive shortly after another. RFC says we should wait, but since reconfiguration is rare, this is harmless.
+            bgp_schedule_packet(old_proto->conn, NULL, PKT_KEEPALIVE); // We might send this keepalive shortly after another.
+                                                                      // RFC says we should wait, but since reconfiguration is rare, this is harmless.
         }
         old_ao->key = cf_ao->key;
-       old_ao->to_delete = 0;
-       found = old_ao;
+        old_ao->to_delete = 0;
+        found = old_ao;
       }
     }
     if (!found)
@@ -2305,10 +2312,12 @@ int reconfigure_tcp_ao(struct bgp_proto *old_proto, struct bgp_config new)
       key->passiv_alive = 0;
       key->next_key = first;
       old_proto->ao_key = key;
-      if (sk_set_ao_auth(s_passiv, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface, cf_ao->key.master_key, cf_ao->key.local_id, cf_ao->key.remote_id, cf_ao->key.cipher, 0))
+      if (sk_set_ao_auth(s_passiv, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface,
+                             cf_ao->key.master_key, cf_ao->key.local_id, cf_ao->key.remote_id, cf_ao->key.cipher, 0))
         return 0;
       key->passiv_alive = 1;
-      if (sk_set_ao_auth(s_activ, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface, cf_ao->key.master_key, cf_ao->key.local_id, cf_ao->key.remote_id, cf_ao->key.cipher, 0))
+      if (sk_set_ao_auth(s_activ, old_proto->local_ip, old_proto->remote_ip, -1, s_passiv->iface,
+                             cf_ao->key.master_key, cf_ao->key.local_id, cf_ao->key.remote_id, cf_ao->key.cipher, 0))
         return 0;
       key->activ_alive = 1;
       key->to_delete = 0;
@@ -2320,7 +2329,8 @@ int reconfigure_tcp_ao(struct bgp_proto *old_proto, struct bgp_config new)
         s_passiv->desired_ao_key = found->key.remote_id;
         ao_try_change_master(s_activ, found->key.local_id, found->key.remote_id);
         if (old_proto->conn->hold_timer->expires != 0)
-          bgp_schedule_packet(old_proto->conn, NULL, PKT_KEEPALIVE); // We might send this keepalive shortly after another. RFC says we should wait, but since reconfiguration is rare, this is harmless.
+          bgp_schedule_packet(old_proto->conn, NULL, PKT_KEEPALIVE); // We might send this keepalive shortly after another.
+                                                                    // RFC says we should wait, but since reconfiguration is rare, this is harmless.
       }
     }
   }
@@ -2334,7 +2344,7 @@ int reconfigure_tcp_ao(struct bgp_proto *old_proto, struct bgp_config new)
       if (old_ao->key.remote_id == key_in_use_rem)
       {
         log(L_WARN "TCP AO: deleting currently used key");
-       return 0;
+        return 0;
       }
       if (ao_delete_key(s_activ, old_proto->remote_ip, -1, s_activ->iface, old_ao->key.local_id, old_ao->key.remote_id))
         return 0;
index 360b612457293616620e0dffedd5cab8614fd4f9..25542af9834ecc73b5ec8c8fd4c2398f00835ef2 100644 (file)
@@ -3410,22 +3410,30 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
   }
 }
 
-void
-delete_deprecated_key(sock *sk, struct bgp_proto *p, int key_rem_id)
+int
+delete_deprecated_keys(sock *sk, struct bgp_proto *p, int new_rnext)
 {
   struct bgp_ao_key *key = p->ao_key;
-  while (key->key.remote_id != key_rem_id)
+  int ret  = 1;
+  while (key)
   {
+    if (key->key.required == -1)
+    {
+      if (new_rnext == key->key.remote_id)
+        ret = 0;
+      else
+      {
+        if (ao_delete_key(sk, p->remote_ip, -1, sk->iface, key->key.local_id, key->key.remote_id))
+          bug("TCP AO: Can not delete deprecated key %i %i on socket %i", key->key.local_id, key->key.remote_id, sk->fd);
+        key->activ_alive = 0;
+        if (ao_delete_key(p->sock->sk, p->remote_ip, -1, p->sock->sk->iface, key->key.local_id, key->key.remote_id))
+          bug("TCP AO: Can not delete deprecated key %i %i on socket %i", key->key.local_id, key->key.remote_id, p->sock->sk->fd);
+        key->passiv_alive = 0;
+      }
+    }
     key = key->next_key;
   }
-  if (key->key.required != -1)
-    bug("TCP AO: unexpected key management error");
-  if (ao_delete_key(sk, p->remote_ip, -1, sk->iface, key->key.local_id, key->key.remote_id))
-    bug("TCP AO: Can not delete deprecated key %i %i on socket %i", key->key.local_id, key->key.remote_id, sk->fd);
-  key->activ_alive = 0;
-  if (ao_delete_key(p->sock->sk, p->remote_ip, -1, p->sock->sk->iface, key->key.local_id, key->key.remote_id))
-    bug("TCP AO: Can not delete deprecated key %i %i on socket %i", key->key.local_id, key->key.remote_id, p->sock->sk->fd);
-  key->passiv_alive = 0;
+  return ret;
 }
 
 /**
@@ -3454,8 +3462,8 @@ bgp_rx(sock *sk, uint size)
 
       if (sk->proto_del_ao_key && sk->desired_ao_key == new_rnext)
       {
-        delete_deprecated_key(sk, sk->proto_del_ao_key, sk->last_used_ao_key);
-       sk->proto_del_ao_key = NULL;
+        if (delete_deprecated_keys(sk, sk->proto_del_ao_key, new_rnext))
+          sk->proto_del_ao_key = NULL;
       }
       sk->last_used_ao_key = new_rnext;
     }
index a6f0fe1266f3d14e3b75e1aa66b229c2e142094e..53c82018097e9b61124ed7f3f2b03357f18cbf4a 100644 (file)
@@ -217,7 +217,6 @@ void log_tcp_ao_info(int sock_fd)
   struct tcp_ao_info_opt_ext tmp;
   memset(&tmp, 0, sizeof(struct tcp_ao_info_opt_ext));
   socklen_t len = sizeof(tmp);
-  log("socket: fd %i", sock_fd);
 
   if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
   {
@@ -225,8 +224,8 @@ void log_tcp_ao_info(int sock_fd)
     return;
   }
   else
-    log(L_INFO "TCP AO:\ncurrent key id %i (rem), next key %i (loc),\n set current %i, is 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);
+    log(L_INFO "TCP AO on socket %i:\ncurrent key id %i (rem), next key %i (loc),\n set current %i, is ao required %i\n good packets %i, bad packets %i",
+                   sock_fd, tmp.current_key, tmp.rnext, tmp.set_current, tmp.ao_required, tmp.pkt_good, tmp.pkt_bad);
 }
 
 int get_current_key_id(int sock_fd)
@@ -237,8 +236,8 @@ int get_current_key_id(int sock_fd)
 
   if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
   {
-     log(L_WARN "TCP AO: Getting current ao key for socket file descriptor %i failed with errno %i", sock_fd, errno);
-     return -1;
+    log(L_WARN "TCP AO: Getting current ao key for socket file descriptor %i failed with errno %i", sock_fd, errno);
+    return -1;
   }
   else
     return tmp.current_key;
@@ -269,8 +268,8 @@ int get_num_ao_keys(int sock_fd)
 
   if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_GET_KEYS, &tmp, &len))
   {
-     log(L_WARN "TCP AO: get keys on socket fd %i failed with err code %i", sock_fd, errno);
-     return -1;
+    log(L_WARN "TCP AO: get keys on socket fd %i failed with err code %i", sock_fd, errno);
+    return -1;
   }
   return tmp.nkeys;
 }
@@ -288,13 +287,15 @@ log_tcp_ao_get_key(int sock_fd)
   tm_all[0].get_all = 1;
   if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_GET_KEYS, tm_all, &len))  // len should be still size of one struct. Because kernel net/ipv4/tcp_ao.c line 2165
   {
-     log(L_WARN "TCP AO: getting keys on socket fd %i failed with err code %i", sock_fd, errno);
-     return;
+    log(L_WARN "TCP AO: getting keys on socket fd %i failed with err code %i", sock_fd, errno);
+    return;
   }
   log(L_INFO "TCP AO on socket fd %i has %i keys", tm_all[0].nkeys);
   for (int i = 0; i < nkeys; i++)
   {
-    log(L_INFO "sndid %i rcvid %i, %s %s, cipher %s key %s (%i/%i)", tm_all[i].sndid, tm_all[i].rcvid, tm_all[i].is_current ? "current" : "", tm_all[i].is_rnext ? "rnext" : "", tm_all[i].alg_name, tm_all[i].key, i+1, tm_all[0].nkeys);
+    log(L_INFO "sndid %i rcvid %i, %s %s, cipher %s key %s (%i/%i)",
+                   tm_all[i].sndid, tm_all[i].rcvid, tm_all[i].is_current ? "current" : "",
+                   tm_all[i].is_rnext ? "rnext" : "", tm_all[i].alg_name, tm_all[i].key, i+1, tm_all[0].nkeys);
   }
 }
 
@@ -411,7 +412,7 @@ int check_ao_keys_id(int sock_fd, struct bgp_ao_key *keys)
   for (struct bgp_ao_key *key = keys; key; key = key->next_key)
     expected_keys[key->key.local_id] = key->key.remote_id + 1; // the + 1 because we do not want 0 id be 0
   int nkeys = get_num_ao_keys(sock_fd);
-  if(nkeys == -1)
+  if (nkeys == -1)
   {
     log(L_WARN "TCP AO: unable to get num of keys");
     return 1;
@@ -434,7 +435,7 @@ int check_ao_keys_id(int sock_fd, struct bgp_ao_key *keys)
       if (expected_keys[sock_key.rcvid] == 0)
         log(L_WARN "TCP AO: unexpected ao key %i %i", sock_key.rcvid, sock_key.sndid);
       else
-       log(L_WARN "TCP AO: expected key local id %i has different remote id than expected (%i vs %i)", sock_key.rcvid, expected_keys[sock_key.rcvid] - 1, sock_key.sndid);
+        log(L_WARN "TCP AO: expected key local id %i has different remote id than expected (%i vs %i)", sock_key.rcvid, expected_keys[sock_key.rcvid] - 1, sock_key.sndid);
       errors++;
     }
     expected_keys[sock_key.rcvid] = 0;