summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2019-05-31 15:25:58 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2019-05-31 15:25:58 +0000
commitade6fd10cfcef327575dffa177dcb4502de7c4e1 (patch)
treeec8aaf45d2a18b1eca0c0142c522d9d6974bffb2 /usr.sbin
parentd17761b242ae6c21aeb21d5fce043a4b92f90cc9 (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.c11
-rw-r--r--usr.sbin/relayd/parse.y39
-rw-r--r--usr.sbin/relayd/relayd.c12
-rw-r--r--usr.sbin/relayd/relayd.conf.540
-rw-r--r--usr.sbin/relayd/relayd.h12
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);