diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-10-09 10:01:30 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-10-09 10:01:30 +0000 |
commit | fda95ded0712cc490f848930197a2998203bc55e (patch) | |
tree | 7fc753a24d50f8739ccc6513c9c7bf06b0417c72 /usr.sbin/bgpd | |
parent | 25b323ce240ffd001e1258937ef58fe45a862182 (diff) |
Make it possible to configure tcp md5 and ipsec on rtr as well
Single out the auth_config yacc rules. Even though this requires an
extra merge_auth_conf() function to handle manual IPsec setups but
even with that this seems like a net gain.
There is no rtr cache that does tcp md5 on OpenBSD so those bits remain
untested for now.
OK tb@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/parse.y | 287 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 64 |
2 files changed, 187 insertions, 164 deletions
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 166c0e79438..954bc5c882a 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.469 2024/10/01 11:49:24 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.470 2024/10/09 10:01:29 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -187,6 +187,7 @@ static int push_unary_numop(enum comp_ops, long long); static int push_binary_numop(enum comp_ops, long long, long long); static int geticmptypebyname(char *, uint8_t); static int geticmpcodebyname(u_long, char *, uint8_t); +static int merge_auth_conf(struct auth_config *, struct auth_config *); static struct bgpd_config *conf; static struct network_head *netconf; @@ -228,6 +229,7 @@ typedef struct { } prefix; struct filter_prefixlen prefixlen; struct prefixset_item *prefixset_item; + struct auth_config authconf; struct { enum auth_enc_alg enc_alg; uint8_t enc_key_len; @@ -293,6 +295,7 @@ typedef struct { %type <v.filter_prefix> filter_prefix filter_prefix_l filter_prefix_h %type <v.filter_prefix> filter_prefix_m %type <v.u8> unaryop equalityop binaryop filter_as_type +%type <v.authconf> authconf %type <v.encspec> encspec %type <v.aspa_elm> aspa_tas aspa_tas_l %% @@ -732,6 +735,10 @@ rtropt : DESCR STRING { } currtr->min_version = $2; } + | authconf { + if (merge_auth_conf(&currtr->auth, &$1) == 0) + YYERROR; + } ; conf_main : AS as4number { @@ -2075,142 +2082,9 @@ peeropts : REMOTEAS as4number { curpeer->conf.max_out_prefix = $2; curpeer->conf.max_out_prefix_restart = $4; } - | TCP MD5SIG PASSWORD string { - if (curpeer->auth_conf.method) { - yyerror("auth method cannot be redefined"); - free($4); - YYERROR; - } - if (strlcpy(curpeer->auth_conf.md5key, $4, - sizeof(curpeer->auth_conf.md5key)) >= - sizeof(curpeer->auth_conf.md5key)) { - yyerror("tcp md5sig password too long: max %zu", - sizeof(curpeer->auth_conf.md5key) - 1); - free($4); - YYERROR; - } - curpeer->auth_conf.method = AUTH_MD5SIG; - curpeer->auth_conf.md5key_len = strlen($4); - free($4); - } - | TCP MD5SIG KEY string { - if (curpeer->auth_conf.method) { - yyerror("auth method cannot be redefined"); - free($4); - YYERROR; - } - - if (str2key($4, curpeer->auth_conf.md5key, - sizeof(curpeer->auth_conf.md5key)) == -1) { - free($4); - YYERROR; - } - curpeer->auth_conf.method = AUTH_MD5SIG; - curpeer->auth_conf.md5key_len = strlen($4) / 2; - free($4); - } - | IPSEC espah IKE { - if (curpeer->auth_conf.method) { - yyerror("auth method cannot be redefined"); - YYERROR; - } - if ($2) - curpeer->auth_conf.method = AUTH_IPSEC_IKE_ESP; - else - curpeer->auth_conf.method = AUTH_IPSEC_IKE_AH; - } - | IPSEC espah inout SPI NUMBER STRING STRING encspec { - enum auth_alg auth_alg; - uint8_t keylen; - - if (curpeer->auth_conf.method && - (((curpeer->auth_conf.spi_in && $3 == 1) || - (curpeer->auth_conf.spi_out && $3 == 0)) || - ($2 == 1 && curpeer->auth_conf.method != - AUTH_IPSEC_MANUAL_ESP) || - ($2 == 0 && curpeer->auth_conf.method != - AUTH_IPSEC_MANUAL_AH))) { - yyerror("auth method cannot be redefined"); - free($6); - free($7); - YYERROR; - } - - if (!strcmp($6, "sha1")) { - auth_alg = AUTH_AALG_SHA1HMAC; - keylen = 20; - } else if (!strcmp($6, "md5")) { - auth_alg = AUTH_AALG_MD5HMAC; - keylen = 16; - } else { - yyerror("unknown auth algorithm \"%s\"", $6); - free($6); - free($7); + | authconf { + if (merge_auth_conf(&curpeer->auth_conf, &$1) == 0) YYERROR; - } - free($6); - - if (strlen($7) / 2 != keylen) { - yyerror("auth key len: must be %u bytes, " - "is %zu bytes", keylen, strlen($7) / 2); - free($7); - YYERROR; - } - - if ($2) - curpeer->auth_conf.method = - AUTH_IPSEC_MANUAL_ESP; - else { - if ($8.enc_alg) { - yyerror("\"ipsec ah\" doesn't take " - "encryption keys"); - free($7); - YYERROR; - } - curpeer->auth_conf.method = - AUTH_IPSEC_MANUAL_AH; - } - - if ($5 <= SPI_RESERVED_MAX || $5 > UINT_MAX) { - yyerror("bad spi number %lld", $5); - free($7); - YYERROR; - } - - if ($3 == 1) { - if (str2key($7, curpeer->auth_conf.auth_key_in, - sizeof(curpeer->auth_conf.auth_key_in)) == - -1) { - free($7); - YYERROR; - } - curpeer->auth_conf.spi_in = $5; - curpeer->auth_conf.auth_alg_in = auth_alg; - curpeer->auth_conf.enc_alg_in = $8.enc_alg; - memcpy(&curpeer->auth_conf.enc_key_in, - &$8.enc_key, - sizeof(curpeer->auth_conf.enc_key_in)); - curpeer->auth_conf.enc_keylen_in = - $8.enc_key_len; - curpeer->auth_conf.auth_keylen_in = keylen; - } else { - if (str2key($7, curpeer->auth_conf.auth_key_out, - sizeof(curpeer->auth_conf.auth_key_out)) == - -1) { - free($7); - YYERROR; - } - curpeer->auth_conf.spi_out = $5; - curpeer->auth_conf.auth_alg_out = auth_alg; - curpeer->auth_conf.enc_alg_out = $8.enc_alg; - memcpy(&curpeer->auth_conf.enc_key_out, - &$8.enc_key, - sizeof(curpeer->auth_conf.enc_key_out)); - curpeer->auth_conf.enc_keylen_out = - $8.enc_key_len; - curpeer->auth_conf.auth_keylen_out = keylen; - } - free($7); } | TTLSECURITY yesno { curpeer->conf.ttlsec = $2; @@ -2357,6 +2231,111 @@ nettype : STATIC { $$ = 1; } | CONNECTED { $$ = 0; } ; +authconf : TCP MD5SIG PASSWORD string { + memset(&$$, 0, sizeof($$)); + if (strlcpy($$.md5key, $4, sizeof($$.md5key)) >= + sizeof($$.md5key)) { + yyerror("tcp md5sig password too long: max %zu", + sizeof($$.md5key) - 1); + free($4); + YYERROR; + } + $$.method = AUTH_MD5SIG; + $$.md5key_len = strlen($4); + free($4); + } + | TCP MD5SIG KEY string { + memset(&$$, 0, sizeof($$)); + if (str2key($4, $$.md5key, sizeof($$.md5key)) == -1) { + free($4); + YYERROR; + } + $$.method = AUTH_MD5SIG; + $$.md5key_len = strlen($4) / 2; + free($4); + } + | IPSEC espah IKE { + memset(&$$, 0, sizeof($$)); + if ($2) + $$.method = AUTH_IPSEC_IKE_ESP; + else + $$.method = AUTH_IPSEC_IKE_AH; + } + | IPSEC espah inout SPI NUMBER STRING STRING encspec { + enum auth_alg auth_alg; + uint8_t keylen; + + memset(&$$, 0, sizeof($$)); + if (!strcmp($6, "sha1")) { + auth_alg = AUTH_AALG_SHA1HMAC; + keylen = 20; + } else if (!strcmp($6, "md5")) { + auth_alg = AUTH_AALG_MD5HMAC; + keylen = 16; + } else { + yyerror("unknown auth algorithm \"%s\"", $6); + free($6); + free($7); + YYERROR; + } + free($6); + + if (strlen($7) / 2 != keylen) { + yyerror("auth key len: must be %u bytes, " + "is %zu bytes", keylen, strlen($7) / 2); + free($7); + YYERROR; + } + + if ($2) + $$.method = AUTH_IPSEC_MANUAL_ESP; + else { + if ($8.enc_alg) { + yyerror("\"ipsec ah\" doesn't take " + "encryption keys"); + free($7); + YYERROR; + } + $$.method = AUTH_IPSEC_MANUAL_AH; + } + + if ($5 <= SPI_RESERVED_MAX || $5 > UINT_MAX) { + yyerror("bad spi number %lld", $5); + free($7); + YYERROR; + } + + if ($3 == 1) { + if (str2key($7, $$.auth_key_in, + sizeof($$.auth_key_in)) == -1) { + free($7); + YYERROR; + } + $$.spi_in = $5; + $$.auth_alg_in = auth_alg; + $$.enc_alg_in = $8.enc_alg; + memcpy(&$$.enc_key_in, &$8.enc_key, + sizeof($$.enc_key_in)); + $$.enc_keylen_in = $8.enc_key_len; + $$.auth_keylen_in = keylen; + } else { + if (str2key($7, $$.auth_key_out, + sizeof($$.auth_key_out)) == -1) { + free($7); + YYERROR; + } + $$.spi_out = $5; + $$.auth_alg_out = auth_alg; + $$.enc_alg_out = $8.enc_alg; + memcpy(&$$.enc_key_out, &$8.enc_key, + sizeof($$.enc_key_out)); + $$.enc_keylen_out = $8.enc_key_len; + $$.auth_keylen_out = keylen; + } + free($7); + } + ; + espah : ESP { $$ = 1; } | AH { $$ = 0; } ; @@ -6033,3 +6012,39 @@ geticmpcodebyname(u_long type, char *w, uint8_t aid) } return -1; } + +static int +merge_auth_conf(struct auth_config *to, struct auth_config *from) +{ + if (to->method != 0) { + /* extra magic for manual ipsec rules */ + if (to->method == from->method && + (to->method == AUTH_IPSEC_MANUAL_ESP || + to->method == AUTH_IPSEC_MANUAL_AH)) { + if (to->spi_in == 0 && from->spi_in != 0) { + to->spi_in = from->spi_in; + to->auth_alg_in = from->auth_alg_in; + to->enc_alg_in = from->enc_alg_in; + memcpy(to->enc_key_in, from->enc_key_in, + sizeof(to->enc_key_in)); + to->enc_keylen_in = from->enc_keylen_in; + to->auth_keylen_in = from->auth_keylen_in; + return 1; + } else if (to->spi_out == 0 && from->spi_out != 0) { + to->spi_out = from->spi_out; + to->auth_alg_out = from->auth_alg_out; + to->enc_alg_out = from->enc_alg_out; + memcpy(to->enc_key_out, from->enc_key_out, + sizeof(to->enc_key_out)); + to->enc_keylen_out = from->enc_keylen_out; + to->auth_keylen_out = from->auth_keylen_out; + return 1; + } + } + yyerror("auth method cannot be redefined"); + return 0; + } + *to = *from; + return 1; +} + diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index e34380ffd38..a62311e7b62 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.175 2024/10/01 11:49:24 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.176 2024/10/09 10:01:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -712,6 +712,39 @@ print_aspa(struct aspa_tree *a) printf("\n}\n\n"); } +static void +print_auth(struct auth_config *auth, const char *c) +{ + char *method; + + if (auth->method == AUTH_MD5SIG) + printf("%s\ttcp md5sig\n", c); + else if (auth->method == AUTH_IPSEC_MANUAL_ESP || + auth->method == AUTH_IPSEC_MANUAL_AH) { + if (auth->method == AUTH_IPSEC_MANUAL_ESP) + method = "esp"; + else + method = "ah"; + + printf("%s\tipsec %s in spi %u %s XXXXXX", c, method, + auth->spi_in, print_auth_alg(auth->auth_alg_in)); + if (auth->enc_alg_in) + printf(" %s XXXXXX", print_enc_alg(auth->enc_alg_in)); + printf("\n"); + + printf("%s\tipsec %s out spi %u %s XXXXXX", c, method, + auth->spi_out, print_auth_alg(auth->auth_alg_out)); + if (auth->enc_alg_out) + printf(" %s XXXXXX", + print_enc_alg(auth->enc_alg_out)); + printf("\n"); + } else if (auth->method == AUTH_IPSEC_IKE_AH) + printf("%s\tipsec ah ike\n", c); + else if (auth->method == AUTH_IPSEC_IKE_ESP) + printf("%s\tipsec esp ike\n", c); + +} + void print_rtrs(struct rtr_config_head *rh) { @@ -723,6 +756,7 @@ print_rtrs(struct rtr_config_head *rh) printf("\tport %u\n", r->remote_port); if (r->local_addr.aid != AID_UNSPEC) printf("local-addr %s\n", log_addr(&r->local_addr)); + print_auth(&r->auth, ""); printf("}\n\n"); } } @@ -731,9 +765,7 @@ void print_peer(struct peer *peer, struct bgpd_config *conf, const char *c) { struct in_addr ina; - char *method; struct peer_config *p = &peer->conf; - struct auth_config *auth = &peer->auth_conf; if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) || (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128)) @@ -832,31 +864,7 @@ print_peer(struct peer *peer, struct bgpd_config *conf, const char *c) if (p->flags & PEERFLAG_LOG_UPDATES) printf("%s\tlog updates\n", c); - if (auth->method == AUTH_MD5SIG) - printf("%s\ttcp md5sig\n", c); - else if (auth->method == AUTH_IPSEC_MANUAL_ESP || - auth->method == AUTH_IPSEC_MANUAL_AH) { - if (auth->method == AUTH_IPSEC_MANUAL_ESP) - method = "esp"; - else - method = "ah"; - - printf("%s\tipsec %s in spi %u %s XXXXXX", c, method, - auth->spi_in, print_auth_alg(auth->auth_alg_in)); - if (auth->enc_alg_in) - printf(" %s XXXXXX", print_enc_alg(auth->enc_alg_in)); - printf("\n"); - - printf("%s\tipsec %s out spi %u %s XXXXXX", c, method, - auth->spi_out, print_auth_alg(auth->auth_alg_out)); - if (auth->enc_alg_out) - printf(" %s XXXXXX", - print_enc_alg(auth->enc_alg_out)); - printf("\n"); - } else if (auth->method == AUTH_IPSEC_IKE_AH) - printf("%s\tipsec ah ike\n", c); - else if (auth->method == AUTH_IPSEC_IKE_ESP) - printf("%s\tipsec esp ike\n", c); + print_auth(&peer->auth_conf, c); if (p->ttlsec) printf("%s\tttl-security yes\n", c); |