From e3dc32e064850fd4d46c5b906878737526abd306 Mon Sep 17 00:00:00 2001 From: Katerina Kubecova Date: Mon, 19 Feb 2024 12:09:36 +0100 Subject: [PATCH] repaired bgp/config.Y, tests are passing with good passwords, failing with wrong --- lib/socket.h | 19 ++++++++++++-- proto/bgp/bgp.c | 24 +++++++++++++++--- proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 47 ++++++++++++++++++++++++++++++++-- proto/bgp/packets.c | 1 - sysdep/linux/sysio.h | 60 +++++++++++++++++++++++++++++++------------- sysdep/unix/io.c | 14 +++++++++-- 7 files changed, 138 insertions(+), 28 deletions(-) diff --git a/lib/socket.h b/lib/socket.h index 32a7caed..044efdcd 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -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); diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 6d39b107..529076f0 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -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, - p->cf->password, 123, 123, p->cf->setkey); + 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, 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", diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 840862f6..c57d2327 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -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 */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index f589fd84..4e3d5856 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -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 bgp_nh %type 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); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index f48ebcdc..8d963ba8 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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; diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index ad17af94..09b7d3f3 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -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) { diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 7f51a712..18d13172 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -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; }