aboutsummaryrefslogtreecommitdiff
path: root/httpd/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'httpd/server.c')
-rw-r--r--httpd/server.c160
1 files changed, 105 insertions, 55 deletions
diff --git a/httpd/server.c b/httpd/server.c
index 21593bf..849b92a 100644
--- a/httpd/server.c
+++ b/httpd/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.75 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.88 2016/08/15 16:12:34 jsing Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -65,7 +65,7 @@ void server_tls_readcb(int, short, void *);
void server_tls_writecb(int, short, void *);
void server_accept(int, short, void *);
-void server_accept_tls(int, short, void *);
+void server_handshake_tls(int, short, void *);
void server_input(struct client *);
void server_inflight_dec(struct client *, const char *);
@@ -133,6 +133,30 @@ server_privinit(struct server *srv)
}
int
+server_tls_cmp(struct server *s1, struct server *s2)
+{
+ struct server_config *sc1, *sc2;
+
+ sc1 = &s1->srv_conf;
+ sc2 = &s2->srv_conf;
+
+ if (sc1->tls_protocols != sc2->tls_protocols)
+ return (-1);
+ if (strcmp(sc1->tls_cert_file, sc2->tls_cert_file) != 0)
+ return (-1);
+ if (strcmp(sc1->tls_key_file, sc2->tls_key_file) != 0)
+ return (-1);
+ if (strcmp(sc1->tls_ciphers, sc2->tls_ciphers) != 0)
+ return (-1);
+ if (strcmp(sc1->tls_dhe_params, sc2->tls_dhe_params) != 0)
+ return (-1);
+ if (strcmp(sc1->tls_ecdhe_curve, sc2->tls_ecdhe_curve) != 0)
+ return (-1);
+
+ return (0);
+}
+
+int
server_tls_load_keypair(struct server *srv)
{
if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0)
@@ -162,18 +186,18 @@ server_tls_init(struct server *srv)
if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0)
return (0);
- log_debug("%s: setting up TLS for %s", __func__, srv->srv_conf.name);
+ log_debug("%s: setting up tls for %s", __func__, srv->srv_conf.name);
if (tls_init() != 0) {
- log_warn("%s: failed to initialise tls", __func__);
+ log_warnx("%s: failed to initialise tls", __func__);
return (-1);
}
if ((srv->srv_tls_config = tls_config_new()) == NULL) {
- log_warn("%s: failed to get tls config", __func__);
+ log_warnx("%s: failed to get tls config", __func__);
return (-1);
}
if ((srv->srv_tls_ctx = tls_server()) == NULL) {
- log_warn("%s: failed to get tls server", __func__);
+ log_warnx("%s: failed to get tls server", __func__);
return (-1);
}
@@ -182,33 +206,33 @@ server_tls_init(struct server *srv)
if (tls_config_set_ciphers(srv->srv_tls_config,
srv->srv_conf.tls_ciphers) != 0) {
- log_warn("%s: failed to set tls ciphers", __func__);
+ log_warnx("%s: failed to set tls ciphers: %s",
+ __func__, tls_config_error(srv->srv_tls_config));
return (-1);
}
if (tls_config_set_dheparams(srv->srv_tls_config,
srv->srv_conf.tls_dhe_params) != 0) {
- log_warn("%s: failed to set tls dhe params", __func__);
+ log_warnx("%s: failed to set tls dhe params: %s",
+ __func__, tls_config_error(srv->srv_tls_config));
return (-1);
}
if (tls_config_set_ecdhecurve(srv->srv_tls_config,
srv->srv_conf.tls_ecdhe_curve) != 0) {
- log_warn("%s: failed to set tls ecdhe curve", __func__);
+ log_warnx("%s: failed to set tls ecdhe curve: %s",
+ __func__, tls_config_error(srv->srv_tls_config));
return (-1);
}
- if (tls_config_set_cert_mem(srv->srv_tls_config,
- srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len) != 0) {
- log_warn("%s: failed to set tls cert", __func__);
- return (-1);
- }
- if (tls_config_set_key_mem(srv->srv_tls_config,
+ if (tls_config_set_keypair_mem(srv->srv_tls_config,
+ srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len,
srv->srv_conf.tls_key, srv->srv_conf.tls_key_len) != 0) {
- log_warn("%s: failed to set tls key", __func__);
+ log_warnx("%s: failed to set tls certificate/key: %s",
+ __func__, tls_config_error(srv->srv_tls_config));
return (-1);
}
if (tls_configure(srv->srv_tls_ctx, srv->srv_tls_config) != 0) {
- log_warn("%s: failed to configure TLS - %s", __func__,
+ log_warnx("%s: failed to configure tls - %s", __func__,
tls_error(srv->srv_tls_ctx));
return (-1);
}
@@ -244,6 +268,9 @@ server_init(struct privsep *ps, struct privsep_proc *p, void *arg)
/* Unlimited file descriptors (use system limits) */
socket_rlimit(-1);
+ if (pledge("stdio rpath inet unix recvfd", NULL) == -1)
+ fatal("pledge");
+
#if 0
/* Schedule statistics timer */
evtimer_set(&env->sc_statev, server_statistics, NULL);
@@ -313,7 +340,6 @@ server_purge(struct server *srv)
void
serverconfig_free(struct server_config *srv_conf)
{
- free(srv_conf->auth);
free(srv_conf->return_uri);
free(srv_conf->tls_cert_file);
free(srv_conf->tls_key_file);
@@ -392,6 +418,33 @@ server_foreach(int (*srv_cb)(struct server *,
return (0);
}
+struct server *
+server_match(struct server *s2, int match_name)
+{
+ struct server *s1;
+
+ /* Attempt to find matching server. */
+ TAILQ_FOREACH(s1, env->sc_servers, srv_entry) {
+ if ((s1->srv_conf.flags & SRVFLAG_LOCATION) != 0)
+ continue;
+ if (match_name) {
+ if (strcmp(s1->srv_conf.name, s2->srv_conf.name) != 0)
+ continue;
+ }
+ if (s1->srv_conf.port != s2->srv_conf.port)
+ continue;
+ if (sockaddr_cmp(
+ (struct sockaddr *)&s1->srv_conf.ss,
+ (struct sockaddr *)&s2->srv_conf.ss,
+ s1->srv_conf.prefixlen) != 0)
+ continue;
+
+ return (s1);
+ }
+
+ return (NULL);
+}
+
int
server_socket_af(struct sockaddr_storage *ss, in_port_t port)
{
@@ -439,7 +492,8 @@ server_socket(struct sockaddr_storage *ss, in_port_t port,
if (server_socket_af(ss, port) == -1)
goto bad;
- s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM, IPPROTO_TCP) : fd;
+ s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM | SOCK_NONBLOCK,
+ IPPROTO_TCP) : fd;
if (s == -1)
goto bad;
@@ -455,8 +509,6 @@ server_socket(struct sockaddr_storage *ss, in_port_t port,
sizeof(int)) == -1)
goto bad;
}
- if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
- goto bad;
if (srv_conf->tcpflags & TCPFLAG_BUFSIZ) {
val = srv_conf->tcpbufsiz;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
@@ -564,7 +616,7 @@ server_tls_readcb(int fd, short event, void *arg)
char rbuf[IBUF_READ_SIZE];
int what = EVBUFFER_READ;
int howmuch = IBUF_READ_SIZE;
- int ret;
+ ssize_t ret;
size_t len;
if (event == EV_TIMEOUT) {
@@ -575,13 +627,14 @@ server_tls_readcb(int fd, short event, void *arg)
if (bufev->wm_read.high != 0)
howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
- ret = tls_read(clt->clt_tls_ctx, rbuf, howmuch, &len);
- if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) {
+ ret = tls_read(clt->clt_tls_ctx, rbuf, howmuch);
+ if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
goto retry;
- } else if (ret != 0) {
+ } else if (ret < 0) {
what |= EVBUFFER_ERROR;
goto err;
}
+ len = ret;
if (len == 0) {
what |= EVBUFFER_EOF;
@@ -622,7 +675,7 @@ server_tls_writecb(int fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
struct client *clt = bufev->cbarg;
- int ret;
+ ssize_t ret;
short what = EVBUFFER_WRITE;
size_t len;
@@ -634,13 +687,14 @@ server_tls_writecb(int fd, short event, void *arg)
if (EVBUFFER_LENGTH(bufev->output)) {
ret = tls_write(clt->clt_tls_ctx,
EVBUFFER_DATA(bufev->output),
- EVBUFFER_LENGTH(bufev->output), &len);
- if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) {
+ EVBUFFER_LENGTH(bufev->output));
+ if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
goto retry;
- } else if (ret != 0) {
+ } else if (ret < 0) {
what |= EVBUFFER_ERROR;
goto err;
}
+ len = ret;
evbuffer_drain(bufev->output, len);
}
@@ -742,8 +796,6 @@ server_write(struct bufferevent *bev, void *arg)
void
server_dump(struct client *clt, const void *buf, size_t len)
{
- size_t outlen;
-
if (!len)
return;
@@ -754,7 +806,7 @@ server_dump(struct client *clt, const void *buf, size_t len)
* error message before gracefully closing the client.
*/
if (clt->clt_tls_ctx != NULL)
- (void)tls_write(clt->clt_tls_ctx, buf, len, &outlen);
+ (void)tls_write(clt->clt_tls_ctx, buf, len);
else
(void)write(clt->clt_s, buf, len);
}
@@ -857,9 +909,6 @@ server_accept(int fd, short event, void *arg)
if (server_clients >= SERVER_MAX_CLIENTS)
goto err;
- if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
- goto err;
-
if ((clt = calloc(1, sizeof(*clt))) == NULL)
goto err;
@@ -916,8 +965,13 @@ server_accept(int fd, short event, void *arg)
}
if (srv->srv_conf.flags & SRVFLAG_TLS) {
+ if (tls_accept_socket(srv->srv_tls_ctx, &clt->clt_tls_ctx,
+ clt->clt_s) != 0) {
+ server_close(clt, "failed to setup tls context");
+ return;
+ }
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_READ,
- server_accept_tls, &clt->clt_tv_start,
+ server_handshake_tls, &clt->clt_tv_start,
&srv->srv_conf.timeout, clt);
return;
}
@@ -938,39 +992,36 @@ server_accept(int fd, short event, void *arg)
}
void
-server_accept_tls(int fd, short event, void *arg)
+server_handshake_tls(int fd, short event, void *arg)
{
struct client *clt = (struct client *)arg;
struct server *srv = (struct server *)clt->clt_srv;
int ret;
if (event == EV_TIMEOUT) {
- server_close(clt, "TLS accept timeout");
+ server_close(clt, "tls handshake timeout");
return;
}
- if (srv->srv_tls_ctx == NULL)
+ if (srv->srv_tls_ctx == NULL || clt->clt_tls_ctx == NULL)
fatalx("NULL tls context");
- ret = tls_accept_socket(srv->srv_tls_ctx, &clt->clt_tls_ctx,
- clt->clt_s);
- if (ret == TLS_READ_AGAIN) {
+ ret = tls_handshake(clt->clt_tls_ctx);
+ if (ret == 0) {
+ server_input(clt);
+ } else if (ret == TLS_WANT_POLLIN) {
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_READ,
- server_accept_tls, &clt->clt_tv_start,
+ server_handshake_tls, &clt->clt_tv_start,
&srv->srv_conf.timeout, clt);
- } else if (ret == TLS_WRITE_AGAIN) {
+ } else if (ret == TLS_WANT_POLLOUT) {
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_WRITE,
- server_accept_tls, &clt->clt_tv_start,
+ server_handshake_tls, &clt->clt_tv_start,
&srv->srv_conf.timeout, clt);
- } else if (ret != 0) {
- log_warnx("%s: TLS accept failed - %s", __func__,
- tls_error(srv->srv_tls_ctx));
- server_close(clt, "TLS accept failed");
- return;
+ } else {
+ log_warnx("%s: tls handshake failed - %s", __func__,
+ tls_error(clt->clt_tls_ctx));
+ server_close(clt, "tls handshake failed");
}
-
- server_input(clt);
- return;
}
void
@@ -1020,8 +1071,7 @@ server_sendlog(struct server_config *srv_conf, int cmd, const char *emsg, ...)
iov[1].iov_base = msg;
iov[1].iov_len = strlen(msg) + 1;
- if (proc_composev_imsg(env->sc_ps, PROC_LOGGER, -1, cmd, -1, iov,
- 2) != 0) {
+ if (proc_composev(env->sc_ps, PROC_LOGGER, cmd, iov, 2) != 0) {
log_warn("%s: failed to compose imsg", __func__);
return;
}