? ktrace.out ? ldpd.conf ? y.output 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 23 Jan 2019 00:40:23 -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 23 Jan 2019 00:40:23 -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,62 @@ 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) { + uint32_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 = htonl(~0U << 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); } 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 23 Jan 2019 00:40:23 -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,27 @@ 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 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, 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 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 23 Jan 2019 00:40:23 -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,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; }; 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 23 Jan 2019 00:40:23 -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 23 Jan 2019 00:40:23 -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 23 Jan 2019 00:40:23 -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 23 Jan 2019 00:40:23 -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 23 Jan 2019 00:40:23 -0000 @@ -24,6 +24,8 @@ %{ #include +#include +#include #include #include #include @@ -33,6 +35,8 @@ #include #include #include +#include +#include #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_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 +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 NUMBER %type yesno ldp_af l2vpn_type pw_type %type string +%type 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}, @@ -1601,4 +1707,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 23 Jan 2019 00:40:23 -0000 @@ -36,7 +36,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 +367,81 @@ 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) - 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) { + uint32_t mask = htonl(~0U << 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 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 23 Jan 2019 00:40:23 -0000 @@ -19,8 +19,11 @@ */ #include +#include #include #include +#include +#include #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) { @@ -191,6 +216,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);