Hi,
relayd uses privsep to mitigate the risk of potential attacks.
OpenSSL's SSL code wasn't designed with privsep in mind. We already
have a hack to load the keys and certificates in the parent process
and to send them via imsg to the chroot'ed relays; OpenSSL normally
wants to load them from files.
This diff goes a bit further by moving the private keys to a new
separate process instead of copying them to the relays. A custom RSA
engine is used by the SSL/TLS code of the relay processes to send RSA
private key encryption/decryption requests to the new ca process (I
used the name ca because something similar exists in iked) instead
of operating on the private key directly.
The diff is still experimental, misses support for the SSL inspection,
probably client mode and hasn't been tested very well. The following
configuration has been tested:
relay wwwssl {
listen on $ext_addr port 443 ssl
forward to 127.0.0.1 port 80
}
It may impact performance because it adds a little for the RSA
communication between the processes, but SSL only does it once to get
the session keys and RSA is already slow.
I would like to get some first thoughts / feedback.
Reyk
Index: Makefile
===
RCS file: /cvs/src/usr.sbin/relayd/Makefile,v
retrieving revision 1.24
diff -u -p -u -p -r1.24 Makefile
--- Makefile18 Jan 2014 05:54:51 - 1.24
+++ Makefile9 Apr 2014 14:02:37 -
@@ -1,10 +1,12 @@
# $OpenBSD: Makefile,v 1.24 2014/01/18 05:54:51 martynas Exp $
PROG= relayd
-SRCS= parse.y log.c control.c ssl.c ssl_privsep.c \
- relayd.c pfe.c pfe_filter.c pfe_route.c hce.c relay.c \
- relay_http.c relay_udp.c carp.c check_icmp.c check_tcp.c \
- check_script.c name2id.c snmp.c shuffle.c proc.c config.c
+SRCS= parse.y
+SRCS+= ca.c carp.c check_icmp.c check_script.c check_tcp.c \
+ config.c control.c hce.c log.c name2id.c \
+ pfe.c pfe_filter.c pfe_route.c proc.c \
+ relay.c relay_http.c relay_udp.c relayd.c \
+ shuffle.c snmp.c ssl.c ssl_privsep.c
MAN= relayd.8 relayd.conf.5
LDADD= -levent -lssl -lcrypto -lutil
Index: ca.c
===
RCS file: ca.c
diff -N ca.c
--- /dev/null 1 Jan 1970 00:00:00 -
+++ ca.c9 Apr 2014 14:02:37 -
@@ -0,0 +1,414 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2014 Reyk Floeter r...@openbsd.org
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include sys/param.h
+#include sys/queue.h
+#include sys/socket.h
+#include sys/uio.h
+
+#include net/if.h
+#include netinet/in.h
+
+#include limits.h
+#include event.h
+#include fcntl.h
+#include unistd.h
+#include string.h
+#include stdlib.h
+#include errno.h
+
+#include openssl/pem.h
+#include openssl/evp.h
+#include openssl/rsa.h
+#include openssl/engine.h
+
+#include relayd.h
+
+voidca_init(struct privsep *, struct privsep_proc *p, void *);
+
+int ca_dispatch_parent(int, struct privsep_proc *, struct imsg *);
+int ca_dispatch_relay(int, struct privsep_proc *, struct imsg *);
+
+int rsae_pub_enc(int, const u_char *, u_char *, RSA *, int);
+int rsae_pub_dec(int,const u_char *, u_char *, RSA *, int);
+int rsae_priv_enc(int, const u_char *, u_char *, RSA *, int);
+int rsae_priv_dec(int, const u_char *, u_char *, RSA *, int);
+int rsae_mod_exp(BIGNUM *, const BIGNUM *, RSA *, BN_CTX *);
+int rsae_bn_mod_exp(BIGNUM *, const BIGNUM *, const BIGNUM *,
+ const BIGNUM *, BN_CTX *, BN_MONT_CTX *);
+int rsae_init(RSA *);
+int rsae_finish(RSA *);
+int rsae_sign(int, const u_char *, u_int,
+ u_char *, u_int *, const RSA *);
+int rsae_verify(int dtype, const u_char *m, u_int,
+ const u_char *, u_int, const RSA *);
+int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *);
+
+static struct relayd *env = NULL;
+extern int proc_id;
+
+static struct privsep_proc procs[] = {
+ { parent, PROC_PARENT,ca_dispatch_parent },
+ { relay, PROC_RELAY, ca_dispatch_relay },
+};
+
+pid_t
+ca(struct privsep *ps, struct privsep_proc *p)
+{
+ env =