summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2014-08-06 02:04:43 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2014-08-06 02:04:43 +0000
commita272708f606d45e97b412e86a1675227de893faf (patch)
treeae3de18f2555f0c6e47b81f617b3f94abec8124e /usr.sbin
parent7f18874c52d06c659bc6f09a1c0ffba1fbdd3a62 (diff)
Load the SSL public/private keys in the parent process, then provide them
to the privsep process via imsg. This allows the keys to be moved out of the chroot (now /etc/ssl/server.crt, /etc/ssl/private/server.key). ok reyk@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/httpd/config.c38
-rw-r--r--usr.sbin/httpd/httpd.810
-rw-r--r--usr.sbin/httpd/httpd.h14
-rw-r--r--usr.sbin/httpd/parse.y9
-rw-r--r--usr.sbin/httpd/server.c74
5 files changed, 126 insertions, 19 deletions
diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c
index 9eb8dd801c1..95c80a8b635 100644
--- a/usr.sbin/httpd/config.c
+++ b/usr.sbin/httpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.19 2014/08/05 18:01:10 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.20 2014/08/06 02:04:42 jsing Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -184,6 +184,14 @@ config_setserver(struct httpd *env, struct server *srv)
c = 0;
iov[c].iov_base = &s;
iov[c++].iov_len = sizeof(s);
+ if (srv->srv_conf.ssl_cert_len != 0) {
+ iov[c].iov_base = srv->srv_conf.ssl_cert;
+ iov[c++].iov_len = srv->srv_conf.ssl_cert_len;
+ }
+ if (srv->srv_conf.ssl_key_len != 0) {
+ iov[c].iov_base = srv->srv_conf.ssl_key;
+ iov[c++].iov_len = srv->srv_conf.ssl_key_len;
+ }
if (id == PROC_SERVER &&
(srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) {
@@ -313,7 +321,7 @@ config_getserver(struct httpd *env, struct imsg *imsg)
#ifdef DEBUG
struct privsep *ps = env->sc_ps;
#endif
- struct server *srv;
+ struct server *srv = NULL;
struct server_config srv_conf;
u_int8_t *p = imsg->data;
size_t s;
@@ -322,6 +330,12 @@ config_getserver(struct httpd *env, struct imsg *imsg)
memcpy(&srv_conf, p, sizeof(srv_conf));
s = sizeof(srv_conf);
+ if ((u_int)(IMSG_DATA_SIZE(imsg) - s) <
+ (srv_conf.ssl_cert_len + srv_conf.ssl_key_len)) {
+ log_debug("%s: invalid message length", __func__);
+ goto fail;
+ }
+
/* Check if server with matching listening socket already exists */
if ((srv = server_byaddr((struct sockaddr *)
&srv_conf.ss, srv_conf.port)) != NULL) {
@@ -354,7 +368,27 @@ config_getserver(struct httpd *env, struct imsg *imsg)
srv->srv_conf.name,
printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
+ if (srv->srv_conf.ssl_cert_len != 0) {
+ if ((srv->srv_conf.ssl_cert = get_data(p + s,
+ srv->srv_conf.ssl_cert_len)) == NULL)
+ goto fail;
+ s += srv->srv_conf.ssl_cert_len;
+ }
+ if (srv->srv_conf.ssl_key_len != 0) {
+ if ((srv->srv_conf.ssl_key = get_data(p + s,
+ srv->srv_conf.ssl_key_len)) == NULL)
+ goto fail;
+ s += srv->srv_conf.ssl_key_len;
+ }
+
return (0);
+
+ fail:
+ free(srv->srv_conf.ssl_cert);
+ free(srv->srv_conf.ssl_key);
+ free(srv);
+
+ return (-1);
}
int
diff --git a/usr.sbin/httpd/httpd.8 b/usr.sbin/httpd/httpd.8
index 050bfcdeff2..f7c9da88b39 100644
--- a/usr.sbin/httpd/httpd.8
+++ b/usr.sbin/httpd/httpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.8,v 1.41 2014/08/04 18:12:15 reyk Exp $
+.\" $OpenBSD: httpd.8,v 1.42 2014/08/06 02:04:42 jsing Exp $
.\"
.\" Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -14,7 +14,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: August 4 2014 $
+.Dd $Mdocdate: August 6 2014 $
.Dt HTTPD 8
.Os
.Sh NAME
@@ -36,10 +36,10 @@ Default configuration file.
.Ux Ns -domain
socket used for communication with
.Nm .
-.It /var/www/conf/server.key
-Default SSL/TLS server key.
-.It /var/www/conf/server.crt
+.It /etc/ssl/server.crt
Default SSL/TLS server certificate.
+.It /etc/ssl/private/server.key
+Default SSL/TLS server key.
.It /var/www/logs/access.log
Default access log file.
.It /var/www/logs/error.log
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index 74fa3c5dbc5..0983ce22500 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.46 2014/08/05 18:01:10 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.47 2014/08/06 02:04:42 jsing Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -38,8 +38,8 @@
#define HTTPD_LOGROOT "/logs"
#define HTTPD_ACCESS_LOG "access.log"
#define HTTPD_ERROR_LOG "error.log"
-#define HTTPD_SSL_KEY "/conf/server.key"
-#define HTTPD_SSL_CERT "/conf/server.crt"
+#define HTTPD_SSL_KEY "/etc/ssl/private/server.key"
+#define HTTPD_SSL_CERT "/etc/ssl/server.crt"
#define FD_RESERVE 5
#define SERVER_MAX_CLIENTS 1024
@@ -367,6 +367,13 @@ struct server_config {
struct timeval timeout;
u_int32_t maxrequests;
+ char *ssl_cert;
+ off_t ssl_cert_len;
+ char *ssl_cert_file;
+ char *ssl_key;
+ off_t ssl_key_len;
+ char *ssl_key_file;
+
u_int16_t flags;
u_int8_t tcpflags;
int tcpbufsiz;
@@ -446,6 +453,7 @@ int cmdline_symset(char *);
/* server.c */
pid_t server(struct privsep *, struct privsep_proc *);
+int server_ssl_load_keypair(struct server *);
int server_privinit(struct server *);
void server_purge(struct server *);
int server_socket_af(struct sockaddr_storage *, in_port_t);
diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y
index 91e18bed818..9daf57c7592 100644
--- a/usr.sbin/httpd/parse.y
+++ b/usr.sbin/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.28 2014/08/05 18:01:10 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.29 2014/08/06 02:04:42 jsing Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -233,6 +233,8 @@ server : SERVER STRING {
s->srv_conf.maxrequests = SERVER_MAXREQUESTS;
s->srv_conf.flags |= SRVFLAG_LOG;
s->srv_conf.logformat = LOG_FORMAT_COMMON;
+ s->srv_conf.ssl_cert_file = HTTPD_SSL_CERT;
+ s->srv_conf.ssl_key_file = HTTPD_SSL_KEY;
if (last_server_id == INT_MAX) {
yyerror("too many servers defined");
@@ -250,6 +252,11 @@ server : SERVER STRING {
free($2);
YYERROR;
}
+ if (server_ssl_load_keypair(srv) == -1) {
+ yyerror("failed to load public/private keys "
+ "for server %s", srv->srv_conf.name);
+ YYERROR;
+ }
srv = NULL;
srv_conf = NULL;
}
diff --git a/usr.sbin/httpd/server.c b/usr.sbin/httpd/server.c
index 7f675e1249e..8f4b7ce61ae 100644
--- a/usr.sbin/httpd/server.c
+++ b/usr.sbin/httpd/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.29 2014/08/05 15:36:59 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.30 2014/08/06 02:04:42 jsing Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -116,6 +116,57 @@ server_privinit(struct server *srv)
return (0);
}
+static char *
+server_load_file(const char *filename, off_t *len)
+{
+ struct stat st;
+ off_t size;
+ char *buf = NULL;
+ int fd;
+
+ if ((fd = open(filename, O_RDONLY)) == -1)
+ return (NULL);
+ if (fstat(fd, &st) != 0)
+ goto fail;
+ size = st.st_size;
+ if ((buf = calloc(1, size + 1)) == NULL)
+ goto fail;
+ if (read(fd, buf, size) != size)
+ goto fail;
+
+ close(fd);
+
+ *len = size;
+ return (buf);
+
+ fail:
+ free(buf);
+ close(fd);
+
+ return (NULL);
+}
+
+int
+server_ssl_load_keypair(struct server *srv)
+{
+ if ((srv->srv_conf.flags & SRVFLAG_SSL) == 0)
+ return (0);
+
+ if ((srv->srv_conf.ssl_cert = server_load_file(
+ srv->srv_conf.ssl_cert_file, &srv->srv_conf.ssl_cert_len)) == NULL)
+ return (-1);
+ log_debug("%s: using certificate %s", __func__,
+ srv->srv_conf.ssl_cert_file);
+
+ if ((srv->srv_conf.ssl_key = server_load_file(
+ srv->srv_conf.ssl_key_file, &srv->srv_conf.ssl_key_len)) == NULL)
+ return (-1);
+ log_debug("%s: using private key %s", __func__,
+ srv->srv_conf.ssl_key_file);
+
+ return (0);
+}
+
int
server_ssl_init(struct server *srv)
{
@@ -137,12 +188,10 @@ server_ssl_init(struct server *srv)
return (-1);
}
- /*
- * XXX Make these configurable and move keys out of the chroot.
- * XXX The RSA privsep code in relayd should be adopted to ressl.
- */
- ressl_config_set_cert_file(srv->srv_ressl_config, HTTPD_SSL_CERT);
- ressl_config_set_key_file(srv->srv_ressl_config, HTTPD_SSL_KEY);
+ ressl_config_set_cert_mem(srv->srv_ressl_config,
+ srv->srv_conf.ssl_cert, srv->srv_conf.ssl_cert_len);
+ ressl_config_set_key_mem(srv->srv_ressl_config,
+ srv->srv_conf.ssl_key, srv->srv_conf.ssl_key_len);
if (ressl_configure(srv->srv_ressl_ctx, srv->srv_ressl_config) != 0) {
log_warn("%s: failed to configure SSL - %s", __func__,
@@ -150,6 +199,12 @@ server_ssl_init(struct server *srv)
return (-1);
}
+ /* We're now done with the key... */
+ explicit_bzero(srv->srv_conf.ssl_key, srv->srv_conf.ssl_key_len);
+ free(srv->srv_conf.ssl_key);
+ srv->srv_conf.ssl_key = NULL;
+ srv->srv_conf.ssl_key_len = 0;
+
return (0);
}
@@ -223,8 +278,11 @@ server_purge(struct server *srv)
TAILQ_REMOVE(&srv->srv_hosts, srv_conf, entry);
/* It might point to our own "default" entry */
- if (srv_conf != &srv->srv_conf)
+ if (srv_conf != &srv->srv_conf) {
+ free(srv_conf->ssl_cert);
+ free(srv_conf->ssl_key);
free(srv_conf);
+ }
}
ressl_config_free(srv->srv_ressl_config);