mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
documentation, beautify
This commit is contained in:
parent
29559dd6aa
commit
b60337b294
@ -2433,6 +2433,38 @@ protocol bfd [<name>] {
|
||||
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
|
||||
|
@ -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)
|
||||
{
|
||||
@ -2245,14 +2249,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;
|
||||
}
|
||||
@ -2263,11 +2269,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)
|
||||
@ -2278,10 +2285,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;
|
||||
@ -2293,7 +2302,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.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2307,7 +2317,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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user