diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2019-05-31 15:25:58 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2019-05-31 15:25:58 +0000 |
commit | ade6fd10cfcef327575dffa177dcb4502de7c4e1 (patch) | |
tree | ec8aaf45d2a18b1eca0c0142c522d9d6974bffb2 /usr.sbin | |
parent | d17761b242ae6c21aeb21d5fce043a4b92f90cc9 (diff) |
Add support for SNI with new "tls keypair" option to load additional certs.
Tested by many (thanks!)
Feedback & OK rob@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/relayd/config.c | 11 | ||||
-rw-r--r-- | usr.sbin/relayd/parse.y | 39 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.c | 12 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.conf.5 | 40 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 12 |
5 files changed, 83 insertions, 31 deletions
diff --git a/usr.sbin/relayd/config.c b/usr.sbin/relayd/config.c index 9b71565d956..50b03744b72 100644 --- a/usr.sbin/relayd/config.c +++ b/usr.sbin/relayd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.37 2019/05/31 15:15:37 reyk Exp $ */ +/* $OpenBSD: config.c,v 1.38 2019/05/31 15:25:57 reyk Exp $ */ /* * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -104,6 +104,7 @@ config_init(struct relayd *env) env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT; env->sc_proto_default.tcpbacklog = RELAY_BACKLOG; env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT; + TAILQ_INIT(&env->sc_proto_default.tlscerts); (void)strlcpy(env->sc_proto_default.tlsciphers, TLSCIPHERS_DEFAULT, sizeof(env->sc_proto_default.tlsciphers)); @@ -146,6 +147,7 @@ config_purge(struct relayd *env, u_int reset) struct netroute *nr; struct router *rt; struct ca_pkey *pkey; + struct keyname *keyname; u_int what; what = ps->ps_what[privsep_process] & reset; @@ -191,6 +193,12 @@ config_purge(struct relayd *env, u_int reset) free(proto->style); free(proto->tlscapass); free(proto); + while ((keyname = + TAILQ_FIRST(&proto->tlscerts)) != NULL) { + TAILQ_REMOVE(&proto->tlscerts, keyname, entry); + free(keyname->name); + free(keyname); + } } env->sc_protocount = 0; } @@ -696,6 +704,7 @@ config_getproto(struct relayd *env, struct imsg *imsg) } TAILQ_INIT(&proto->rules); + TAILQ_INIT(&proto->tlscerts); proto->tlscapass = NULL; TAILQ_INSERT_TAIL(env->sc_protos, proto, entry); diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index bb1765ebe33..6cdbba67d5f 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.237 2019/05/31 15:15:37 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.238 2019/05/31 15:25:57 reyk Exp $ */ /* * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -169,8 +169,8 @@ typedef struct { %token ALL APPEND BACKLOG BACKUP BUFFER CA CACHE SET CHECK CIPHERS CODE %token COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT PASS BLOCK EXTERNAL FILENAME %token FORWARD FROM HASH HEADER HEADERLEN HOST HTTP ICMP INCLUDE INET INET6 -%token INTERFACE INTERVAL IP LABEL LISTEN VALUE LOADBALANCE LOG LOOKUP METHOD -%token MODE NAT NO DESTINATION NODELAY NOTHING ON PARENT PATH PFTAG PORT +%token INTERFACE INTERVAL IP KEYPAIR LABEL LISTEN VALUE LOADBALANCE LOG LOOKUP +%token METHOD MODE NAT NO DESTINATION NODELAY NOTHING ON PARENT PATH PFTAG PORT %token PREFORK PRIORITY PROTO QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST %token RESPONSE RETRY QUICK RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION %token SNMP SOCKET SPLICE SSL STICKYADDR STYLE TABLE TAG TAGGED TCP TIMEOUT TLS @@ -1029,6 +1029,7 @@ proto : relay_proto PROTO STRING { p->tcpbacklog = RELAY_BACKLOG; p->httpheaderlen = RELAY_DEFHEADERLENGTH; TAILQ_INIT(&p->rules); + TAILQ_INIT(&p->tlscerts); (void)strlcpy(p->tlsciphers, TLSCIPHERS_DEFAULT, sizeof(p->tlsciphers)); (void)strlcpy(p->tlsecdhecurves, TLSECDHECURVES_DEFAULT, @@ -1257,6 +1258,22 @@ tlsflags : SESSION TICKETS { proto->tickets = 1; } } free($3); } + | KEYPAIR STRING { + struct keyname *name; + + if (strlen($2) >= PATH_MAX) { + yyerror("keypair name too long"); + free($2); + YYERROR; + } + if ((name = calloc(1, sizeof(*name))) == NULL) { + yyerror("calloc"); + free($2); + YYERROR; + } + name->name = $2; + TAILQ_INSERT_TAIL(&proto->tlscerts, name, entry); + } | NO flag { proto->tlsflags &= ~($2); } | flag { proto->tlsflags |= $1; } ; @@ -1723,6 +1740,7 @@ relay : RELAY STRING { } '{' optnl relayopts_l '}' { struct relay *r; struct relay_config *rlconf = &rlay->rl_conf; + struct keyname *name; if (relay_findbyname(conf, rlconf->name) != NULL || relay_findbyaddr(conf, rlconf) != NULL) { @@ -1754,11 +1772,21 @@ relay : RELAY STRING { rlay->rl_conf.proto = conf->sc_proto_default.id; } - if (relay_load_certfiles(conf, rlay) == -1) { + if (TAILQ_EMPTY(&rlay->rl_proto->tlscerts) && + relay_load_certfiles(conf, rlay, NULL) == -1) { yyerror("cannot load certificates for relay %s", rlay->rl_conf.name); YYERROR; } + TAILQ_FOREACH(name, &rlay->rl_proto->tlscerts, entry) { + if (relay_load_certfiles(conf, + rlay, name->name) == -1) { + yyerror("cannot load keypair %s" + " for relay %s", name->name, + rlay->rl_conf.name); + YYERROR; + } + } conf->sc_relaycount++; SPLAY_INIT(&rlay->rl_sessions); @@ -2317,6 +2345,7 @@ lookup(char *s) { "interval", INTERVAL }, { "ip", IP }, { "key", KEY }, + { "keypair", KEYPAIR }, { "label", LABEL }, { "least-states", LEASTSTATES }, { "listen", LISTEN }, @@ -3292,7 +3321,7 @@ relay_inherit(struct relay *ra, struct relay *rb) goto err; } - if (relay_load_certfiles(conf, rb) == -1) { + if (relay_load_certfiles(conf, rb, NULL) == -1) { yyerror("cannot load certificates for relay %s", rb->rl_conf.name); goto err; diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c index 74ecc21a360..47edff9e077 100644 --- a/usr.sbin/relayd/relayd.c +++ b/usr.sbin/relayd/relayd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.c,v 1.178 2019/05/31 15:15:37 reyk Exp $ */ +/* $OpenBSD: relayd.c,v 1.179 2019/05/31 15:25:57 reyk Exp $ */ /* * Copyright (c) 2007 - 2016 Reyk Floeter <reyk@openbsd.org> @@ -1318,10 +1318,10 @@ relay_load_fd(int fd, off_t *len) } int -relay_load_certfiles(struct relayd *env, struct relay *rlay) +relay_load_certfiles(struct relayd *env, struct relay *rlay, const char *name) { char certfile[PATH_MAX]; - char hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + char hbuf[PATH_MAX]; struct protocol *proto = rlay->rl_proto; struct relay_cert *cert; int useport = htons(rlay->rl_conf.port); @@ -1356,7 +1356,11 @@ relay_load_certfiles(struct relayd *env, struct relay *rlay) if ((rlay->rl_conf.flags & F_TLS) == 0) return (0); - if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL) + if (name == NULL && + print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL) + goto fail; + else if (name != NULL && + strlcpy(hbuf, name, sizeof(hbuf)) >= sizeof(hbuf)) goto fail; if (snprintf(certfile, sizeof(certfile), diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index ebfafc3f2de..9421661e8bc 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.189 2019/05/10 09:15:00 reyk Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.190 2019/05/31 15:25:57 reyk Exp $ .\" .\" Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org> .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -15,7 +15,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: May 10 2019 $ +.Dd $Mdocdate: May 31 2019 $ .Dt RELAYD.CONF 5 .Os .Sh NAME @@ -682,27 +682,10 @@ Like the previous directive, but for redirections with rdr-to in .Xc Specify the address and port for the relay to listen on. The relay will accept incoming connections to the specified address. -.Pp If the .Ic tls keyword is present, the relay will accept connections using the encrypted TLS protocol. -The relay will attempt to look up a private key in -.Pa /etc/ssl/private/address:port.key -and a public certificate in -.Pa /etc/ssl/address:port.crt , -where -.Ar address -is the specified IP address and -.Ar port -is the specified port that the relay listens on. -If these files are not present, the relay will continue to look in -.Pa /etc/ssl/private/address.key -and -.Pa /etc/ssl/address.crt . -See -.Xr ssl 8 -for details about SSL/TLS server certificates. .It Ic protocol Ar name Use the specified protocol definition for the relay. The generic TCP protocol options will be used by default; @@ -963,6 +946,25 @@ Values higher than 1024 bits can cause incompatibilities with older TLS clients. The default is .Ic no edh . +.It Ic keypair Ar name +The relay will attempt to look up a private key in +.Pa /etc/ssl/private/name:port.key +and a public certificate in +.Pa /etc/ssl/name:port.crt , +where +.Ar port +is the specified port that the relay listens on. +If these files are not present, the relay will continue to look in +.Pa /etc/ssl/private/name.key +and +.Pa /etc/ssl/name.crt . +This option can be specified multiple times for TLS Server Name Indication. +If not specified, +a keypair will be loaded using the specified IP address of the relay as +.Ar name . +See +.Xr ssl 8 +for details about SSL/TLS server certificates. .It Ic no cipher-server-preference Prefer the client's cipher list over the server's preferences when choosing a cipher for the connection. diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index ec76c38c795..4314cec0a6b 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.257 2019/05/31 15:15:37 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.258 2019/05/31 15:25:57 reyk Exp $ */ /* * Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org> @@ -714,6 +714,12 @@ struct relay_ticket_key { #define HTTPFLAG_WEBSOCKETS 0x01 +struct keyname { + TAILQ_ENTRY(keyname) entry; + char *name; +}; +TAILQ_HEAD(keynamelist, keyname); + struct protocol { objid_t id; u_int32_t flags; @@ -732,6 +738,7 @@ struct protocol { char tlscacert[PATH_MAX]; char tlscakey[PATH_MAX]; char *tlscapass; + struct keynamelist tlscerts; char name[MAX_NAME_SIZE]; int tickets; enum prototype type; @@ -1312,7 +1319,8 @@ struct ca_pkey *pkey_add(struct relayd *, EVP_PKEY *, char *hash); struct relay_cert *cert_add(struct relayd *, objid_t); struct relay_cert *cert_find(struct relayd *, objid_t); char *relay_load_fd(int, off_t *); -int relay_load_certfiles(struct relayd *, struct relay *); +int relay_load_certfiles(struct relayd *, struct relay *, + const char *); int expand_string(char *, size_t, const char *, const char *); void translate_string(char *); void purge_key(char **, off_t); |