diff options
-rw-r--r-- | usr.sbin/ldpd/lde.c | 15 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.c | 80 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.conf.5 | 41 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpd.h | 24 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.c | 20 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 15 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 11 | ||||
-rw-r--r-- | usr.sbin/ldpd/packet.c | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/parse.y | 180 | ||||
-rw-r--r-- | usr.sbin/ldpd/pfkey.c | 99 | ||||
-rw-r--r-- | usr.sbin/ldpd/printconf.c | 36 |
11 files changed, 399 insertions, 126 deletions
diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c index e6b45719700..1bfd701a390 100644 --- a/usr.sbin/ldpd/lde.c +++ b/usr.sbin/ldpd/lde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lde.c,v 1.73 2017/03/04 00:15:35 renato Exp $ */ +/* $OpenBSD: lde.c,v 1.74 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -480,6 +480,7 @@ lde_dispatch_parent(int fd, short event, void *bula) LIST_INIT(&nconf->tnbr_list); LIST_INIT(&nconf->nbrp_list); LIST_INIT(&nconf->l2vpn_list); + LIST_INIT(&nconf->auth_list); break; case IMSG_RECONF_IFACE: if ((niface = malloc(sizeof(struct iface))) == NULL) @@ -534,6 +535,18 @@ lde_dispatch_parent(int fd, short event, void *bula) npw->l2vpn = nl2vpn; LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); break; + case IMSG_RECONF_CONF_AUTH: { + struct ldp_auth *auth; + + auth = malloc(sizeof(*auth)); + if (auth == NULL) + fatal(NULL); + + memcpy(auth, imsg.data, sizeof(*auth)); + + LIST_INSERT_HEAD(&nconf->auth_list, auth, entry); + break; + } case IMSG_RECONF_END: merge_config(ldeconf, nconf); nconf = NULL; diff --git a/usr.sbin/ldpd/ldpd.c b/usr.sbin/ldpd/ldpd.c index 901df833a91..7425d2030e5 100644 --- a/usr.sbin/ldpd/ldpd.c +++ b/usr.sbin/ldpd/ldpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpd.c,v 1.62 2017/03/03 23:36:06 renato Exp $ */ +/* $OpenBSD: ldpd.c,v 1.63 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -60,6 +60,7 @@ static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *); static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *); static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *, struct l2vpn *); +static void merge_auths(struct ldpd_conf *, struct ldpd_conf *); struct ldpd_global global; struct ldpd_conf *ldpd_conf; @@ -681,11 +682,18 @@ main_imsg_send_config(struct ldpd_conf *xconf) struct l2vpn *l2vpn; struct l2vpn_if *lif; struct l2vpn_pw *pw; + struct ldp_auth *auth; if (main_imsg_compose_both(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) return (-1); + LIST_FOREACH(auth, &xconf->auth_list, entry) { + if (main_imsg_compose_both(IMSG_RECONF_CONF_AUTH, + auth, sizeof(*auth)) == -1) + return (-1); + } + LIST_FOREACH(iface, &xconf->iface_list, entry) { if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface, sizeof(*iface)) == -1) @@ -747,6 +755,7 @@ void merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) { merge_global(conf, xconf); + merge_auths(conf, xconf); merge_af(AF_INET, &conf->ipv4, &xconf->ipv4); merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6); merge_ifaces(conf, xconf); @@ -971,7 +980,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbr = nbr_find_ldpid(xn->lsr_id.s_addr); if (nbr) { session_shutdown(nbr, S_SHUTDOWN, 0, 0); - if (pfkey_establish(nbr, xn) == -1) + if (pfkey_establish(conf, nbr) == -1) fatalx("pfkey setup failed"); if (nbr_session_active_role(nbr)) nbr_establish_connection(nbr); @@ -984,9 +993,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) if (nbrp->flags != xn->flags || nbrp->keepalive != xn->keepalive || nbrp->gtsm_enabled != xn->gtsm_enabled || - nbrp->gtsm_hops != xn->gtsm_hops || - nbrp->auth.method != xn->auth.method || - strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0) + nbrp->gtsm_hops != xn->gtsm_hops) nbrp_changed = 1; else nbrp_changed = 0; @@ -994,10 +1001,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) nbrp->keepalive = xn->keepalive; nbrp->gtsm_enabled = xn->gtsm_enabled; nbrp->gtsm_hops = xn->gtsm_hops; - nbrp->auth.method = xn->auth.method; - strlcpy(nbrp->auth.md5key, xn->auth.md5key, - sizeof(nbrp->auth.md5key)); - nbrp->auth.md5key_len = xn->auth.md5key_len; nbrp->flags = xn->flags; if (ldpd_process == PROC_LDP_ENGINE) { @@ -1005,7 +1008,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) if (nbr && nbrp_changed) { session_shutdown(nbr, S_SHUTDOWN, 0, 0); pfkey_remove(nbr); - if (pfkey_establish(nbr, nbrp) == -1) + if (pfkey_establish(conf, nbr) == -1) fatalx("pfkey setup failed"); if (nbr_session_active_role(nbr)) nbr_establish_connection(nbr); @@ -1205,6 +1208,62 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) l2vpn->br_ifindex = xl->br_ifindex; } +static struct ldp_auth * +auth_find(struct ldpd_conf *conf, const struct ldp_auth *needle) +{ + struct ldp_auth *auth; + + LIST_FOREACH(auth, &conf->auth_list, entry) { + in_addr_t mask; + if (needle->md5key_len != auth->md5key_len) + continue; + if (needle->idlen != auth->idlen) + continue; + + if (memcmp(needle->md5key, auth->md5key, + needle->md5key_len) != 0) + continue; + + mask = prefixlen2mask(auth->idlen); + if ((needle->id.s_addr & mask) != (auth->id.s_addr & mask)) + continue; + + return (auth); + } + + return (NULL); +} + +static void +merge_auths(struct ldpd_conf *conf, struct ldpd_conf *xconf) +{ + struct ldp_auth *auth, *nauth, *xauth; + + /* find deleted auths */ + LIST_FOREACH_SAFE(auth, &conf->auth_list, entry, nauth) { + xauth = auth_find(xconf, auth); + if (xauth == NULL) + continue; + + LIST_REMOVE(auth, entry); + + free(auth); + } + + /* find new auths */ + LIST_FOREACH_SAFE(xauth, &xconf->auth_list, entry, nauth) { + LIST_REMOVE(xauth, entry); + + auth = auth_find(conf, xauth); + if (auth == NULL) { + LIST_INSERT_HEAD(&conf->auth_list, xauth, entry); + continue; + } + + free(xauth); + } +} + struct ldpd_conf * config_new_empty(void) { @@ -1218,6 +1277,7 @@ config_new_empty(void) LIST_INIT(&xconf->tnbr_list); LIST_INIT(&xconf->nbrp_list); LIST_INIT(&xconf->l2vpn_list); + LIST_INIT(&xconf->auth_list); return (xconf); } diff --git a/usr.sbin/ldpd/ldpd.conf.5 b/usr.sbin/ldpd/ldpd.conf.5 index c9d7706702c..2c797649be6 100644 --- a/usr.sbin/ldpd/ldpd.conf.5 +++ b/usr.sbin/ldpd/ldpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ldpd.conf.5,v 1.36 2018/08/06 17:25:11 mestre Exp $ +.\" $OpenBSD: ldpd.conf.5,v 1.37 2019/01/23 02:02:04 dlg Exp $ .\" .\" Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> .\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -19,7 +19,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: August 6 2018 $ +.Dd $Mdocdate: January 23 2019 $ .Dt LDPD.CONF 5 .Os .Sh NAME @@ -72,14 +72,6 @@ and may contain any of those characters. Macro names may not be reserved words (for example, .Ic neighbor ) . Macros are not expanded inside quotes. -.Pp -For example: -.Bd -literal -offset indent -peer1="10.0.1.5" -neighbor $peer1 { - password "openbsd" -} -.Ed .Sh GLOBAL CONFIGURATION Several settings can be configured globally or within a more restricted scope, like per address-family or per interface. @@ -119,6 +111,27 @@ Set the router ID; in combination with labelspace it forms the LSR-ID. If not specified, the numerically lowest IP address of the router will be used. .Pp .It Xo +.Ic tcp md5sig password Ar secret +.Op Ar lsr-id Ns Op / Ns Ar prefix +.Xc +.It Xo +.Ic tcp md5sig key Ar secret +.Op Ar lsr-id Ns Op / Ns Ar prefix +.Xc +.It Xo +.Ic no tcp md5sig +.Op Ar lsr-id Ns Op / Ns Ar prefix +.Xc +Enable or disable TCP MD5 signatures per RFC 5036. +The shared secret can either be given as a password or hexadecimal key. +An optional prefix may be specified to scope the key configuration to a +set of neighbors with the specified LSR-IDs. +.Bd -literal -offset indent +tcp md5sig password mekmitasdigoat 192.168.0.0/24 +no tcp md5sig 192.168.0.25 +.Ed +.Pp +.It Xo .Ic transport-preference .Pq Ic ipv4 Ns | Ns Ic ipv6 .Xc @@ -278,8 +291,12 @@ When GTSM is enabled for this neighbor, incoming packets are required to have a TTL/hop limit of 256 minus this value, ensuring they have not passed through more than the expected number of hops. The default value is 1; valid range is 1\-255. -.It Ic password Ar secret -Enable TCP MD5 signatures per RFC 5036. +.It Ic tcp md5sig password Ar secret +Enable TCP MD5 signatures per RFC 5036 with the specified password. +.It Ic tcp md5sig key Ar secret +Enable TCP MD5 signatures per RFC 5036 with the specified hexadecimal key. +.It Ic no tcp md5sig +Disable the use of TCP MD5 signatures. .El .Sh LAYER 2 VPNS .Xr ldpd 8 diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h index 6280bde5588..6d2f15c29e0 100644 --- a/usr.sbin/ldpd/ldpd.h +++ b/usr.sbin/ldpd/ldpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpd.h,v 1.88 2018/02/08 00:17:31 claudio Exp $ */ +/* $OpenBSD: ldpd.h,v 1.89 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -128,6 +128,7 @@ enum imsg_type { IMSG_RECONF_L2VPN, IMSG_RECONF_L2VPN_IF, IMSG_RECONF_L2VPN_PW, + IMSG_RECONF_CONF_AUTH, IMSG_RECONF_END }; @@ -300,11 +301,6 @@ struct tnbr { #define F_TNBR_CONFIGURED 0x01 #define F_TNBR_DYNAMIC 0x02 -enum auth_method { - AUTH_NONE, - AUTH_MD5SIG -}; - /* neighbor specific parameters */ struct nbr_params { LIST_ENTRY(nbr_params) entry; @@ -312,11 +308,6 @@ struct nbr_params { uint16_t keepalive; int gtsm_enabled; uint8_t gtsm_hops; - struct { - enum auth_method method; - char md5key[TCP_MD5_KEY_LEN]; - uint8_t md5key_len; - } auth; uint8_t flags; }; #define F_NBRP_KEEPALIVE 0x01 @@ -403,6 +394,16 @@ struct ldpd_af_conf { #define F_LDPD_AF_EXPNULL 0x0004 #define F_LDPD_AF_NO_GTSM 0x0008 +struct ldp_auth { + LIST_ENTRY(ldp_auth) entry; + char md5key[TCP_MD5_KEY_LEN]; + unsigned int md5key_len; + struct in_addr id; + int idlen; +}; + +#define LDP_AUTH_REQUIRED(_a) ((_a)->md5key_len != 0) + struct ldpd_conf { struct in_addr rtr_id; unsigned int rdomain; @@ -412,6 +413,7 @@ struct ldpd_conf { LIST_HEAD(, tnbr) tnbr_list; LIST_HEAD(, nbr_params) nbrp_list; LIST_HEAD(, l2vpn) l2vpn_list; + LIST_HEAD(, ldp_auth) auth_list; uint16_t trans_pref; int flags; }; diff --git a/usr.sbin/ldpd/ldpe.c b/usr.sbin/ldpd/ldpe.c index b30ab0f3c96..79084baea1f 100644 --- a/usr.sbin/ldpd/ldpe.c +++ b/usr.sbin/ldpd/ldpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpe.c,v 1.74 2017/03/04 00:21:48 renato Exp $ */ +/* $OpenBSD: ldpe.c,v 1.75 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -235,7 +235,6 @@ ldpe_dispatch_main(int fd, short event, void *bula) static int edisc_socket = -1; static int session_socket = -1; struct nbr *nbr; - struct nbr_params *nbrp; int n, shut = 0; if (event & EV_READ) { @@ -380,8 +379,7 @@ ldpe_dispatch_main(int fd, short event, void *bula) continue; nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr; - nbrp = nbr_params_find(leconf, nbr->id); - if (nbrp && pfkey_establish(nbr, nbrp) == -1) + if (pfkey_establish(nconf, nbr) == -1) fatalx("pfkey setup failed"); if (nbr_session_active_role(nbr)) nbr_establish_connection(nbr); @@ -397,6 +395,7 @@ ldpe_dispatch_main(int fd, short event, void *bula) LIST_INIT(&nconf->tnbr_list); LIST_INIT(&nconf->nbrp_list); LIST_INIT(&nconf->l2vpn_list); + LIST_INIT(&nconf->auth_list); break; case IMSG_RECONF_IFACE: if ((niface = malloc(sizeof(struct iface))) == NULL) @@ -451,6 +450,19 @@ ldpe_dispatch_main(int fd, short event, void *bula) npw->l2vpn = nl2vpn; LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); break; + case IMSG_RECONF_CONF_AUTH: { + struct ldp_auth *auth; + + auth = malloc(sizeof(*auth)); + if (auth == NULL) + fatal(NULL); + + memcpy(auth, imsg.data, sizeof(*auth)); + + LIST_INSERT_HEAD(&nconf->auth_list, auth, entry); + break; + } + case IMSG_RECONF_END: merge_config(leconf, nconf); nconf = NULL; diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h index 569e8ffc8bc..a4ad7de0440 100644 --- a/usr.sbin/ldpd/ldpe.h +++ b/usr.sbin/ldpd/ldpe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpe.h,v 1.75 2017/03/04 00:21:48 renato Exp $ */ +/* $OpenBSD: ldpe.h,v 1.76 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -94,13 +94,10 @@ struct nbr { uint16_t keepalive; uint16_t max_pdu_len; - struct { - uint8_t established; - uint32_t spi_in; - uint32_t spi_out; - enum auth_method method; - char md5key[TCP_MD5_KEY_LEN]; - } auth; + uint32_t auth_spi_in; + uint32_t auth_spi_out; + int auth_established; + int flags; }; #define F_NBR_GTSM_NEGOTIATED 0x01 @@ -276,7 +273,7 @@ char *pkt_ptr; /* packet buffer */ /* pfkey.c */ int pfkey_read(int, struct sadb_msg *); -int pfkey_establish(struct nbr *, struct nbr_params *); +int pfkey_establish(struct ldpd_conf *, struct nbr *); int pfkey_remove(struct nbr *); int pfkey_init(void); diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c index 37d7260fcfb..e41b922b403 100644 --- a/usr.sbin/ldpd/neighbor.c +++ b/usr.sbin/ldpd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.79 2017/03/04 00:15:35 renato Exp $ */ +/* $OpenBSD: neighbor.c,v 1.80 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -223,7 +223,6 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, uint32_t scope_id) { struct nbr *nbr; - struct nbr_params *nbrp; struct adj *adj; struct pending_conn *pconn; @@ -272,8 +271,7 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, evtimer_set(&nbr->init_timeout, nbr_itimeout, nbr); evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr); - nbrp = nbr_params_find(leconf, nbr->id); - if (nbrp && pfkey_establish(nbr, nbrp) == -1) + if (pfkey_establish(leconf, nbr) == -1) fatalx("pfkey setup failed"); pconn = pending_conn_find(nbr->af, &nbr->raddr); @@ -581,8 +579,7 @@ nbr_establish_connection(struct nbr *nbr) return (-1); } - nbrp = nbr_params_find(leconf, nbr->id); - if (nbrp && nbrp->auth.method == AUTH_MD5SIG) { + if (nbr->auth_established) { if (sysdep.no_pfkey || sysdep.no_md5sig) { log_warnx("md5sig configured but not available"); close(nbr->fd); @@ -610,6 +607,7 @@ nbr_establish_connection(struct nbr *nbr) return (-1); } + nbrp = nbr_params_find(leconf, nbr->id); if (nbr_gtsm_check(nbr->fd, nbr, nbrp)) { close(nbr->fd); return (-1); @@ -761,7 +759,6 @@ nbr_params_new(struct in_addr lsr_id) fatal(__func__); nbrp->lsr_id = lsr_id; - nbrp->auth.method = AUTH_NONE; return (nbrp); } diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c index 1e03a09bcee..09c83469778 100644 --- a/usr.sbin/ldpd/packet.c +++ b/usr.sbin/ldpd/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.70 2017/03/04 00:06:10 renato Exp $ */ +/* $OpenBSD: packet.c,v 1.71 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -391,7 +391,7 @@ session_accept_nbr(struct nbr *nbr, int fd) return; } - if (nbrp && nbrp->auth.method == AUTH_MD5SIG) { + if (!LIST_EMPTY(&leconf->auth_list)) { if (sysdep.no_pfkey || sysdep.no_md5sig) { log_warnx("md5sig configured but not available"); close(fd); diff --git a/usr.sbin/ldpd/parse.y b/usr.sbin/ldpd/parse.y index bfcca083172..4128ba94af8 100644 --- a/usr.sbin/ldpd/parse.y +++ b/usr.sbin/ldpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.67 2018/11/01 00:18:44 sashan Exp $ */ +/* $OpenBSD: parse.y,v 1.68 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2015, 2016 Renato Westphal <renato@openbsd.org> @@ -24,6 +24,8 @@ %{ #include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> #include <arpa/inet.h> #include <ctype.h> #include <err.h> @@ -33,6 +35,8 @@ #include <limits.h> #include <stdio.h> #include <syslog.h> +#include <errno.h> +#include <netdb.h> #include "ldpd.h" #include "ldpe.h" @@ -76,6 +80,7 @@ typedef struct { union { int64_t number; char *string; + struct ldp_auth *auth; } v; int lineno; } YYSTYPE; @@ -107,6 +112,7 @@ static void clear_config(struct ldpd_conf *xconf); static uint32_t get_rtr_id(void); static int get_address(const char *, union ldpd_addr *); static int get_af_address(const char *, int *, union ldpd_addr *); +static int str2key(char *, const char *, int); static struct file *file, *topfile; static struct files files = TAILQ_HEAD_INITIALIZER(files); @@ -135,9 +141,10 @@ static struct config_defaults *defs; %token INTERFACE TNEIGHBOR ROUTERID FIBUPDATE RDOMAIN EXPNULL %token LHELLOHOLDTIME LHELLOINTERVAL %token THELLOHOLDTIME THELLOINTERVAL -%token THELLOACCEPT AF IPV4 IPV6 GTSMENABLE GTSMHOPS +%token THELLOACCEPT AF IPV4 IPV6 INET INET6 GTSMENABLE GTSMHOPS %token KEEPALIVE TRANSADDRESS TRANSPREFERENCE DSCISCOINTEROP -%token NEIGHBOR PASSWORD +%token NEIGHBOR +%token TCP MD5SIG PASSWORD KEY %token L2VPN TYPE VPLS PWTYPE MTU BRIDGE %token ETHERNET ETHERNETTAGGED STATUSTLV CONTROLWORD %token PSEUDOWIRE NEIGHBORID NEIGHBORADDR PWID @@ -149,6 +156,7 @@ static struct config_defaults *defs; %token <v.number> NUMBER %type <v.number> yesno ldp_af l2vpn_type pw_type %type <v.string> string +%type <v.auth> auth tcpmd5 optnbrprefix %% @@ -273,6 +281,9 @@ conf_main : ROUTERID STRING { else conf->flags &= ~F_LDPD_DS_CISCO_INTEROP; } + | auth { + LIST_INSERT_HEAD(&conf->auth_list, $1, entry); + } | af_defaults | iface_defaults | tnbr_defaults @@ -404,6 +415,103 @@ tnbr_defaults : THELLOHOLDTIME NUMBER { } ; +tcpmd5 : TCP MD5SIG PASSWORD STRING { + size_t len; + + $$ = calloc(1, sizeof(*$$)); + if ($$ == NULL) { + free($4); + yyerror("unable to allocate md5 key"); + YYERROR; + } + + len = strlen($4); + if (len > sizeof($$->md5key)) { + free($$); + free($4); + yyerror("tcp md5sig password too long: " + "max %zu", sizeof($$->md5key)); + YYERROR; + } + + memcpy($$->md5key, $4, len); + $$->md5key_len = len; + + free($4); + } + | TCP MD5SIG KEY STRING { + int len; + + $$ = calloc(1, sizeof(*$$)); + if ($$ == NULL) { + free($4); + yyerror("unable to allocate md5 key"); + YYERROR; + } + + len = str2key($$->md5key, $4, sizeof($$->md5key)); + if (len == -1) { + free($$); + free($4); + yyerror("invalid hex string"); + YYERROR; + } + if ((size_t)len > sizeof($$->md5key_len)) { + free($$); + free($4); + yyerror("tcp md5sig key too long: %d " + "max %zu", len, sizeof($$->md5key)); + YYERROR; + } + + $$->md5key_len = len; + + free($4); + } + | NO TCP MD5SIG { + $$ = calloc(1, sizeof(*$$)); + if ($$ == NULL) { + yyerror("unable to allocate no md5 key"); + YYERROR; + } + $$->md5key_len = 0; + } + ; + +optnbrprefix : STRING { + $$ = calloc(1, sizeof(*$$)); + if ($$ == NULL) { + yyerror("unable to allocate auth"); + free($1); + YYERROR; + } + + $$->idlen = inet_net_pton(AF_INET, $1, + &$$->id, sizeof($$->id)); + if ($$->idlen == -1) { + yyerror("%s: %s", $1, strerror(errno)); + free($1); + YYERROR; + } + } + | /* empty */ { + $$ = NULL; + } + ; + +auth : tcpmd5 optnbrprefix { + $$ = $1; + if ($2 != NULL) { + $$->id = $2->id; + $$->idlen = $2->idlen; + free($2); + } else { + $$->id.s_addr = 0; + $$->idlen = 0; + } + } + ; + nbr_opts : KEEPALIVE NUMBER { if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) { yyerror("keepalive out of range (%d-%d)", @@ -413,18 +521,11 @@ nbr_opts : KEEPALIVE NUMBER { nbrp->keepalive = $2; nbrp->flags |= F_NBRP_KEEPALIVE; } - | PASSWORD STRING { - if (strlcpy(nbrp->auth.md5key, $2, - sizeof(nbrp->auth.md5key)) >= - sizeof(nbrp->auth.md5key)) { - yyerror("tcp md5sig password too long: max %zu", - sizeof(nbrp->auth.md5key) - 1); - free($2); - YYERROR; - } - nbrp->auth.md5key_len = strlen($2); - nbrp->auth.method = AUTH_MD5SIG; - free($2); + | tcpmd5 { + /* this is syntactic sugar... */ + $1->id = nbrp->lsr_id; + $1->idlen = 32; + LIST_INSERT_HEAD(&conf->auth_list, $1, entry); } | GTSMENABLE yesno { nbrp->flags |= F_NBRP_GTSM; @@ -835,13 +936,17 @@ lookup(char *s) {"gtsm-enable", GTSMENABLE}, {"gtsm-hops", GTSMHOPS}, {"include", INCLUDE}, + {"inet", INET}, + {"inet6", INET6}, {"interface", INTERFACE}, {"ipv4", IPV4}, {"ipv6", IPV6}, {"keepalive", KEEPALIVE}, + {"key", KEY}, {"l2vpn", L2VPN}, {"link-hello-holdtime", LHELLOHOLDTIME}, {"link-hello-interval", LHELLOINTERVAL}, + {"md5sig", MD5SIG}, {"mtu", MTU}, {"neighbor", NEIGHBOR}, {"neighbor-addr", NEIGHBORADDR}, @@ -858,6 +963,7 @@ lookup(char *s) {"targeted-hello-holdtime", THELLOHOLDTIME}, {"targeted-hello-interval", THELLOINTERVAL}, {"targeted-neighbor", TNEIGHBOR}, + {"tcp", TCP}, {"transport-address", TRANSADDRESS}, {"transport-preference", TRANSPREFERENCE}, {"type", TYPE}, @@ -1602,3 +1708,47 @@ get_af_address(const char *s, int *family, union ldpd_addr *addr) return (-1); } + +static int +hexchar(int ch) +{ + if (ch >= '0' && ch <= '9') + return (ch - '0'); + if (ch >= 'a' && ch <= 'f') + return (ch - 'a'); + if (ch >= 'A' && ch <= 'F') + return (ch - 'A'); + + return (-1); +} + +static int +str2key(char *dst, const char *src, int dstlen) +{ + int i = 0; + int digit; + + while (*src != '\0') { + digit = hexchar(*src); + if (digit == -1) + return (-1); + + if (i < dstlen) + *dst = digit << 4; + + src++; + if (*src == '\0') + return (-1); + digit = hexchar(*src); + if (digit == -1) + return (-1); + + if (i < dstlen) + *dst |= digit; + + src++; + i++; + } + + return (i); +} diff --git a/usr.sbin/ldpd/pfkey.c b/usr.sbin/ldpd/pfkey.c index 8e56c138b6e..0af77a85af4 100644 --- a/usr.sbin/ldpd/pfkey.c +++ b/usr.sbin/ldpd/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.11 2017/04/18 02:29:56 deraadt Exp $ */ +/* $OpenBSD: pfkey.c,v 1.12 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -36,7 +36,7 @@ static int pfkey_sa_add(int, union ldpd_addr *, union ldpd_addr *, uint8_t, char *, uint32_t *); static int pfkey_sa_remove(int, union ldpd_addr *, union ldpd_addr *, uint32_t *); -static int pfkey_md5sig_establish(struct nbr *, struct nbr_params *nbrp); +static int pfkey_md5sig_establish(struct nbr *, struct ldp_auth *); static int pfkey_md5sig_remove(struct nbr *); #define PFKEY2_CHUNK sizeof(uint64_t) @@ -367,84 +367,81 @@ pfkey_sa_remove(int af, union ldpd_addr *src, union ldpd_addr *dst, } static int -pfkey_md5sig_establish(struct nbr *nbr, struct nbr_params *nbrp) +pfkey_md5sig_establish(struct nbr *nbr, struct ldp_auth *auth) { sleep(1); - if (!nbr->auth.spi_out) - if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr, - nbrp->auth.md5key_len, nbrp->auth.md5key, - &nbr->auth.spi_out) == -1) - return (-1); - if (!nbr->auth.spi_in) - if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr, - nbrp->auth.md5key_len, nbrp->auth.md5key, - &nbr->auth.spi_in) == -1) - return (-1); + pfkey_md5sig_remove(nbr); + + if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr, + auth->md5key_len, auth->md5key, &nbr->auth_spi_out) == -1) + return (-1); + + if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr, + auth->md5key_len, auth->md5key, &nbr->auth_spi_in) == -1) + return (-1); + + nbr->auth_established = 1; - nbr->auth.established = 1; return (0); } static int pfkey_md5sig_remove(struct nbr *nbr) { - if (nbr->auth.spi_out) + if (nbr->auth_spi_out) { if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr, - &nbr->auth.spi_out) == -1) + &nbr->auth_spi_out) == -1) return (-1); - if (nbr->auth.spi_in) + } + if (nbr->auth_spi_in) { if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr, - &nbr->auth.spi_in) == -1) + &nbr->auth_spi_in) == -1) return (-1); + } - nbr->auth.established = 0; - nbr->auth.spi_in = 0; - nbr->auth.spi_out = 0; - nbr->auth.method = AUTH_NONE; - memset(nbr->auth.md5key, 0, sizeof(nbr->auth.md5key)); + nbr->auth_established = 0; + nbr->auth_spi_in = 0; + nbr->auth_spi_out = 0; return (0); } -int -pfkey_establish(struct nbr *nbr, struct nbr_params *nbrp) +static struct ldp_auth * +pfkey_find_auth(struct ldpd_conf *conf, struct nbr *nbr) { - if (nbrp->auth.method == AUTH_NONE) - return (0); + struct ldp_auth *auth, *match = NULL; - /* - * make sure we keep copies of everything we need to - * remove SAs and flows later again. - */ - nbr->auth.method = nbrp->auth.method; - - switch (nbr->auth.method) { - case AUTH_MD5SIG: - strlcpy(nbr->auth.md5key, nbrp->auth.md5key, - sizeof(nbr->auth.md5key)); - return (pfkey_md5sig_establish(nbr, nbrp)); - default: - break; + LIST_FOREACH(auth, &conf->auth_list, entry) { + in_addr_t mask = prefixlen2mask(auth->idlen); + if ((auth->id.s_addr & mask) != (nbr->id.s_addr & mask)) + continue; + + if (match == NULL || + match->idlen < auth->idlen) + match = auth; } - return (0); + return (match); } int -pfkey_remove(struct nbr *nbr) +pfkey_establish(struct ldpd_conf *conf, struct nbr *nbr) { - if (nbr->auth.method == AUTH_NONE || !nbr->auth.established) - return (0); + struct ldp_auth *auth = NULL; - switch (nbr->auth.method) { - case AUTH_MD5SIG: - return (pfkey_md5sig_remove(nbr)); - default: - break; - } + auth = pfkey_find_auth(conf, nbr); + if (auth == NULL || /* no policy */ + auth->md5key_len == 0) /* "no tcpmd5 sig" */ + return (0); + + return (pfkey_md5sig_establish(nbr, auth)); +} - return (0); +int +pfkey_remove(struct nbr *nbr) +{ + return (pfkey_md5sig_remove(nbr)); } int diff --git a/usr.sbin/ldpd/printconf.c b/usr.sbin/ldpd/printconf.c index e39b43f8336..b622e54d03b 100644 --- a/usr.sbin/ldpd/printconf.c +++ b/usr.sbin/ldpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.27 2017/03/03 23:36:06 renato Exp $ */ +/* $OpenBSD: printconf.c,v 1.28 2019/01/23 02:02:04 dlg Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -19,8 +19,11 @@ */ #include <sys/types.h> +#include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> +#include <netdb.h> +#include <err.h> #include "ldpd.h" #include "ldpe.h" @@ -132,9 +135,6 @@ print_nbrp(struct nbr_params *nbrp) if (nbrp->flags & F_NBRP_GTSM_HOPS) printf("\tgtsm-hops %u\n", nbrp->gtsm_hops); - if (nbrp->auth.method == AUTH_MD5SIG) - printf("\tpassword XXXXXX\n"); - printf("}\n"); } @@ -184,6 +184,31 @@ print_pw(struct l2vpn_pw *pw) printf("\t}\n"); } +static void +print_auth(struct ldpd_conf *conf) +{ + struct ldp_auth *auth; + + printf("\n"); + + LIST_FOREACH(auth, &conf->auth_list, entry) { + if (auth->md5key_len) + printf("tcp md5sig key XXX"); + else + printf("no tcp md5sig"); + if (auth->idlen) { + char hbuf[NI_MAXHOST]; + + if (inet_net_ntop(AF_INET, &auth->id, auth->idlen, + hbuf, sizeof(hbuf)) == NULL) + err(1, "inet_net_ntop"); + + printf(" %s", hbuf); + } + printf("\n"); + } +} + void print_config(struct ldpd_conf *conf) { @@ -192,6 +217,9 @@ print_config(struct ldpd_conf *conf) print_mainconf(conf); + if (!LIST_EMPTY(&conf->auth_list)) + print_auth(conf); + if (conf->ipv4.flags & F_LDPD_AF_ENABLED) print_af(AF_INET, conf, &conf->ipv4); if (conf->ipv6.flags & F_LDPD_AF_ENABLED) |