aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2016-08-15 20:54:53 +0200
committerReyk Floeter <reyk@esdenera.com>2016-08-15 20:54:53 +0200
commitf6babe9f2d05966903998909432e8b873b69192f (patch)
tree0a86b5b92f4a8ee3e04f5039b5c1fc70842e6aa0
parent5a83fddddbf34b5da95507bbca99427616d37f79 (diff)
downloadhttpd-f6babe9f2d05966903998909432e8b873b69192f.tar.gz
httpd-f6babe9f2d05966903998909432e8b873b69192f.zip
sync
-rw-r--r--httpd/config.c87
-rw-r--r--httpd/control.c31
-rw-r--r--httpd/http.h3
-rw-r--r--httpd/httpd.86
-rw-r--r--httpd/httpd.c152
-rw-r--r--httpd/httpd.conf.576
-rw-r--r--httpd/httpd.h61
-rw-r--r--httpd/log.c171
-rw-r--r--httpd/logger.c9
-rw-r--r--httpd/parse.y95
-rw-r--r--httpd/patterns.c5
-rw-r--r--httpd/patterns.h3
-rw-r--r--httpd/proc.c77
-rw-r--r--httpd/server.c160
-rw-r--r--httpd/server_fcgi.c17
-rw-r--r--httpd/server_file.c12
-rw-r--r--httpd/server_http.c60
17 files changed, 607 insertions, 418 deletions
diff --git a/httpd/config.c b/httpd/config.c
index 8536028..4f8ef4c 100644
--- a/httpd/config.c
+++ b/httpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.43 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.47 2016/08/15 14:14:55 jsing Exp $ */
/*
* Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -113,7 +113,7 @@ config_setreset(struct httpd *env, unsigned int reset)
if ((reset & ps->ps_what[id]) == 0 ||
id == privsep_process)
continue;
- proc_compose_imsg(ps, id, -1, IMSG_CTL_RESET, -1,
+ proc_compose(ps, id, IMSG_CTL_RESET,
&reset, sizeof(reset));
}
@@ -151,8 +151,8 @@ config_getcfg(struct httpd *env, struct imsg *imsg)
what = ps->ps_what[privsep_process];
if (privsep_process != PROC_PARENT)
- proc_compose_imsg(env->sc_ps, PROC_PARENT, -1,
- IMSG_CFG_DONE, -1, NULL, 0);
+ proc_compose(env->sc_ps, PROC_PARENT,
+ IMSG_CFG_DONE, NULL, 0);
return (0);
}
@@ -205,7 +205,7 @@ config_setserver(struct httpd *env, struct server *srv)
else if ((fd = dup(srv->srv_s)) == -1)
return (-1);
if (proc_composev_imsg(ps, id, n,
- IMSG_CFG_SERVER, fd, iov, c) != 0) {
+ IMSG_CFG_SERVER, -1, fd, iov, c) != 0) {
log_warn("%s: failed to compose "
"IMSG_CFG_SERVER imsg for `%s'",
__func__, srv->srv_conf.name);
@@ -216,7 +216,7 @@ config_setserver(struct httpd *env, struct server *srv)
/* Configure TLS if necessary. */
config_settls(env, srv);
} else {
- if (proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1,
+ if (proc_composev(ps, id, IMSG_CFG_SERVER,
iov, c) != 0) {
log_warn("%s: failed to compose "
"IMSG_CFG_SERVER imsg for `%s'",
@@ -233,61 +233,56 @@ int
config_settls(struct httpd *env, struct server *srv)
{
struct privsep *ps = env->sc_ps;
+ struct server_config *srv_conf = &srv->srv_conf;
struct tls_config tls;
struct iovec iov[2];
size_t c;
- if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0)
+ if ((srv_conf->flags & SRVFLAG_TLS) == 0)
return (0);
- log_debug("%s: configuring TLS for %s", __func__, srv->srv_conf.name);
+ log_debug("%s: configuring tls for %s", __func__, srv_conf->name);
- if (srv->srv_conf.tls_cert_len != 0) {
- DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__,
- srv->srv_conf.name, srv->srv_conf.id,
- ps->ps_title[PROC_SERVER], srv->srv_s);
+ if (srv_conf->tls_cert_len != 0) {
+ DPRINTF("%s: sending tls cert \"%s[%u]\" to %s fd %d", __func__,
+ srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
+ srv->srv_s);
memset(&tls, 0, sizeof(tls));
- tls.id = srv->srv_conf.id;
- tls.port = srv->srv_conf.port;
- memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss));
- tls.tls_cert_len = srv->srv_conf.tls_cert_len;
+ tls.id = srv_conf->id;
+ tls.tls_cert_len = srv_conf->tls_cert_len;
c = 0;
iov[c].iov_base = &tls;
iov[c++].iov_len = sizeof(tls);
- iov[c].iov_base = srv->srv_conf.tls_cert;
- iov[c++].iov_len = srv->srv_conf.tls_cert_len;
+ iov[c].iov_base = srv_conf->tls_cert;
+ iov[c++].iov_len = srv_conf->tls_cert_len;
- if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1,
- iov, c) != 0) {
+ if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
- "`%s'", __func__, srv->srv_conf.name);
+ "`%s'", __func__, srv_conf->name);
return (-1);
}
}
- if (srv->srv_conf.tls_key_len != 0) {
- DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__,
- srv->srv_conf.name, srv->srv_conf.id,
- ps->ps_title[PROC_SERVER], srv->srv_s);
+ if (srv_conf->tls_key_len != 0) {
+ DPRINTF("%s: sending tls key \"%s[%u]\" to %s fd %d", __func__,
+ srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
+ srv->srv_s);
memset(&tls, 0, sizeof(tls));
- tls.id = srv->srv_conf.id;
- tls.port = srv->srv_conf.port;
- memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss));
- tls.tls_key_len = srv->srv_conf.tls_key_len;
+ tls.id = srv_conf->id;
+ tls.tls_key_len = srv_conf->tls_key_len;
c = 0;
iov[c].iov_base = &tls;
iov[c++].iov_len = sizeof(tls);
- iov[c].iov_base = srv->srv_conf.tls_key;
- iov[c++].iov_len = srv->srv_conf.tls_key_len;
+ iov[c].iov_base = srv_conf->tls_key;
+ iov[c++].iov_len = srv_conf->tls_key_len;
- if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1,
- iov, c) != 0) {
+ if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
- "`%s'", __func__, srv->srv_conf.name);
+ "`%s'", __func__, srv_conf->name);
return (-1);
}
}
@@ -565,7 +560,7 @@ config_gettls(struct httpd *env, struct imsg *imsg)
#ifdef DEBUG
struct privsep *ps = env->sc_ps;
#endif
- struct server *srv = NULL;
+ struct server_config *srv_conf = NULL;
struct tls_config tls_conf;
uint8_t *p = imsg->data;
size_t s;
@@ -580,27 +575,25 @@ config_gettls(struct httpd *env, struct imsg *imsg)
goto fail;
}
- /* Find server with matching listening socket. */
- if ((srv = server_byaddr((struct sockaddr *)
- &tls_conf.ss, tls_conf.port)) == NULL) {
+ if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) {
log_debug("%s: server not found", __func__);
goto fail;
}
- DPRINTF("%s: %s %d TLS configuration \"%s[%u]\"", __func__,
+ DPRINTF("%s: %s %d tls configuration \"%s[%u]\"", __func__,
ps->ps_title[privsep_process], ps->ps_instance,
- srv->srv_conf.name, srv->srv_conf.id);
+ srv_conf->name, srv_conf->id);
if (tls_conf.tls_cert_len != 0) {
- srv->srv_conf.tls_cert_len = tls_conf.tls_cert_len;
- if ((srv->srv_conf.tls_cert = get_data(p + s,
+ srv_conf->tls_cert_len = tls_conf.tls_cert_len;
+ if ((srv_conf->tls_cert = get_data(p + s,
tls_conf.tls_cert_len)) == NULL)
goto fail;
s += tls_conf.tls_cert_len;
}
if (tls_conf.tls_key_len != 0) {
- srv->srv_conf.tls_key_len = tls_conf.tls_key_len;
- if ((srv->srv_conf.tls_key = get_data(p + s,
+ srv_conf->tls_key_len = tls_conf.tls_key_len;
+ if ((srv_conf->tls_key = get_data(p + s,
tls_conf.tls_key_len)) == NULL)
goto fail;
s += tls_conf.tls_key_len;
@@ -628,8 +621,7 @@ config_setmedia(struct httpd *env, struct media_type *media)
DPRINTF("%s: sending media \"%s\" to %s", __func__,
media->media_name, ps->ps_title[id]);
- proc_compose_imsg(ps, id, -1, IMSG_CFG_MEDIA, -1,
- media, sizeof(*media));
+ proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media));
}
return (0);
@@ -676,8 +668,7 @@ config_setauth(struct httpd *env, struct auth *auth)
DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__,
auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]);
- proc_compose_imsg(ps, id, -1, IMSG_CFG_AUTH, -1,
- auth, sizeof(*auth));
+ proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth));
}
return (0);
diff --git a/httpd/control.c b/httpd/control.c
index 5c71545..c29cd5b 100644
--- a/httpd/control.c
+++ b/httpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.7 2015/05/28 17:08:08 florian Exp $ */
+/* $OpenBSD: control.c,v 1.9 2015/12/05 13:15:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -50,7 +50,7 @@ control_init(struct privsep *ps, struct control_sock *cs)
if (cs->cs_name == NULL)
return (0);
- if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) {
log_warn("%s: socket", __func__);
return (-1);
}
@@ -93,7 +93,6 @@ control_init(struct privsep *ps, struct control_sock *cs)
return (-1);
}
- socket_set_blockmode(fd, BM_NONBLOCK);
cs->cs_fd = fd;
cs->cs_env = env;
@@ -143,8 +142,8 @@ control_accept(int listenfd, short event, void *arg)
return;
len = sizeof(sun);
- if ((connfd = accept(listenfd,
- (struct sockaddr *)&sun, &len)) == -1) {
+ if ((connfd = accept4(listenfd,
+ (struct sockaddr *)&sun, &len, SOCK_NONBLOCK)) == -1) {
/*
* Pause accept if we are out of file descriptors, or
* libevent will haunt us here too.
@@ -160,8 +159,6 @@ control_accept(int listenfd, short event, void *arg)
return;
}
- socket_set_blockmode(connfd, BM_NONBLOCK);
-
if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) {
close(connfd);
log_warn("%s: calloc", __func__);
@@ -233,7 +230,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
}
if (event & EV_READ) {
- if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
+ if (((n = imsg_read(&c->iev.ibuf)) == -1 && errno != EAGAIN) ||
+ n == 0) {
control_close(fd, cs);
return;
}
@@ -314,20 +312,3 @@ control_imsg_forward(struct imsg *imsg)
0, imsg->hdr.pid, -1, imsg->data,
imsg->hdr.len - IMSG_HEADER_SIZE);
}
-
-void
-socket_set_blockmode(int fd, enum blockmodes bm)
-{
- int flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
- fatal("fcntl F_GETFL");
-
- if (bm == BM_NONBLOCK)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
-
- if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
- fatal("fcntl F_SETFL");
-}
diff --git a/httpd/http.h b/httpd/http.h
index 9042342..410704f 100644
--- a/httpd/http.h
+++ b/httpd/http.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http.h,v 1.13 2015/06/11 18:49:09 reyk Exp $ */
+/* $OpenBSD: http.h,v 1.14 2016/08/01 21:15:30 benno Exp $ */
/*
* Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -241,6 +241,7 @@ struct http_descriptor {
enum httpmethod http_method;
int http_chunked;
char *http_version;
+ unsigned int http_status;
/* Rewritten path remains NULL if not used */
char *http_path_alias;
diff --git a/httpd/httpd.8 b/httpd/httpd.8
index fcb3e42..7084120 100644
--- a/httpd/httpd.8
+++ b/httpd/httpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.8,v 1.51 2015/03/26 19:16:57 jmc Exp $
+.\" $OpenBSD: httpd.8,v 1.52 2016/06/10 18:32:40 jmc 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: March 26 2015 $
+.Dd $Mdocdate: June 10 2016 $
.Dt HTTPD 8
.Os
.Sh NAME
@@ -65,7 +65,7 @@ Check that the configuration is valid, but don't start any servers.
Verbose mode.
Multiple
.Fl v
-options increases the verbosity.
+options increase the verbosity.
.El
.Sh FILES
.Bl -tag -width "/etc/ssl/private/server.key" -compact
diff --git a/httpd/httpd.c b/httpd/httpd.c
index f6decea..fae7c53 100644
--- a/httpd/httpd.c
+++ b/httpd/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.39 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.56 2016/06/10 12:09:48 florian Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -33,10 +33,12 @@
#include <string.h>
#include <signal.h>
#include <getopt.h>
+#include <netdb.h>
#include <fnmatch.h>
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <syslog.h>
#include <unistd.h>
#include <ctype.h>
#include <pwd.h>
@@ -189,7 +191,8 @@ main(int argc, char *argv[])
}
}
- log_init(debug ? debug : 1); /* log to stderr until daemonized */
+ /* log to stderr until daemonized */
+ log_init(debug ? debug : 1, LOG_DAEMON);
argc -= optind;
if (argc > 0)
@@ -218,7 +221,7 @@ main(int argc, char *argv[])
/* Configure the control socket */
ps->ps_csock.cs_name = NULL;
- log_init(debug);
+ log_init(debug, LOG_DAEMON);
log_verbose(verbose);
if (!debug && daemon(1, 0) == -1)
@@ -244,8 +247,11 @@ main(int argc, char *argv[])
}
proc_init(ps, procs, nitems(procs));
+ log_procinit("parent");
- setproctitle("parent");
+ if (pledge("stdio rpath wpath cpath inet dns proc ioctl sendfd",
+ NULL) == -1)
+ fatal("pledge");
event_init();
@@ -331,8 +337,7 @@ parent_configure(struct httpd *env)
cf.cf_opts = env->sc_opts;
cf.cf_flags = env->sc_flags;
- proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, -1,
- &cf, sizeof(cf));
+ proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf));
}
ret = 0;
@@ -377,8 +382,7 @@ parent_reload(struct httpd *env, unsigned int reset, const char *filename)
void
parent_reopen(struct httpd *env)
{
- proc_compose_imsg(env->sc_ps, PROC_LOGGER, -1, IMSG_CTL_REOPEN,
- -1, NULL, 0);
+ proc_compose(env->sc_ps, PROC_LOGGER, IMSG_CTL_REOPEN, NULL, 0);
}
void
@@ -397,8 +401,7 @@ parent_configure_done(struct httpd *env)
if (id == privsep_process)
continue;
- proc_compose_imsg(env->sc_ps, id, -1, IMSG_CTL_START,
- -1, NULL, 0);
+ proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0);
}
}
}
@@ -454,8 +457,7 @@ parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg)
if (IMSG_DATA_SIZE(imsg) > 0)
str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
parent_reload(env, CONFIG_RELOAD, str);
- if (str != NULL)
- free(str);
+ free(str);
break;
case IMSG_CTL_SHUTDOWN:
parent_shutdown(env);
@@ -565,7 +567,7 @@ canonicalize_host(const char *host, char *name, size_t len)
for (i = j = 0; i < plen; i++) {
if (j >= (len - 1))
goto fail;
- c = tolower(host[i]);
+ c = tolower((unsigned char)host[i]);
if ((c == '.') && (j == 0 || name[j - 1] == '.'))
continue;
name[j++] = c;
@@ -602,7 +604,8 @@ url_decode(char *url)
switch (*p) {
case '%':
/* Encoding character is followed by two hex chars */
- if (!(isxdigit(p[1]) && isxdigit(p[2])))
+ if (!(isxdigit((unsigned char)p[1]) &&
+ isxdigit((unsigned char)p[2])))
return (NULL);
hex[0] = p[1];
@@ -741,7 +744,7 @@ escape_html(const char* src)
{
char *dp, *dst;
- /* We need 5 times the memory if every letter is "<" or ">". */
+ /* We need 5 times the memory if every letter is "&" */
if ((dst = calloc(5, strlen(src) + 1)) == NULL)
return NULL;
@@ -827,17 +830,13 @@ char *
get_string(uint8_t *ptr, size_t len)
{
size_t i;
- char *str;
for (i = 0; i < len; i++)
- if (!(isprint(ptr[i]) || isspace(ptr[i])))
+ if (!(isprint((unsigned char)ptr[i]) ||
+ isspace((unsigned char)ptr[i])))
break;
- if ((str = calloc(1, i + 1)) == NULL)
- return (NULL);
- memcpy(str, ptr, i);
-
- return (str);
+ return strndup(ptr, i);
}
void *
@@ -845,7 +844,7 @@ get_data(uint8_t *ptr, size_t len)
{
uint8_t *data;
- if ((data = calloc(1, len)) == NULL)
+ if ((data = malloc(len)) == NULL)
return (NULL);
memcpy(data, ptr, len);
@@ -959,7 +958,7 @@ accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
return (-1);
}
- if ((ret = accept(sockfd, addr, addrlen)) > -1) {
+ if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) {
(*counter)++;
DPRINTF("%s: inflight incremented, now %d",__func__, *counter);
}
@@ -1001,11 +1000,13 @@ kv_set(struct kv *kv, char *fmt, ...)
va_list ap;
char *value = NULL;
struct kv *ckv;
+ int ret;
va_start(ap, fmt);
- if (vasprintf(&value, fmt, ap) == -1)
- return (-1);
+ ret = vasprintf(&value, fmt, ap);
va_end(ap);
+ if (ret == -1)
+ return (-1);
/* Remove all children */
while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) {
@@ -1015,8 +1016,7 @@ kv_set(struct kv *kv, char *fmt, ...)
}
/* Set the new value */
- if (kv->kv_value != NULL)
- free(kv->kv_value);
+ free(kv->kv_value);
kv->kv_value = value;
return (0);
@@ -1027,14 +1027,15 @@ kv_setkey(struct kv *kv, char *fmt, ...)
{
va_list ap;
char *key = NULL;
+ int ret;
va_start(ap, fmt);
- if (vasprintf(&key, fmt, ap) == -1)
- return (-1);
+ ret = vasprintf(&key, fmt, ap);
va_end(ap);
+ if (ret == -1)
+ return (-1);
- if (kv->kv_key != NULL)
- free(kv->kv_key);
+ free(kv->kv_key);
kv->kv_key = key;
return (0);
@@ -1089,13 +1090,9 @@ kv_purge(struct kvtree *keys)
void
kv_free(struct kv *kv)
{
- if (kv->kv_key != NULL) {
- free(kv->kv_key);
- }
+ free(kv->kv_key);
kv->kv_key = NULL;
- if (kv->kv_value != NULL) {
- free(kv->kv_value);
- }
+ free(kv->kv_value);
kv->kv_value = NULL;
memset(kv, 0, sizeof(*kv));
}
@@ -1202,8 +1199,8 @@ void
media_delete(struct mediatypes *types, struct media_type *media)
{
RB_REMOVE(mediatypes, types, media);
- if (media->media_encoding != NULL)
- free(media->media_encoding);
+
+ free(media->media_encoding);
free(media);
}
@@ -1302,3 +1299,78 @@ auth_free(struct serverauth *serverauth, struct auth *auth)
{
TAILQ_REMOVE(serverauth, auth, auth_entry);
}
+
+
+const char *
+print_host(struct sockaddr_storage *ss, char *buf, size_t len)
+{
+ if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
+ buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
+ buf[0] = '\0';
+ return (NULL);
+ }
+ return (buf);
+}
+
+const char *
+print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
+{
+ struct timeval tv;
+ unsigned long h, sec, min;
+
+ timerclear(&tv);
+ timersub(a, b, &tv);
+ sec = tv.tv_sec % 60;
+ min = tv.tv_sec / 60 % 60;
+ h = tv.tv_sec / 60 / 60;
+
+ snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
+ return (buf);
+}
+
+const char *
+printb_flags(const uint32_t v, const char *bits)
+{
+ static char buf[2][BUFSIZ];
+ static int idx = 0;
+ int i, any = 0;
+ char c, *p, *r;
+
+ p = r = buf[++idx % 2];
+ memset(p, 0, BUFSIZ);
+
+ if (bits) {
+ bits++;
+ while ((i = *bits++)) {
+ if (v & (1 << (i - 1))) {
+ if (any) {
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ any = 1;
+ for (; (c = *bits) > 32; bits++) {
+ if (c == '_')
+ *p++ = ' ';
+ else
+ *p++ =
+ tolower((unsigned char)c);
+ }
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ }
+
+ return (r);
+}
+
+void
+getmonotime(struct timeval *tv)
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts))
+ fatal("clock_gettime");
+
+ TIMESPEC_TO_TIMEVAL(tv, &ts);
+}
diff --git a/httpd/httpd.conf.5 b/httpd/httpd.conf.5
index 785f726..2bd3ec7 100644
--- a/httpd/httpd.conf.5
+++ b/httpd/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.68 2015/07/19 05:17:27 reyk Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.73 2016/05/09 19:36:54 tj Exp $
.\"
.\" Copyright (c) 2014, 2015 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: July 19 2015 $
+.Dd $Mdocdate: May 9 2016 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -274,6 +274,67 @@ root directory of
.Xr httpd 8
and defaults to
.Pa /run/slowcgi.sock .
+.Pp
+The FastCGI handler will be given the following variables:
+.Pp
+.Bl -tag -width GATEWAY_INTERFACE -offset indent -compact
+.It Ic DOCUMENT_ROOT
+The document root in which the script is located as configured by the
+.Ic root
+option for the server or location that matches the request.
+.It Ic GATEWAY_INTERFACE
+The revision of the CGI specification used.
+.It Ic HTTP_*
+Additional HTTP headers the connected client sent in the request, if
+any.
+.It Ic HTTPS
+A variable that is set to
+.Qq on
+when the server has been configured to use TLS.
+This variable is omitted otherwise.
+.It Ic REQUEST_URI
+The path and optional query string as requested by the connected client.
+.It Ic DOCUMENT_URI
+The canonicalized request path, possibly with a slash or
+directory index file name appended.
+This is the same as
+.Ic PATH_INFO
+appended to
+.Ic SCRIPT_NAME .
+.It Ic SCRIPT_NAME
+The virtual URI path to the script.
+.It Ic PATH_INFO
+The optional path appended after the script name in the request path.
+This variable is an empty string if no path is appended after the
+script name.
+.It Ic SCRIPT_FILENAME
+The absolute, physical path to the script within the
+.Xr chroot 2
+directory.
+.It Ic QUERY_STRING
+The optional query string of the request.
+This variable is an empty
+string if there is no query string in the request.
+.It Ic REMOTE_ADDR
+The IP address of the connected client.
+.It Ic REMOTE_PORT
+The TCP source port of the connected client.
+.It Ic REMOTE_USER
+The remote user when using HTTP authentication.
+.It Ic REQUEST_METHOD
+The HTTP method the connected client used when making the request.
+.It Ic SERVER_ADDR
+The configured IP address of the server.
+.It Ic SERVER_NAME
+The name of the server.
+.It Ic SERVER_PORT
+The configured TCP server port of the server.
+.It Ic SERVER_PROTOCOL
+The revision of the HTTP specification used.
+.It Ic SERVER_SOFTWARE
+The server software name of
+.Xr httpd 8 .
+.El
.It Ic hsts Oo Ar option Oc
Enable HTTP Strict Transport Security.
Valid options are:
@@ -299,11 +360,14 @@ The
argument will be matched against the request path with shell globbing rules.
A location section may include most of the server configuration rules
except
+.Ic alias ,
.Ic connection ,
+.Ic hsts ,
.Ic listen on ,
-.Ic location
+.Ic location ,
+.Ic tcp
and
-.Ic tcp .
+.Ic tls .
.It Ic location match Ar path Brq ...
Like the
.Ic location
@@ -530,7 +594,7 @@ server "default" {
types {
text/css css
text/html html htm
- text/txt txt
+ text/plain txt
image/gif gif
image/jpeg jpeg jpg
image/png png
@@ -584,7 +648,7 @@ directive:
.Bd -literal -offset indent
server "example.com" {
listen on 10.0.0.1 port 80
- block return 301 "http://www.example.com/"
+ block return 301 "http://www.example.com$REQUEST_URI"
}
server "www.example.com" {
diff --git a/httpd/httpd.h b/httpd/httpd.h
index f1c6090..595cce9 100644
--- a/httpd/httpd.h
+++ b/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.97 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.106 2016/08/15 16:12:34 jsing Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -52,7 +52,7 @@
#define HTTPD_LOGVIS VIS_NL|VIS_TAB|VIS_CSTYLE
#define HTTPD_TLS_CERT "/etc/ssl/server.crt"
#define HTTPD_TLS_KEY "/etc/ssl/private/server.key"
-#define HTTPD_TLS_CIPHERS "HIGH:!aNULL"
+#define HTTPD_TLS_CIPHERS "compat"
#define HTTPD_TLS_DHE_PARAMS "none"
#define HTTPD_TLS_ECDHE_CURVE "auto"
#define FD_RESERVE 5
@@ -164,11 +164,6 @@ struct {
int fd;
} control_state;
-enum blockmodes {
- BM_NORMAL,
- BM_NONBLOCK
-};
-
struct imsgev {
struct imsgbuf ibuf;
void (*handler)(int, short, void *);
@@ -454,7 +449,7 @@ struct server_config {
char auth_realm[NAME_MAX];
uint32_t auth_id;
- struct auth *auth;
+ const struct auth *auth;
int return_code;
char *return_uri;
@@ -470,9 +465,6 @@ TAILQ_HEAD(serverhosts, server_config);
struct tls_config {
uint32_t id;
- in_port_t port;
- struct sockaddr_storage ss;
-
size_t tls_cert_len;
size_t tls_key_len;
};
@@ -524,7 +516,6 @@ void control_dispatch_imsg(int, short, void *);
void control_imsg_forward(struct imsg *);
struct ctl_conn *
control_connbyfd(int);
-void socket_set_blockmode(int, enum blockmodes);
extern struct ctl_connlist ctl_conns;
@@ -535,6 +526,7 @@ int cmdline_symset(char *);
/* server.c */
pid_t server(struct privsep *, struct privsep_proc *);
+int server_tls_cmp(struct server *, struct server *);
int server_tls_load_keypair(struct server *);
int server_privinit(struct server *);
void server_purge(struct server *);
@@ -569,6 +561,8 @@ struct server_config *
serverconfig_byid(uint32_t);
int server_foreach(int (*)(struct server *,
struct server_config *, void *), void *);
+struct server *
+ server_match(struct server *, int);
SPLAY_PROTOTYPE(client_tree, client, clt_nodes, server_client_cmp);
@@ -664,22 +658,31 @@ RB_PROTOTYPE(mediatypes, media_type, media_entry, media_cmp);
struct auth *auth_add(struct serverauth *, struct auth *);
struct auth *auth_byid(struct serverauth *, uint32_t);
void auth_free(struct serverauth *, struct auth *);
+const char *print_host(struct sockaddr_storage *, char *, size_t);
+const char *print_time(struct timeval *, struct timeval *, char *, size_t);
+const char *printb_flags(const uint32_t, const char *);
+void getmonotime(struct timeval *);
/* log.c */
-void log_init(int);
+void log_init(int, int);
+void log_procinit(const char *);
void log_verbose(int);
-void log_warn(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-void log_warnx(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-void log_info(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-void log_debug(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-void logit(int, const char *, ...) __attribute__((__format__ (printf, 2, 3)));
-void vlog(int, const char *, va_list) __attribute__((__format__ (printf, 2, 0)));
-__dead void fatal(const char *);
-__dead void fatalx(const char *);
-const char *print_host(struct sockaddr_storage *, char *, size_t);
-const char *print_time(struct timeval *, struct timeval *, char *, size_t);
-const char *printb_flags(const uint32_t, const char *);
-void getmonotime(struct timeval *);
+void log_warn(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_warnx(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_info(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_debug(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void logit(int, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+void vlog(int, const char *, va_list)
+ __attribute__((__format__ (printf, 2, 0)));
+__dead void fatal(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+__dead void fatalx(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
/* proc.c */
void proc_init(struct privsep *, struct privsep_proc *, unsigned int);
@@ -691,9 +694,13 @@ pid_t proc_run(struct privsep *, struct privsep_proc *,
void (*)(struct privsep *, struct privsep_proc *, void *), void *);
void proc_range(struct privsep *, enum privsep_procid, int *, int *);
int proc_compose_imsg(struct privsep *, enum privsep_procid, int,
- uint16_t, int, void *, uint16_t);
+ u_int16_t, u_int32_t, int, void *, u_int16_t);
+int proc_compose(struct privsep *, enum privsep_procid,
+ uint16_t, void *, uint16_t);
int proc_composev_imsg(struct privsep *, enum privsep_procid, int,
- uint16_t, int, const struct iovec *, int);
+ u_int16_t, u_int32_t, int, const struct iovec *, int);
+int proc_composev(struct privsep *, enum privsep_procid,
+ uint16_t, const struct iovec *, int);
int proc_forward_imsg(struct privsep *, struct imsg *,
enum privsep_procid, int);
struct imsgbuf *
diff --git a/httpd/log.c b/httpd/log.c
index 16e57d0..1f6ff49 100644
--- a/httpd/log.c
+++ b/httpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.6 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: log.c,v 1.10 2015/12/07 12:13:51 reyk Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -11,50 +11,66 @@
* 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 MIND, 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.
+ * 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/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <errno.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <syslog.h>
+#include <errno.h>
#include <time.h>
-#include <netdb.h>
-#include <ctype.h>
-
-#include "httpd.h"
-int debug;
-int verbose;
-
-void vlog(int, const char *, va_list)
- __attribute__((__format__ (printf, 2, 0)));
-void logit(int, const char *, ...)
+int debug;
+int verbose;
+const char *log_procname;
+
+void log_init(int, int);
+void log_procinit(const char *);
+void log_verbose(int);
+void log_warn(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_warnx(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_info(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void log_debug(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+void logit(int, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
+void vlog(int, const char *, va_list)
+ __attribute__((__format__ (printf, 2, 0)));
+__dead void fatal(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
+__dead void fatalx(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
void
-log_init(int n_debug)
+log_init(int n_debug, int facility)
{
extern char *__progname;
debug = n_debug;
verbose = n_debug;
+ log_procinit(__progname);
if (!debug)
- openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+ openlog(__progname, LOG_PID | LOG_NDELAY, facility);
tzset();
}
void
+log_procinit(const char *procname)
+{
+ if (procname != NULL)
+ log_procname = procname;
+}
+
+void
log_verbose(int v)
{
verbose = v;
@@ -146,98 +162,45 @@ log_debug(const char *emsg, ...)
}
}
-void
-fatal(const char *emsg)
+static void
+vfatal(const char *emsg, va_list ap)
{
- if (emsg == NULL)
- logit(LOG_CRIT, "fatal: %s", strerror(errno));
+ static char s[BUFSIZ];
+ const char *sep;
+
+ if (emsg != NULL) {
+ (void)vsnprintf(s, sizeof(s), emsg, ap);
+ sep = ": ";
+ } else {
+ s[0] = '\0';
+ sep = "";
+ }
+ if (errno)
+ logit(LOG_CRIT, "%s: %s%s%s",
+ log_procname, s, sep, strerror(errno));
else
- if (errno)
- logit(LOG_CRIT, "fatal: %s: %s",
- emsg, strerror(errno));
- else
- logit(LOG_CRIT, "fatal: %s", emsg);
-
- exit(1);
+ logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
}
void
-fatalx(const char *emsg)
-{
- errno = 0;
- fatal(emsg);
-}
-
-const char *
-print_host(struct sockaddr_storage *ss, char *buf, size_t len)
+fatal(const char *emsg, ...)
{
- if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
- buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
- buf[0] = '\0';
- return (NULL);
- }
- return (buf);
-}
-
-const char *
-print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
-{
- struct timeval tv;
- unsigned long h, sec, min;
-
- timerclear(&tv);
- timersub(a, b, &tv);
- sec = tv.tv_sec % 60;
- min = tv.tv_sec / 60 % 60;
- h = tv.tv_sec / 60 / 60;
-
- snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
- return (buf);
-}
-
-const char *
-printb_flags(const uint32_t v, const char *bits)
-{
- static char buf[2][BUFSIZ];
- static int idx = 0;
- int i, any = 0;
- char c, *p, *r;
-
- p = r = buf[++idx % 2];
- memset(p, 0, BUFSIZ);
-
- if (bits) {
- bits++;
- while ((i = *bits++)) {
- if (v & (1 << (i - 1))) {
- if (any) {
- *p++ = ',';
- *p++ = ' ';
- }
- any = 1;
- for (; (c = *bits) > 32; bits++) {
- if (c == '_')
- *p++ = ' ';
- else
- *p++ =
- tolower((unsigned char)c);
- }
- } else
- for (; *bits > 32; bits++)
- ;
- }
- }
+ va_list ap;
- return (r);
+ va_start(ap, emsg);
+ vfatal(emsg, ap);
+ va_end(ap);
+ exit(1);
}
void
-getmonotime(struct timeval *tv)
+fatalx(const char *emsg, ...)
{
- struct timespec ts;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- fatal("clock_gettime");
+ va_list ap;
- TIMESPEC_TO_TIMEVAL(tv, &ts);
+ errno = 0;
+ va_start(ap, emsg);
+ vfatal(emsg, ap);
+ va_end(ap);
+ exit(1);
}
diff --git a/httpd/logger.c b/httpd/logger.c
index 4d3b741..a212fb1 100644
--- a/httpd/logger.c
+++ b/httpd/logger.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: logger.c,v 1.13 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: logger.c,v 1.15 2015/12/02 15:13:00 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -70,6 +70,9 @@ logger_shutdown(void)
void
logger_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
+ if (pledge("stdio recvfd", NULL) == -1)
+ fatal("pledge");
+
if (config_init(ps->ps_env) == -1)
fatal("failed to initialize configuration");
@@ -118,7 +121,7 @@ logger_open_file(const char *name)
iov[1].iov_base = log->log_name;
iov[1].iov_len = strlen(log->log_name) + 1;
- if (proc_composev_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_LOG_OPEN, -1,
+ if (proc_composev(env->sc_ps, PROC_PARENT, IMSG_LOG_OPEN,
iov, 2) != 0) {
log_warn("%s: failed to compose IMSG_LOG_OPEN imsg", __func__);
goto err;
@@ -188,7 +191,7 @@ logger_open_priv(struct imsg *imsg)
return (-1);
}
- proc_compose_imsg(env->sc_ps, PROC_LOGGER, -1, IMSG_LOG_OPEN, fd,
+ proc_compose_imsg(env->sc_ps, PROC_LOGGER, -1, IMSG_LOG_OPEN, -1, fd,
&id, sizeof(id));
DPRINTF("%s: opened log file %s, fd %d", __func__, path, fd);
diff --git a/httpd/parse.y b/httpd/parse.y
index 8622d84..6900bc6 100644
--- a/httpd/parse.y
+++ b/httpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.76 2015/08/20 22:39:29 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.80 2016/08/15 16:12:34 jsing Exp $ */
/*
* Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -171,6 +171,14 @@ include : INCLUDE STRING {
;
varset : STRING '=' STRING {
+ char *s = $1;
+ while (*s++) {
+ if (isspace((unsigned char)*s)) {
+ yyerror("macro name cannot contain "
+ "whitespace");
+ YYERROR;
+ }
+ }
if (symset($1, $3, 0) == -1)
fatal("cannot store variable");
free($1);
@@ -275,24 +283,13 @@ server : SERVER optmatch STRING {
TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
} '{' optnl serveropts_l '}' {
- struct server *s = NULL, *sn;
+ struct server *s, *sn;
struct server_config *a, *b;
srv_conf = &srv->srv_conf;
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
- if ((s->srv_conf.flags &
- SRVFLAG_LOCATION) == 0 &&
- strcmp(s->srv_conf.name,
- srv->srv_conf.name) == 0 &&
- s->srv_conf.port == srv->srv_conf.port &&
- sockaddr_cmp(
- (struct sockaddr *)&s->srv_conf.ss,
- (struct sockaddr *)&srv->srv_conf.ss,
- s->srv_conf.prefixlen) == 0)
- break;
- }
- if (s != NULL) {
+ /* Check if the new server already exists. */
+ if (server_match(srv, 1) != NULL) {
yyerror("server \"%s\" defined twice",
srv->srv_conf.name);
serverconfig_free(srv_conf);
@@ -307,16 +304,39 @@ server : SERVER optmatch STRING {
YYERROR;
}
+ if ((s = server_match(srv, 0)) != NULL) {
+ if ((s->srv_conf.flags & SRVFLAG_TLS) !=
+ (srv->srv_conf.flags & SRVFLAG_TLS)) {
+ yyerror("server \"%s\": tls and "
+ "non-tls on same address/port",
+ srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYERROR;
+ }
+ if (server_tls_cmp(s, srv) != 0) {
+ yyerror("server \"%s\": tls "
+ "configuration mismatch on same "
+ "address/port",
+ srv->srv_conf.name);
+ serverconfig_free(srv_conf);
+ free(srv);
+ YYERROR;
+ }
+ }
+
if ((srv->srv_conf.flags & SRVFLAG_TLS) &&
srv->srv_conf.tls_protocols == 0) {
- yyerror("no TLS protocols");
+ yyerror("server \"%s\": no tls protocols",
+ srv->srv_conf.name);
+ serverconfig_free(srv_conf);
free(srv);
YYERROR;
}
if (server_tls_load_keypair(srv) == -1) {
- yyerror("failed to load public/private keys "
- "for server %s", srv->srv_conf.name);
+ yyerror("server \"%s\": failed to load "
+ "public/private keys", srv->srv_conf.name);
serverconfig_free(srv_conf);
free(srv);
YYERROR;
@@ -390,7 +410,7 @@ serveroptsl : LISTEN ON STRING opttls port {
sizeof(*alias))) == NULL)
fatal("out of memory");
- /* Add as an alias */
+ /* Add as an IP-based alias. */
s_conf = alias;
} else
s_conf = &srv->srv_conf;
@@ -408,9 +428,8 @@ serveroptsl : LISTEN ON STRING opttls port {
s_conf->prefixlen = h->prefixlen;
host_free(&al);
- if ($4) {
+ if ($4)
s_conf->flags |= SRVFLAG_TLS;
- }
if (alias != NULL) {
/* IP-based; use name match flags from parent */
@@ -460,10 +479,22 @@ serveroptsl : LISTEN ON STRING opttls port {
}
}
| tls {
+ struct server_config *sc;
+ int tls_flag = 0;
+
if (parentsrv != NULL) {
yyerror("tls configuration inside location");
YYERROR;
}
+
+ /* Ensure that at least one server has TLS enabled. */
+ TAILQ_FOREACH(sc, &srv->srv_hosts, entry) {
+ tls_flag |= (sc->flags & SRVFLAG_TLS);
+ }
+ if (tls_flag == 0) {
+ yyerror("tls options without tls listener");
+ YYERROR;
+ }
}
| root
| directory
@@ -708,7 +739,7 @@ tlsopts : CERTIFICATE STRING {
| PROTOCOLS STRING {
if (tls_config_parse_protocols(
&srv_conf->tls_protocols, $2) != 0) {
- yyerror("invalid TLS protocols");
+ yyerror("invalid tls protocols");
free($2);
YYERROR;
}
@@ -1723,7 +1754,7 @@ host_v4(const char *s)
return (NULL);
if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
+ fatal(__func__);
sain = (struct sockaddr_in *)&h->ss;
sain->sin_len = sizeof(struct sockaddr_in);
sain->sin_family = AF_INET;
@@ -1748,7 +1779,7 @@ host_v6(const char *s)
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(s, "0", &hints, &res) == 0) {
if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
+ fatal(__func__);
sa_in6 = (struct sockaddr_in6 *)&h->ss;
sa_in6->sin6_len = sizeof(struct sockaddr_in6);
sa_in6->sin6_family = AF_INET6;
@@ -1799,7 +1830,7 @@ host_dns(const char *s, struct addresslist *al, int max,
res->ai_family != AF_INET6)
continue;
if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
+ fatal(__func__);
if (port != NULL)
memcpy(&h->port, port, sizeof(h->port));
@@ -2020,19 +2051,7 @@ server_inherit(struct server *src, struct server_config *alias,
}
/* Check if the new server already exists */
- TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
- if ((s->srv_conf.flags &
- SRVFLAG_LOCATION) == 0 &&
- strcmp(s->srv_conf.name,
- dst->srv_conf.name) == 0 &&
- s->srv_conf.port == dst->srv_conf.port &&
- sockaddr_cmp(
- (struct sockaddr *)&s->srv_conf.ss,
- (struct sockaddr *)&dst->srv_conf.ss,
- s->srv_conf.prefixlen) == 0)
- break;
- }
- if (s != NULL) {
+ if (server_match(dst, 1) != NULL) {
yyerror("server \"%s\" defined twice",
dst->srv_conf.name);
serverconfig_free(&dst->srv_conf);
diff --git a/httpd/patterns.c b/httpd/patterns.c
index 42e4b25..c691078 100644
--- a/httpd/patterns.c
+++ b/httpd/patterns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: patterns.c,v 1.4 2015/08/18 08:26:39 reyk Exp $ */
+/* $OpenBSD: patterns.c,v 1.5 2016/02/14 18:20:59 semarie Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -26,7 +26,7 @@
/*
* Derived from Lua 5.3.1:
- * $Id: patterns.c,v 1.4 2015/08/18 08:26:39 reyk Exp $
+ * $Id: patterns.c,v 1.5 2016/02/14 18:20:59 semarie Exp $
* Standard library for string operations and pattern-matching
*/
@@ -708,5 +708,6 @@ str_match_free(struct str_match *m)
for (i = 0; i < m->sm_nmatch; i++)
free(m->sm_match[i]);
free(m->sm_match);
+ m->sm_match = NULL;
m->sm_nmatch = 0;
}
diff --git a/httpd/patterns.h b/httpd/patterns.h
index 74790b5..6dccd7b 100644
--- a/httpd/patterns.h
+++ b/httpd/patterns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: patterns.h,v 1.2 2015/06/26 17:26:29 semarie Exp $ */
+/* $OpenBSD: patterns.h,v 1.3 2015/12/12 19:59:43 mmcc Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -20,7 +20,6 @@
#define PATTERNS_H
#include <sys/types.h>
-#include <sys/cdefs.h>
#define MAXCAPTURES 32 /* Max no. of allowed captures in pattern */
#define MAXCCALLS 200 /* Max recusion depth in pattern matching */
diff --git a/httpd/proc.c b/httpd/proc.c
index 9ba7bbe..7a6124a 100644
--- a/httpd/proc.c
+++ b/httpd/proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.c,v 1.9 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: proc.c,v 1.15 2015/12/07 16:05:56 reyk Exp $ */
/*
* Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -41,6 +41,7 @@ int proc_ispeer(struct privsep_proc *, unsigned int, enum privsep_procid);
void proc_shutdown(struct privsep_proc *);
void proc_sig_handler(int, short, void *);
void proc_range(struct privsep *, enum privsep_procid, int *, int *);
+int proc_dispatch_null(int, struct privsep_proc *, struct imsg *);
int
proc_ispeer(struct privsep_proc *procs, unsigned int nproc,
@@ -160,6 +161,8 @@ proc_open(struct privsep *ps, struct privsep_proc *p,
for (proc = 0; proc < nproc; proc++) {
procs[proc].p_ps = ps;
procs[proc].p_env = ps->ps_env;
+ if (procs[proc].p_cb == NULL)
+ procs[proc].p_cb = proc_dispatch_null;
for (i = 0; i < ps->ps_instances[src]; i++) {
for (j = 0; j < ps->ps_instances[procs[proc].p_id];
@@ -171,13 +174,11 @@ proc_open(struct privsep *ps, struct privsep_proc *p,
if (pa->pp_pipes[procs[proc].p_id][j] != -1)
continue;
- if (socketpair(AF_UNIX, SOCK_STREAM,
+ if (socketpair(AF_UNIX,
+ SOCK_STREAM | SOCK_NONBLOCK,
PF_UNSPEC, fds) == -1)
fatal("socketpair");
- socket_set_blockmode(fds[0], BM_NONBLOCK);
- socket_set_blockmode(fds[1], BM_NONBLOCK);
-
pa->pp_pipes[procs[proc].p_id][j] = fds[0];
pb->pp_pipes[src][i] = fds[1];
}
@@ -328,7 +329,7 @@ proc_sig_handler(int sig, short event, void *arg)
pid_t
proc_run(struct privsep *ps, struct privsep_proc *p,
struct privsep_proc *procs, unsigned int nproc,
- void (*init)(struct privsep *, struct privsep_proc *, void *), void *arg)
+ void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg)
{
pid_t pid;
struct passwd *pw;
@@ -346,6 +347,8 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
case -1:
fatal("proc_run: cannot fork");
case 0:
+ log_procinit(p->p_title);
+
/* Set the process group of the current process */
setpgid(0, 0);
break;
@@ -357,10 +360,10 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
if (control_init(ps, &ps->ps_csock) == -1)
- fatalx(p->p_title);
+ fatalx(__func__);
TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
if (control_init(ps, rcs) == -1)
- fatalx(p->p_title);
+ fatalx(__func__);
}
/* Change root directory */
@@ -417,14 +420,14 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
TAILQ_INIT(&ctl_conns);
if (control_listen(&ps->ps_csock) == -1)
- fatalx(p->p_title);
+ fatalx(__func__);
TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
if (control_listen(rcs) == -1)
- fatalx(p->p_title);
+ fatalx(__func__);
}
- if (init != NULL)
- init(ps, p, arg);
+ if (run != NULL)
+ run(ps, p, arg);
event_dispatch();
@@ -449,8 +452,8 @@ proc_dispatch(int fd, short event, void *arg)
ibuf = &iev->ibuf;
if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal(title);
+ if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
+ fatal(__func__);
if (n == 0) {
/* this pipe is dead, so remove the event handler */
event_del(&iev->ev);
@@ -461,19 +464,19 @@ proc_dispatch(int fd, short event, void *arg)
if (event & EV_WRITE) {
if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
- fatal(title);
+ fatal(__func__);
}
for (;;) {
if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal(title);
+ fatal(__func__);
if (n == 0)
break;
#if DEBUG > 1
- log_debug("%s: %s %d got imsg %d from %s %d",
+ log_debug("%s: %s %d got imsg %d peerid %d from %s %d",
__func__, title, ps->ps_instance + 1,
- imsg.hdr.type, p->p_title, p->p_instance);
+ imsg.hdr.type, imsg.hdr.peerid, p->p_title, p->p_instance);
#endif
/*
@@ -495,16 +498,24 @@ proc_dispatch(int fd, short event, void *arg)
log_verbose(verbose);
break;
default:
- log_warnx("%s: %s %d got invalid imsg %d from %s %d",
+ log_warnx("%s: %s %d got invalid imsg %d peerid %d "
+ "from %s %d",
__func__, title, ps->ps_instance + 1,
- imsg.hdr.type, p->p_title, p->p_instance);
- fatalx(title);
+ imsg.hdr.type, imsg.hdr.peerid,
+ p->p_title, p->p_instance);
+ fatalx(__func__);
}
imsg_free(&imsg);
}
imsg_event_add(iev);
}
+int
+proc_dispatch_null(int fd, struct privsep_proc *p, struct imsg *imsg)
+{
+ return (-1);
+}
+
/*
* imsg helper functions
*/
@@ -567,14 +578,14 @@ proc_range(struct privsep *ps, enum privsep_procid id, int *n, int *m)
int
proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
- uint16_t type, int fd, void *data, uint16_t datalen)
+ uint16_t type, uint32_t peerid, int fd, void *data, uint16_t datalen)
{
int m;
proc_range(ps, id, &n, &m);
for (; n < m; n++) {
if (imsg_compose_event(&ps->ps_ievs[id][n],
- type, -1, 0, fd, data, datalen) == -1)
+ type, peerid, 0, fd, data, datalen) == -1)
return (-1);
}
@@ -582,26 +593,40 @@ proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
}
int
+proc_compose(struct privsep *ps, enum privsep_procid id,
+ uint16_t type, void *data, uint16_t datalen)
+{
+ return (proc_compose_imsg(ps, id, -1, type, -1, -1, data, datalen));
+}
+
+int
proc_composev_imsg(struct privsep *ps, enum privsep_procid id, int n,
- uint16_t type, int fd, const struct iovec *iov, int iovcnt)
+ uint16_t type, uint32_t peerid, int fd, const struct iovec *iov, int iovcnt)
{
int m;
proc_range(ps, id, &n, &m);
for (; n < m; n++)
if (imsg_composev_event(&ps->ps_ievs[id][n],
- type, -1, 0, fd, iov, iovcnt) == -1)
+ type, peerid, 0, fd, iov, iovcnt) == -1)
return (-1);
return (0);
}
int
+proc_composev(struct privsep *ps, enum privsep_procid id,
+ uint16_t type, const struct iovec *iov, int iovcnt)
+{
+ return (proc_composev_imsg(ps, id, -1, type, -1, -1, iov, iovcnt));
+}
+
+int
proc_forward_imsg(struct privsep *ps, struct imsg *imsg,
enum privsep_procid id, int n)
{
return (proc_compose_imsg(ps, id, n, imsg->hdr.type,
- imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg)));
+ imsg->hdr.peerid, imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg)));
}
struct imsgbuf *
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;
}
diff --git a/httpd/server_fcgi.c b/httpd/server_fcgi.c
index e7d9747..21ebeed 100644
--- a/httpd/server_fcgi.c
+++ b/httpd/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.64 2015/08/20 13:00:23 reyk Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.68 2016/04/24 20:09:45 chrisz Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -122,7 +122,8 @@ server_fcgi(struct httpd *env, struct client *clt)
struct sockaddr_un sun;
size_t len;
- if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ if ((fd = socket(AF_UNIX,
+ SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
goto fail;
memset(&sun, 0, sizeof(sun));
@@ -130,7 +131,7 @@ server_fcgi(struct httpd *env, struct client *clt)
len = strlcpy(sun.sun_path,
srv_conf->socket, sizeof(sun.sun_path));
if (len >= sizeof(sun.sun_path)) {
- errstr = "socket path to long";
+ errstr = "socket path too long";
goto fail;
}
sun.sun_len = len;
@@ -139,8 +140,6 @@ server_fcgi(struct httpd *env, struct client *clt)
goto fail;
}
- socket_set_blockmode(fd, BM_NONBLOCK);
-
memset(hbuf, 0, sizeof(hbuf));
clt->clt_fcgi_state = FCGI_READ_HEADER;
clt->clt_fcgi_toread = sizeof(struct fcgi_record_header);
@@ -243,12 +242,16 @@ server_fcgi(struct httpd *env, struct client *clt)
goto fail;
}
- if (desc->http_query)
+ if (desc->http_query) {
if (fcgi_add_param(&param, "QUERY_STRING", desc->http_query,
clt) == -1) {
errstr = "failed to encode param";
goto fail;
}
+ } else if (fcgi_add_param(&param, "QUERY_STRING", "", clt) == -1) {
+ errstr = "failed to encode param";
+ goto fail;
+ }
if (fcgi_add_param(&param, "DOCUMENT_ROOT", srv_conf->root,
clt) == -1) {
@@ -399,6 +402,8 @@ server_fcgi(struct httpd *env, struct client *clt)
free(script);
if (errstr == NULL)
errstr = strerror(errno);
+ if (fd != -1 && clt->clt_fd != fd)
+ close(fd);
server_abort_http(clt, 500, errstr);
return (-1);
}
diff --git a/httpd/server_file.c b/httpd/server_file.c
index e060124..48ecbb5 100644
--- a/httpd/server_file.c
+++ b/httpd/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.60 2015/08/03 11:45:17 florian Exp $ */
+/* $OpenBSD: server_file.c,v 1.62 2016/05/17 03:12:39 deraadt Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -287,6 +287,8 @@ server_file_request(struct httpd *env, struct client *clt, char *path,
bufferevent_free(clt->clt_bev);
clt->clt_bev = NULL;
abort:
+ if (fd != -1)
+ close(fd);
if (errstr == NULL)
errstr = strerror(errno);
server_abort_http(clt, code, errstr);
@@ -387,6 +389,9 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path,
media = &multipart_media;
}
+ close(fd);
+ fd = -1;
+
ret = server_response_http(clt, 206, media, content_length,
MINIMUM(time(NULL), st->st_mtim.tv_sec));
switch (ret) {
@@ -394,7 +399,6 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path,
goto fail;
case 0:
/* Connection is already finished */
- close(fd);
evbuffer_free(evb);
evb = NULL;
goto done;
@@ -423,6 +427,8 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path,
bufferevent_free(clt->clt_bev);
clt->clt_bev = NULL;
abort:
+ if (fd != -1)
+ close(fd);
if (errstr == NULL)
errstr = strerror(errno);
server_abort_http(clt, code, errstr);
@@ -484,6 +490,8 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; "
+ "charset=utf-8\"/>\n"
"<title>Index of %s</title>\n"
"<style type=\"text/css\"><!--\n%s\n--></style>\n"
"</head>\n"
diff --git a/httpd/server_http.c b/httpd/server_http.c
index 8ed98b5..b69805a 100644
--- a/httpd/server_http.c
+++ b/httpd/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.98 2015/08/21 07:30:50 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.109 2016/07/27 11:02:41 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -102,26 +102,18 @@ server_httpdesc_free(struct http_descriptor *desc)
{
if (desc == NULL)
return;
- if (desc->http_path != NULL) {
- free(desc->http_path);
- desc->http_path = NULL;
- }
- if (desc->http_path_alias != NULL) {
- free(desc->http_path_alias);
- desc->http_path_alias = NULL;
- }
- if (desc->http_query != NULL) {
- free(desc->http_query);
- desc->http_query = NULL;
- }
- if (desc->http_version != NULL) {
- free(desc->http_version);
- desc->http_version = NULL;
- }
- if (desc->http_host != NULL) {
- free(desc->http_host);
- desc->http_host = NULL;
- }
+
+ free(desc->http_path);
+ desc->http_path = NULL;
+ free(desc->http_path_alias);
+ desc->http_path_alias = NULL;
+ free(desc->http_query);
+ desc->http_query = NULL;
+ free(desc->http_version);
+ desc->http_version = NULL;
+ free(desc->http_host);
+ desc->http_host = NULL;
+
kv_purge(&desc->http_headers);
desc->http_lastheader = NULL;
desc->http_method = 0;
@@ -134,7 +126,7 @@ server_http_authenticate(struct server_config *srv_conf, struct client *clt)
char decoded[1024];
FILE *fp = NULL;
struct http_descriptor *desc = clt->clt_descreq;
- struct auth *auth = srv_conf->auth;
+ const struct auth *auth = srv_conf->auth;
struct kv *ba, key;
size_t linesize = 0;
ssize_t linelen;
@@ -195,6 +187,7 @@ server_http_authenticate(struct server_config *srv_conf, struct client *clt)
}
}
done:
+ free(line);
if (fp != NULL)
fclose(fp);
@@ -303,8 +296,10 @@ server_read_http(struct bufferevent *bev, void *arg)
goto fail;
desc->http_version = strchr(desc->http_path, ' ');
- if (desc->http_version == NULL)
- goto fail;
+ if (desc->http_version == NULL) {
+ server_abort_http(clt, 400, "malformed");
+ goto abort;
+ }
*desc->http_version++ = '\0';
desc->http_query = strchr(desc->http_path, '?');
@@ -385,12 +380,12 @@ server_read_http(struct bufferevent *bev, void *arg)
case HTTP_METHOD_DELETE:
case HTTP_METHOD_GET:
case HTTP_METHOD_HEAD:
- case HTTP_METHOD_OPTIONS:
/* WebDAV methods */
case HTTP_METHOD_COPY:
case HTTP_METHOD_MOVE:
clt->clt_toread = 0;
break;
+ case HTTP_METHOD_OPTIONS:
case HTTP_METHOD_POST:
case HTTP_METHOD_PUT:
case HTTP_METHOD_RESPONSE:
@@ -597,8 +592,7 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
case 0:
/* Chunk is terminated by an empty newline */
line = evbuffer_readln(src, NULL, EVBUFFER_EOL_CRLF_STRICT);
- if (line != NULL)
- free(line);
+ free(line);
if (server_bufferevent_print(clt, "\r\n") == -1)
goto fail;
clt->clt_toread = TOREAD_HTTP_CHUNK_LENGTH;
@@ -824,6 +818,8 @@ server_abort_http(struct client *clt, unsigned int code, const char *msg)
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; "
+ "charset=utf-8\"/>\n"
"<title>%03d %s</title>\n"
"<style type=\"text/css\"><!--\n%s\n--></style>\n"
"</head>\n"
@@ -832,8 +828,10 @@ server_abort_http(struct client *clt, unsigned int code, const char *msg)
"<hr>\n<address>%s</address>\n"
"</body>\n"
"</html>\n",
- code, httperr, style, code, httperr, HTTPD_SERVERNAME)) == -1)
+ code, httperr, style, code, httperr, HTTPD_SERVERNAME)) == -1) {
+ body = NULL;
goto done;
+ }
if (srv_conf->flags & SRVFLAG_SERVER_HSTS) {
if (asprintf(&hstsheader, "Strict-Transport-Security: "
@@ -841,8 +839,10 @@ server_abort_http(struct client *clt, unsigned int code, const char *msg)
srv_conf->hsts_flags & HSTSFLAG_SUBDOMAINS ?
"; includeSubDomains" : "",
srv_conf->hsts_flags & HSTSFLAG_PRELOAD ?
- "; preload" : "") == -1)
+ "; preload" : "") == -1) {
+ hstsheader = NULL;
goto done;
+ }
}
/* Add basic HTTP headers */
@@ -918,7 +918,7 @@ server_expand_http(struct client *clt, const char *val, char *buf,
/* Find previously matched substrings by index */
for (p = val; clt->clt_srv_match.sm_nmatch &&
(p = strstr(p, "%")) != NULL; p++) {
- if (!isdigit(*(p + 1)))
+ if (!isdigit((unsigned char)*(p + 1)))
continue;
/* Copy number, leading '%' char and add trailing \0 */