0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

tcp ao works, but can not be closed

This commit is contained in:
Katerina Kubecova 2024-02-26 14:58:25 +01:00
parent 82134476be
commit 85ce22eb0b
6 changed files with 90 additions and 31 deletions

View File

@ -120,6 +120,7 @@ int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given sock
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_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, const char *passwd, int setkey);
int get_current_key_id(int sock_fd); int get_current_key_id(int sock_fd);
int get_rnext_key_id(int sock_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, int set_current); 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, int set_current);
void ao_delete_key(sock *s, ip_addr remote, int pxlen, struct iface *ifa, int passwd_id_rem, int passwd_id_loc); void ao_delete_key(sock *s, ip_addr remote, int pxlen, struct iface *ifa, int passwd_id_rem, int passwd_id_loc);
void log_tcp_ao_info(int sock_fd); void log_tcp_ao_info(int sock_fd);

View File

@ -179,7 +179,6 @@ bgp_open(struct bgp_proto *p)
sk->type = SK_TCP_PASSIVE; sk->type = SK_TCP_PASSIVE;
sk->ttl = 255; sk->ttl = 255;
sk->saddr = addr; sk->saddr = addr;
// sk->daddr = p->remote_ip;
sk->sport = port; sk->sport = port;
sk->iface = ifa; sk->iface = ifa;
sk->vrf = p->p.vrf; sk->vrf = p->p.vrf;
@ -189,12 +188,11 @@ bgp_open(struct bgp_proto *p)
sk->tbsize = BGP_TX_BUFFER_SIZE; sk->tbsize = BGP_TX_BUFFER_SIZE;
sk->rx_hook = bgp_incoming_connection; sk->rx_hook = bgp_incoming_connection;
sk->err_hook = bgp_listen_sock_err; sk->err_hook = bgp_listen_sock_err;
//sk->password = p->cf->password;
log("passive connect p %i, c cf %i %s", p, p->cf, p->cf->password ? p->cf->password : "no password");
if (sk_open(sk) < 0) if (sk_open(sk) < 0)
goto err; goto err;
log("____________________________________________________________________________%i %i", sk->fd, sk->ao_key);
bs = mb_allocz(proto_pool, sizeof(struct bgp_socket)); bs = mb_allocz(proto_pool, sizeof(struct bgp_socket));
bs->sk = sk; bs->sk = sk;
bs->uc = 1; bs->uc = 1;
@ -251,6 +249,7 @@ bgp_setup_auth(struct bgp_proto *p, int enable)
{ {
log("set ao auth [%s]", p->cf->ao_key->master_key); log("set ao auth [%s]", p->cf->ao_key->master_key);
struct ao_key *key = p->cf->ao_key; struct ao_key *key = p->cf->ao_key;
p->sock->sk->ao_key = key;
do { do {
rv = sk_set_ao_auth(p->sock->sk, rv = sk_set_ao_auth(p->sock->sk,
p->cf->local_ip, prefix, pxlen, p->cf->iface, p->cf->local_ip, prefix, pxlen, p->cf->iface,
@ -1085,6 +1084,7 @@ bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn)
conn->channels_to_send = 0; conn->channels_to_send = 0;
conn->last_channel = 0; conn->last_channel = 0;
conn->last_channel_count = 0; conn->last_channel_count = 0;
conn->last_used_ao_key = -1;
conn->connect_timer = tm_new_init(p->p.pool, bgp_connect_timeout, conn, 0, 0); conn->connect_timer = tm_new_init(p->p.pool, bgp_connect_timeout, conn, 0, 0);
conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0); conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0);
@ -1160,11 +1160,11 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
bgp_setup_sk(conn, s); bgp_setup_sk(conn, s);
bgp_conn_set_state(conn, BS_CONNECT); bgp_conn_set_state(conn, BS_CONNECT);
log("active open p %i, c cf %i %s ", p, p->cf, p->cf->password ? p->cf->password : "no password");
if (sk_open(s) < 0) if (sk_open(s) < 0)
goto err; goto err;
//int rv = sk_set_ao_auth(s, p->local_ip, p->remote_ip, -1, s->iface, s->password ? s->password : "d3f4u1t", 1); log("a..........................................................................................fd %i key %i %I", s->fd, s->ao_key, s->daddr);
/* Set minimal receive TTL if needed */ /* Set minimal receive TTL if needed */
if (p->cf->ttl_security) if (p->cf->ttl_security)
if (sk_set_min_ttl(s, 256 - hops) < 0) if (sk_set_min_ttl(s, 256 - hops) < 0)
@ -2170,9 +2170,9 @@ int reconfigure_tcp_ao(struct bgp_proto old_proto, struct bgp_config new)
log("in reconf ao"); log("in reconf ao");
sock *s_passiv = old_proto.sock->sk; sock *s_passiv = old_proto.sock->sk;
sock *s_activ = old_proto.conn->sk; sock *s_activ = old_proto.conn->sk;
int key_in_use = get_current_key_id(s_activ->fd); int key_in_use_rem = get_current_key_id(s_activ->fd);
if (key_in_use == -1) if (key_in_use_rem == -1)
{ {
log("Unable to detect currently used key"); log("Unable to detect currently used key");
return 0; return 0;
@ -2180,10 +2180,15 @@ int reconfigure_tcp_ao(struct bgp_proto old_proto, struct bgp_config new)
struct ao_key *old_aos[256]; struct ao_key *old_aos[256];
memset(&old_aos, 0, sizeof(struct ao_key*)*256); memset(&old_aos, 0, sizeof(struct ao_key*)*256);
struct ao_key *old_rem_id[256];
memset(&old_rem_id, 0, sizeof(struct ao_key*)*256);
for(struct ao_key *ao_key = old_proto.cf->ao_key; ao_key; ao_key = ao_key->next_key) for(struct ao_key *ao_key = old_proto.cf->ao_key; ao_key; ao_key = ao_key->next_key)
{ {
old_aos[ao_key->local_id] = ao_key; old_aos[ao_key->local_id] = ao_key;
old_rem_id[ao_key->remote_id] = ao_key;
} }
int key_in_use = old_rem_id[key_in_use_rem]->local_id;
for(struct ao_key *ao_key = new.ao_key; ao_key; ao_key = ao_key->next_key) for(struct ao_key *ao_key = new.ao_key; ao_key; ao_key = ao_key->next_key)
{ {
if(old_aos[ao_key->local_id]) if(old_aos[ao_key->local_id])
@ -2191,15 +2196,13 @@ int reconfigure_tcp_ao(struct bgp_proto old_proto, struct bgp_config new)
if(compare_aos(ao_key, old_aos[ao_key->local_id])) if(compare_aos(ao_key, old_aos[ao_key->local_id]))
{ {
struct ao_key *o = old_aos[ao_key->local_id]; struct ao_key *o = old_aos[ao_key->local_id];
log("%i %i %i %i %s %s %s %s", ao_key->local_id, o->local_id, ao_key->remote_id, o->remote_id, ao_key->cipher, o->cipher, ao_key->master_key, o->master_key); log("%i %i (master %i) %i %i %s %s %s %s", ao_key->local_id, o->local_id, key_in_use, ao_key->remote_id, o->remote_id, ao_key->cipher, o->cipher, ao_key->master_key, o->master_key);
if (ao_key->local_id == key_in_use) if (ao_key->local_id == key_in_use)
{ {
//struct ao_key *o = old_aos[ao_key->local_id]; cf_warn("TCP AO reconfiguration: Currently used master key (%i) part update. This is not allowed.", ao_key->local_id);
//log("%i %i %i %i %s %s %s %s", ao_key->local_id, o->local_id, ao_key->remote_id, o->remote_id, ao_key->cipher, o->cipher, ao_key->master_key, o->master_key);
log("Currently used master key part update. This is not allowed.");
return 0; return 0;
} }
log("Reusing key id. Not nice. Lets try to update."); cf_warn("TCP AO reconfiguration: Reusing or manipulating key with id %i. This might break connection.", ao_key->local_id);
struct ao_key *old_key = old_aos[ao_key->local_id]; struct ao_key *old_key = old_aos[ao_key->local_id];
ao_delete_key(s_activ, old_proto.remote_ip, -1, s_activ->iface, old_key->local_id, old_key->remote_id); ao_delete_key(s_activ, old_proto.remote_ip, -1, s_activ->iface, old_key->local_id, old_key->remote_id);
@ -2211,13 +2214,19 @@ int reconfigure_tcp_ao(struct bgp_proto old_proto, struct bgp_config new)
} }
else else
{ {
if (old_rem_id[ao_key->remote_id])
cf_warn("TCP AO reconfiguration: Reusing remote id %i with new local id %i. This might break your connection.", ao_key->remote_id, ao_key->local_id);
sk_set_ao_auth(s_activ, old_proto.local_ip, old_proto.remote_ip, -1, s_activ->iface, ao_key->master_key, ao_key->local_id, ao_key->remote_id, ao_key->cipher, ao_key->required == 1); sk_set_ao_auth(s_activ, old_proto.local_ip, old_proto.remote_ip, -1, s_activ->iface, ao_key->master_key, ao_key->local_id, ao_key->remote_id, ao_key->cipher, ao_key->required == 1);
sk_set_ao_auth(s_passiv, old_proto.local_ip, old_proto.remote_ip, -1, s_passiv->iface, ao_key->master_key, ao_key->local_id, ao_key->remote_id, ao_key->cipher, 0); sk_set_ao_auth(s_passiv, old_proto.local_ip, old_proto.remote_ip, -1, s_passiv->iface, ao_key->master_key, ao_key->local_id, ao_key->remote_id, ao_key->cipher, 0);
} }
s_activ->ao_key = new.ao_key;
s_passiv->ao_key = new.ao_key;
if (ao_key->required == 1) if (ao_key->required == 1 && (ao_key->local_id != get_rnext_key_id(s_activ->fd)))
{ {
ao_try_change_master(s_activ->fd, ao_key->local_id); // or remote id? ao_try_change_master(s_activ->fd, ao_key->local_id);
if (old_proto.conn->hold_timer->expires != 0)
bgp_schedule_packet(old_proto.conn, NULL, PKT_KEEPALIVE); // According to RFC we should not send keepalive shortly after another, but since reconfiguration is rare, this is harmless
} }
} }
for(int i = 0; i<256; i++) for(int i = 0; i<256; i++)
@ -2226,14 +2235,14 @@ int reconfigure_tcp_ao(struct bgp_proto old_proto, struct bgp_config new)
{ {
if (i == key_in_use) if (i == key_in_use)
{ {
log("Currently used key deletion. This is not allowed."); cf_warn("TCP AO reconfiguration: Currently used key (id %i) deletion. This is not allowed.", i);
return 0; return 0;
} }
ao_delete_key(s_activ, old_proto.remote_ip, -1, s_activ->iface, old_aos[i]->local_id, old_aos[i]->remote_id); ao_delete_key(s_activ, old_proto.remote_ip, -1, s_activ->iface, old_aos[i]->local_id, old_aos[i]->remote_id);
ao_delete_key(s_passiv, old_proto.remote_ip, -1, s_passiv->iface, old_aos[i]->local_id, old_aos[i]->remote_id); ao_delete_key(s_passiv, old_proto.remote_ip, -1, s_passiv->iface, old_aos[i]->local_id, old_aos[i]->remote_id);
} }
} }
log("no changes in ao"); log("no big changes in ao");
return 1; return 1;
} }

View File

@ -245,6 +245,8 @@ ao_key:
ao_first_item: ao_first_item:
LOCAL ID expr ';' { LOCAL ID expr ';' {
if($3 >= 256)
cf_error("Key ids ust be in range 0 - 255");
if (!BGP_CFG->ao_lp) if (!BGP_CFG->ao_lp)
BGP_CFG->ao_lp = lp_new(rp_new(&root_pool, "ao struct pool")); BGP_CFG->ao_lp = lp_new(rp_new(&root_pool, "ao struct pool"));
struct ao_key *new_key = lp_alloc(BGP_CFG->ao_lp, sizeof(struct ao_key)); struct ao_key *new_key = lp_alloc(BGP_CFG->ao_lp, sizeof(struct ao_key));
@ -252,20 +254,27 @@ ao_first_item:
BGP_CFG->ao_key = new_key; BGP_CFG->ao_key = new_key;
BGP_CFG->ao_key->required = 0; BGP_CFG->ao_key->required = 0;
BGP_CFG->ao_key->local_id = $3; BGP_CFG->ao_key->local_id = $3;
BGP_CFG->ao_key->remote_id = -1;
} }
; ;
ao_item: ao_item:
REMOTE ID expr ';' {log("remote id %i", $3); BGP_CFG->ao_key->remote_id = $3; } REMOTE ID expr ';' {
| CIPHER text ';' { char *c = lp_alloc(BGP_CFG->ao_lp, strlen($2)); if ($3 > 255)
cf_error("TCP AO: Key id must be in range 0 - 255");
BGP_CFG->ao_key->remote_id = $3; }
| CIPHER text ';' {
if (strcmp($2, "cmac(aes128)") & strcmp($2, "hmac(sha1)") & strcmp($2, "hmac(sha224)") & strcmp($2, "hmac(sha256)") & strcmp($2, "hmac(sha384)") & strcmp($2, "hmac(sha512)")& strcmp($2, "hmac(md5)"))
cf_error("TCP AO: Here are ciphers 'cmac(aes128)', 'hmac(md5)', 'hmac(sha1)', 'hmac(sha224)', 'hmac(sha256)', 'hmac(sha384)' and 'hmac(sha512)' hardcoded. If there is another cipher available in kernel, please contact BIRD developers.");
char *c = lp_alloc(BGP_CFG->ao_lp, strlen($2));
memcpy(c, $2, strlen($2)); memcpy(c, $2, strlen($2));
BGP_CFG->ao_key->cipher = c; BGP_CFG->ao_key->cipher = c;
log("ciph[%s]", $2); } }
| MASTER KEY text ';' { | MASTER KEY text ';' {
char *k = lp_alloc(BGP_CFG->ao_lp, strlen($3)); char *k = lp_alloc(BGP_CFG->ao_lp, strlen($3));
memcpy(k, $3, strlen($3)); memcpy(k, $3, strlen($3));
BGP_CFG->ao_key->master_key = k; BGP_CFG->ao_key->master_key = k;
log("key[%s]", BGP_CFG->ao_key->master_key);} }
| DEPRECATED ';' { BGP_CFG->ao_key->required = -1; } | DEPRECATED ';' { BGP_CFG->ao_key->required = -1; }
| REQUIRED ';' { BGP_CFG->ao_key->required = 1; } | REQUIRED ';' { BGP_CFG->ao_key->required = 1; }
; ;
@ -283,21 +292,27 @@ tcp_ao_end:
while (key) while (key)
{ {
if (used_aos_id_loc[key->local_id]) if (used_aos_id_loc[key->local_id])
cf_error("Reused local key id"); cf_error("TCP AO: Reused local key id %i", key->local_id);
used_aos_id_loc[key->local_id] = 1; used_aos_id_loc[key->local_id] = 1;
if (key->remote_id == -1)
cf_error("TCP AO: No remote key id for local id %i", key->local_id);
if (used_aos_id_rem[key->remote_id]) if (used_aos_id_rem[key->remote_id])
cf_error("Reused remote key id"); cf_error("TCP AO: Reused remote key id %i", key->remote_id);
used_aos_id_rem[key->remote_id] = 1; used_aos_id_rem[key->remote_id] = 1;
if (!key->cipher)
cf_error("TCP AO: No cipher given for key id %i.", key->local_id);
if (!key->master_key)
cf_error("TCP AO: No master key given for key id %i.", key->local_id);
if (key->required == 1) if (key->required == 1)
{ {
if (required_found) if (required_found)
cf_error("How do you want to use two keys at once? Check 'REQUIRED'"); cf_error("TCP AO: How do you want to use two keys at once? Check 'REQUIRED'");
required_found = 1; required_found = 1;
} }
key = key->next_key; key = key->next_key;
} }
if (required_found == 0) if (required_found == 0)
cf_error("Missing 'REQUIRED'. Which key should be used?"); cf_error("TCP AO: Missing 'REQUIRED'. Which key should be used?");
} }
bgp_channel_start: bgp_afi bgp_channel_start: bgp_afi

View File

@ -3424,8 +3424,25 @@ int
bgp_rx(sock *sk, uint size) bgp_rx(sock *sk, uint size)
{ {
struct bgp_conn *conn = sk->data; struct bgp_conn *conn = sk->data;
//if (get_current_key_id(sk->fd) == conn->last_used_ao_key) TODO: uncoment after debug
log_ao(sk->fd); if (sk->ao_key)
{
if (get_current_key_id(sk->fd) != conn->last_used_ao_key)
{
if (conn->hold_timer->expires != 0)
bgp_schedule_packet(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.
conn->last_used_ao_key = get_current_key_id(sk->fd);
log_ao(sk->fd);
log("%i", sk->ao_key);
}
else //todo delete after debug
{
log_ao(sk->fd);
log("%i %i", get_current_key_id(sk->fd), conn->last_used_ao_key);
log("fd %i sk %i key %i", sk->fd, sk, sk->ao_key);
}
}
byte *pkt_start = sk->rbuf; byte *pkt_start = sk->rbuf;
byte *end = pkt_start + size; byte *end = pkt_start + size;
uint i, len; uint i, len;

View File

@ -253,6 +253,21 @@ int get_current_key_id(int sock_fd)
return tmp.current_key; return tmp.current_key;
} }
int get_rnext_key_id(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);
if (getsockopt(sock_fd, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
{
log("get rnext ao key failed %i", errno);
return -1;
}
else
return tmp.rnext;
}
void void
log_tcp_ao_get_key(int sock_fd) log_tcp_ao_get_key(int sock_fd)
{ {
@ -290,7 +305,9 @@ sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *
{ {
struct tcp_ao_add_ext ao; struct tcp_ao_add_ext ao;
memset(&ao, 0, sizeof(struct tcp_ao_add_ext)); memset(&ao, 0, sizeof(struct tcp_ao_add_ext));
log("in sk set ao, pass %s", passwd); if (!s->ao_key)
bug("no ao key");
log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>in sk set ao, pass %s fd %i sk %i %i", passwd, s->fd, s, s->ao_key);
/* int af; /* int af;
if (ipa_is_ip4(remote)) if (ipa_is_ip4(remote))
af = AF_INET; af = AF_INET;
@ -318,8 +335,7 @@ sk_set_ao_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *
ao.keylen = strlen(passwd); ao.keylen = strlen(passwd);
memcpy(ao.key, passwd, (strlen(passwd) > TCP_AO_MAXKEYLEN_) ? TCP_AO_MAXKEYLEN_ : strlen(passwd)); memcpy(ao.key, passwd, (strlen(passwd) > TCP_AO_MAXKEYLEN_) ? TCP_AO_MAXKEYLEN_ : strlen(passwd));
int IPPROTO_TCP_ = 6;
if (setsockopt(s->fd, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)) < 0) if (setsockopt(s->fd, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)) < 0)
bug("tcp ao err %i", errno); bug("tcp ao err %i", errno);
@ -341,7 +357,7 @@ ao_delete_key(sock *s, ip_addr remote, int pxlen, struct iface *ifa, int passwd_
del.prefix = 32; del.prefix = 32;
else else
del.prefix = 128; del.prefix = 128;
int IPPROTO_TCP_ = 6;
if (setsockopt(s->fd, IPPROTO_TCP, TCP_AO_DEL_KEY, &del, sizeof(del)) < 0) if (setsockopt(s->fd, IPPROTO_TCP, TCP_AO_DEL_KEY, &del, sizeof(del)) < 0)
bug("tcp ao deletion err %i", errno); bug("tcp ao deletion err %i", errno);
log("tcp ao key %i %i deleted", passwd_id_loc, passwd_id_rem); log("tcp ao key %i %i deleted", passwd_id_loc, passwd_id_rem);

View File

@ -1098,6 +1098,7 @@ sk_passive_connected(sock *s, int type)
t->vrf = s->vrf; t->vrf = s->vrf;
t->rbsize = s->rbsize; t->rbsize = s->rbsize;
t->tbsize = s->tbsize; t->tbsize = s->tbsize;
t->ao_key = s->ao_key;
if (type == SK_TCP) if (type == SK_TCP)
{ {