currently ldpd only lets you specify md5 params with neighbors (not
targeted neighbors). this is awkward is you want to peer with
arbitrary hosts on a network since you'll have a to generate a lot of
config for each potential peer on that net.
both cisco and juniper let you set up keys for prefixes. this diff
follows their lead and moves tcpmd5 config out of neighbors and up to
the global scope. to work in my test environment, my config now looks
like this:
# global configuration
router-id 192.168.0.25
tcp md5sig password p6zFE8f794c7NaKG inet 192.168.0.0/24
address-family ipv4 {
# explicit-null yes
# keepalive 120
# targeted-hello-accept yes
# transport-address 10.0.0.1
interface vmx1
}
you can then punch holes in this if you want with "no tcp md5sig" lines.
thoughts? ok?
Index: lde.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/lde.c,v
retrieving revision 1.73
diff -u -p -r1.73 lde.c
--- lde.c 4 Mar 2017 00:15:35 -0000 1.73
+++ lde.c 22 Jan 2019 03:33:35 -0000
@@ -480,6 +480,7 @@ lde_dispatch_parent(int fd, short event,
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,
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;
Index: ldpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpd.c,v
retrieving revision 1.62
diff -u -p -r1.62 ldpd.c
--- ldpd.c 3 Mar 2017 23:36:06 -0000 1.62
+++ ldpd.c 22 Jan 2019 03:33:35 -0000
@@ -60,6 +60,7 @@ static void merge_nbrps(struct ldpd_co
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 *
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, stru
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, stru
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, stru
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, stru
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,70 @@ merge_l2vpn(struct ldpd_conf *xconf, str
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) {
+ if (needle->md5key_len != auth->md5key_len)
+ continue;
+ if (needle->sslen != auth->sslen)
+ continue;
+ if (memcmp(needle->md5key, auth->md5key,
+ needle->md5key_len) != 0)
+ continue;
+ if (needle->sslen && memcmp(&needle->ss, &auth->ss,
+ needle->sslen) != 0)
+ 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);
+
+#ifdef notyet
+ if (ldpd_process == PROC_LDP_ENGINE)
+ pfkey_remove(auth);
+#endif
+
+ 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);
+
+#ifdef notyet
+ if (ldpd_process == PROC_LDP_ENGINE)
+ pfkey_establish(xauth);
+#endif
+
+ continue;
+ }
+
+ free(xauth);
+ }
+}
+
struct ldpd_conf *
config_new_empty(void)
{
@@ -1218,6 +1285,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);
}
Index: ldpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpd.conf.5,v
retrieving revision 1.36
diff -u -p -r1.36 ldpd.conf.5
--- ldpd.conf.5 6 Aug 2018 17:25:11 -0000 1.36
+++ ldpd.conf.5 22 Jan 2019 03:33:35 -0000
@@ -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,26 @@ Set the router ID; in combination with l
If not specified, the numerically lowest IP address of the router will be used.
.Pp
.It Xo
+.Ic tcp md5sig password Ar secret
+.Op Oo Po Ic inet Ns | Ns Ic inet6 Pc Oc Ar address Ns Op / Ns Ar prefix
+.Xc
+.It Xo
+.Ic tcp md5sig key Ar secret
+.Op Oo Po Ic inet Ns | Ns Ic inet6 Pc Oc Ar address Ns Op / Ns Ar prefix
+.Xc
+.It Xo
+.Ic no tcp md5sig key Ar secret
+.Op Oo Po Ic inet Ns | Ns Ic inet6 Pc Oc Ar address 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 address prefix may be specified to scope the key configuration.
+.Bd -literal -offset indent
+tcp md5sig password mekmitasdigoat
+tcp md5sig key deadbeef
+.Ed
+.Pp
+.It Xo
.Ic transport-preference
.Pq Ic ipv4 Ns | Ns Ic ipv6
.Xc
@@ -278,8 +290,6 @@ When GTSM is enabled for this neighbor,
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.
.El
.Sh LAYER 2 VPNS
.Xr ldpd 8
Index: ldpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpd.h,v
retrieving revision 1.88
diff -u -p -r1.88 ldpd.h
--- ldpd.h 8 Feb 2018 00:17:31 -0000 1.88
+++ ldpd.h 22 Jan 2019 03:33:35 -0000
@@ -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,19 @@ 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 sockaddr_storage ss;
+ socklen_t sslen;
+ int prefixlen;
+ uint32_t spi_in;
+ uint32_t spi_out;
+};
+
+#define LDP_AUTH_REQUIRED(_a) ((_a)->md5key_len != 0)
+
struct ldpd_conf {
struct in_addr rtr_id;
unsigned int rdomain;
@@ -412,6 +416,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;
};
Index: ldpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpe.c,v
retrieving revision 1.74
diff -u -p -r1.74 ldpe.c
--- ldpe.c 4 Mar 2017 00:21:48 -0000 1.74
+++ ldpe.c 22 Jan 2019 03:33:35 -0000
@@ -235,7 +235,6 @@ ldpe_dispatch_main(int fd, short event,
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,
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,
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,
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;
Index: ldpe.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpe.h,v
retrieving revision 1.75
diff -u -p -r1.75 ldpe.h
--- ldpe.h 4 Mar 2017 00:21:48 -0000 1.75
+++ ldpe.h 22 Jan 2019 03:33:35 -0000
@@ -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);
Index: neighbor.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/neighbor.c,v
retrieving revision 1.79
diff -u -p -r1.79 neighbor.c
--- neighbor.c 4 Mar 2017 00:15:35 -0000 1.79
+++ neighbor.c 22 Jan 2019 03:33:35 -0000
@@ -223,7 +223,6 @@ nbr_new(struct in_addr id, int af, int d
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 d
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);
}
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/packet.c,v
retrieving revision 1.70
diff -u -p -r1.70 packet.c
--- packet.c 4 Mar 2017 00:06:10 -0000 1.70
+++ packet.c 22 Jan 2019 03:33:35 -0000
@@ -391,7 +391,7 @@ session_accept_nbr(struct nbr *nbr, int
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);
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/parse.y,v
retrieving revision 1.67
diff -u -p -r1.67 parse.y
--- parse.y 1 Nov 2018 00:18:44 -0000 1.67
+++ parse.y 22 Jan 2019 03:33:35 -0000
@@ -1,5 +1,6 @@
/* $OpenBSD: parse.y,v 1.67 2018/11/01 00:18:44 sashan Exp $ */
+
/*
* Copyright (c) 2013, 2015, 2016 Renato Westphal <[email protected]>
* Copyright (c) 2004, 2005, 2008 Esben Norby <[email protected]>
@@ -24,6 +25,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 +36,8 @@
#include <limits.h>
#include <stdio.h>
#include <syslog.h>
+#include <errno.h>
+#include <netdb.h>
#include "ldpd.h"
#include "ldpe.h"
@@ -76,6 +81,7 @@ typedef struct {
union {
int64_t number;
char *string;
+ struct ldp_auth *auth;
} v;
int lineno;
} YYSTYPE;
@@ -107,6 +113,7 @@ static void clear_config(struct ldpd_c
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 +142,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
@@ -148,7 +156,9 @@ static struct config_defaults *defs;
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.number> yesno ldp_af l2vpn_type pw_type
+%type <v.number> optaf optprefixlen
%type <v.string> string
+%type <v.auth> auth tcpmd5 optprefix address
%%
@@ -273,6 +283,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 +417,201 @@ tnbr_defaults : THELLOHOLDTIME NUMBER {
}
;
+tcpmd5 : TCP MD5SIG PASSWORD STRING {
+ size_t len;
+
+ $$ = malloc(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;
+
+ $$ = malloc(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 {
+ $$ = malloc(sizeof(*$$));
+ if ($$ == NULL) {
+ yyerror("unable to allocate no md5 key");
+ YYERROR;
+ }
+ $$->md5key_len = 0;
+ }
+ ;
+
+optaf : /* empty */ { $$ = AF_UNSPEC; }
+ | INET { $$ = AF_INET; }
+ | INET6 { $$ = AF_INET6; }
+ | ldp_af { $$ = $1; }
+ ;
+
+optprefix : optaf string {
+ char *ch;
+ int prefix;
+ struct addrinfo hints, *ai;
+ int error;
+
+ ch = strchr($2, '/');
+ if (ch != NULL)
+ *ch++ = '\0';
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = $1;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo($2, NULL, &hints, &ai);
+ if (error != 0) {
+ yyerror("%s: %s", $2, gai_strerror(error));
+ goto free2;
+ }
+
+ if (ai->ai_addrlen > sizeof($$->ss)) {
+ yyerror("ad_addrlen too long");
+ goto freeai;
+ }
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ prefix = 32;
+ break;
+ case AF_INET6:
+ prefix = 128;
+ break;
+ default:
+ yyerror("unexpected address family");
+ goto freeai;
+ }
+
+ if (ch != NULL) {
+ const char *errstr = NULL;
+
+ prefix = strtonum(ch, 0, prefix, &errstr);
+ if (errstr != NULL) {
+ yyerror("prefix %s: %s", ch, errstr);
+ goto freeai;
+ }
+ }
+
+ $$ = malloc(sizeof(*$$));
+ if ($$ == NULL) {
+ yyerror("unable to allocate address");
+ goto freeai;
+ }
+
+ memcpy(&$$->ss, ai->ai_addr, ai->ai_addrlen);
+ $$->sslen = ai->ai_addrlen;
+ $$->prefixlen = prefix;
+
+ freeaddrinfo(ai);
+ free($2);
+ break;
+
+freeai:
+ freeaddrinfo(ai);
+free2:
+ free($2);
+ YYERROR;
+ }
+ ;
+
+optprefixlen : /* empty */ { $$ = -1; }
+ | '/' NUMBER { $$ = $2; }
+ ;
+
+optprefix : /* empty */ {
+ $$ = NULL;
+ }
+ | address optprefixlen {
+ $$ = $1;
+ $$->prefixlen = $2;
+ }
+ ;
+
+auth : tcpmd5 optprefix {
+ $$ = $1;
+ if ($2 != NULL) {
+ memcpy(&$$->ss, &$2->ss, $2->sslen);
+ $$->sslen = $2->sslen;
+ switch ($$->ss.ss_family) {
+ case AF_INET:
+ if ($2->prefixlen > 32) {
+ free($$);
+ free($2);
+ yyerror("IPv4 prefix "
+ "is too long: max 32");
+ YYERROR;
+ } else if ($2->prefixlen == -1)
+ $$->prefixlen = 32;
+ else
+ $$->prefixlen = $2->prefixlen;
+ break;
+ case AF_INET6:
+ if ($2->prefixlen > 128) {
+ free($$);
+ free($2);
+ yyerror("IPv6 prefix "
+ "is too long: max 128");
+ YYERROR;
+ } else if ($2->prefixlen == -1)
+ $$->prefixlen = 128;
+ else
+ $$->prefixlen = $2->prefixlen;
+ break;
+ default:
+ free($$);
+ free($2);
+ yyerror("unhandled address family");
+ YYERROR;
+ }
+
+ free($2);
+ } else {
+ $$->sslen = 0;
+ $$->prefixlen = 0;
+ }
+ }
+ ;
+
nbr_opts : KEEPALIVE NUMBER {
if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) {
yyerror("keepalive out of range (%d-%d)",
@@ -413,19 +621,6 @@ 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);
- }
| GTSMENABLE yesno {
nbrp->flags |= F_NBRP_GTSM;
nbrp->gtsm_enabled = $2;
@@ -835,13 +1030,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 +1057,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},
@@ -1601,4 +1801,48 @@ get_af_address(const char *s, int *famil
}
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);
}
Index: pfkey.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/pfkey.c,v
retrieving revision 1.11
diff -u -p -r1.11 pfkey.c
--- pfkey.c 18 Apr 2017 02:29:56 -0000 1.11
+++ pfkey.c 22 Jan 2019 03:33:35 -0000
@@ -18,6 +18,7 @@
*/
#include <sys/types.h>
+#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -36,7 +37,7 @@ static int pfkey_sa_add(int, union ldpd
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 +368,142 @@ pfkey_sa_remove(int af, union ldpd_addr
}
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)
+ if (nbr->auth_spi_out) {
+ if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr,
+ &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)
+ }
+ if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr,
+ auth->md5key_len, auth->md5key, &nbr->auth_spi_out) == -1)
+ return (-1);
+
+ if (nbr->auth_spi_in) {
+ if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr,
+ &nbr->auth_spi_in) == -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 int
+pfkey_match_prefix(const uint32_t *a, const uint32_t *b, int prefix)
{
- if (nbrp->auth.method == AUTH_NONE)
- return (0);
+ while (prefix >= 32) {
+ if (*a++ != *b++)
+ return (0);
+ prefix -= 32;
+ }
- /*
- * 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;
+ if (prefix) {
+ uint32_t mask = htonl(~0U << prefix);
+ if ((*a & mask) != (*b & mask))
+ return (0);
}
- return (0);
+ return (1);
}
-int
-pfkey_remove(struct nbr *nbr)
+#define ss2sin(_ss) ((struct sockaddr_in *)(_ss))
+#define ss2sin6(_ss) ((struct sockaddr_in6 *)(_ss))
+
+static int
+pkey_match_auth(struct ldp_auth *auth, struct nbr *nbr)
{
- if (nbr->auth.method == AUTH_NONE || !nbr->auth.established)
- return (0);
+ if (auth->sslen > 0) {
+ const uint32_t *a, *b;
- switch (nbr->auth.method) {
- case AUTH_MD5SIG:
- return (pfkey_md5sig_remove(nbr));
- default:
- break;
+ assert(auth->prefixlen != -1);
+
+ if (auth->ss.ss_family != nbr->af)
+ return (0);
+
+ switch (nbr->af) {
+ case AF_INET:
+ assert(auth->prefixlen <= 32);
+ a = (const uint32_t *)&nbr->raddr.v4;
+ b = (const uint32_t *)&ss2sin(&auth->ss)->sin_addr;
+ break;
+
+ case AF_INET6:
+ assert(auth->prefixlen <= 128);
+ a = (const uint32_t *)&nbr->raddr.v6;
+ b = (const uint32_t *)&ss2sin6(&auth->ss)->sin6_addr;
+ break;
+ }
+
+ if (!pfkey_match_prefix(a, b, auth->prefixlen))
+ return (0);
}
- return (0);
+ return (1);
+
+}
+
+static struct ldp_auth *
+pfkey_find_auth(struct ldpd_conf *conf, struct nbr *nbr)
+{
+ struct ldp_auth *auth, *match = NULL;
+
+ LIST_FOREACH(auth, &conf->auth_list, entry) {
+ if (!pkey_match_auth(auth, nbr))
+ continue;
+
+ if (match == NULL ||
+ match->prefixlen < auth->prefixlen)
+ match = auth;
+ }
+
+ return (match);
+}
+
+int
+pfkey_establish(struct ldpd_conf *conf, struct nbr *nbr)
+{
+ struct ldp_auth *auth;
+
+ auth = pfkey_find_auth(conf, nbr);
+ if (auth == NULL || /* no prefix found */
+ auth->md5key_len == 0) /* "no tcpmd5 sig" */
+ return (0);
+
+ return (pfkey_md5sig_establish(nbr, auth));
+}
+
+int
+pfkey_remove(struct nbr *nbr)
+{
+ return (pfkey_md5sig_remove(nbr));
}
int
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/printconf.c,v
retrieving revision 1.27
diff -u -p -r1.27 printconf.c
--- printconf.c 3 Mar 2017 23:36:06 -0000 1.27
+++ printconf.c 22 Jan 2019 03:33:35 -0000
@@ -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,36 @@ 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->sslen) {
+ char hbuf[NI_MAXHOST];
+ int error;
+
+ error = getnameinfo((struct sockaddr *)&auth->ss,
+ auth->sslen, hbuf, sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ errx(1, "getnameinfo: %s",
+ gai_strerror(error));
+ }
+
+ printf(" %s/%d", hbuf, auth->prefixlen);
+ }
+ printf("\n");
+ }
+}
+
void
print_config(struct ldpd_conf *conf)
{
@@ -191,6 +221,9 @@ print_config(struct ldpd_conf *conf)
struct l2vpn *l2vpn;
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);