From c690aa7c2b56f7fb30f72222928b0f7563a1e7e1 Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Thu, 16 Jul 2015 21:06:14 +0200 Subject: sync with -current during c2k15 --- httpd/config.c | 150 +++++++++++++++++++++++++++++++++++++++++++--------- httpd/httpd.conf.5 | 8 ++- httpd/httpd.h | 19 ++++++- httpd/parse.y | 6 ++- httpd/patterns.7 | 13 +++-- httpd/patterns.c | 12 ++--- httpd/patterns.h | 8 +-- httpd/server.c | 55 ++++++++++++++----- httpd/server_file.c | 38 ++++++------- httpd/server_http.c | 101 +++++++++++++++++++++++++++-------- 10 files changed, 313 insertions(+), 97 deletions(-) diff --git a/httpd/config.c b/httpd/config.c index 7635c33..3c88990 100644 --- a/httpd/config.c +++ b/httpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.37 2015/04/11 14:52:49 jsing Exp $ */ +/* $OpenBSD: config.c,v 1.39 2015/07/15 16:00:39 jsing Exp $ */ /* * Copyright (c) 2011 - 2015 Reyk Floeter @@ -193,14 +193,6 @@ config_setserver(struct httpd *env, struct server *srv) iov[c].iov_base = srv->srv_conf.return_uri; iov[c++].iov_len = srv->srv_conf.return_uri_len; } - if (srv->srv_conf.tls_cert_len != 0) { - iov[c].iov_base = srv->srv_conf.tls_cert; - iov[c++].iov_len = srv->srv_conf.tls_cert_len; - } - if (srv->srv_conf.tls_key_len != 0) { - iov[c].iov_base = srv->srv_conf.tls_key; - iov[c++].iov_len = srv->srv_conf.tls_key_len; - } if (id == PROC_SERVER && (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) { @@ -220,6 +212,9 @@ config_setserver(struct httpd *env, struct server *srv) return (-1); } } + + /* Configure TLS if necessary. */ + config_settls(env, srv); } else { if (proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1, iov, c) != 0) { @@ -234,6 +229,72 @@ config_setserver(struct httpd *env, struct server *srv) return (0); } +int +config_settls(struct httpd *env, struct server *srv) +{ + struct privsep *ps = env->sc_ps; + struct tls_config tls; + struct iovec iov[2]; + size_t c; + + if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0) + return (0); + + log_debug("%s: configuring TLS for %s", __func__, srv->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); + + 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; + + 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; + + if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1, + iov, c) != 0) { + log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " + "`%s'", __func__, srv->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); + + 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; + + 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; + + if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1, + iov, c) != 0) { + log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " + "`%s'", __func__, srv->srv_conf.name); + return (-1); + } + } + + return (0); +} + int config_getserver_auth(struct httpd *env, struct server_config *srv_conf) { @@ -422,9 +483,7 @@ config_getserver(struct httpd *env, struct imsg *imsg) /* Reset these variables to avoid free'ing invalid pointers */ serverconfig_reset(&srv_conf); - if ((IMSG_DATA_SIZE(imsg) - s) < - (srv_conf.tls_cert_len + srv_conf.tls_key_len + - srv_conf.return_uri_len)) { + if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) { log_debug("%s: invalid message length", __func__); goto fail; } @@ -475,30 +534,69 @@ config_getserver(struct httpd *env, struct imsg *imsg) goto fail; s += srv->srv_conf.return_uri_len; } - if (srv->srv_conf.tls_cert_len != 0) { + + return (0); + + fail: + if (imsg->fd != -1) + close(imsg->fd); + if (srv != NULL) + serverconfig_free(&srv->srv_conf); + free(srv); + + return (-1); +} + +int +config_gettls(struct httpd *env, struct imsg *imsg) +{ +#ifdef DEBUG + struct privsep *ps = env->sc_ps; +#endif + struct server *srv = NULL; + struct tls_config tls_conf; + u_int8_t *p = imsg->data; + size_t s; + + IMSG_SIZE_CHECK(imsg, &tls_conf); + memcpy(&tls_conf, p, sizeof(tls_conf)); + s = sizeof(tls_conf); + + if ((IMSG_DATA_SIZE(imsg) - s) < + (tls_conf.tls_cert_len + tls_conf.tls_key_len)) { + log_debug("%s: invalid message length", __func__); + goto fail; + } + + /* Find server with matching listening socket. */ + if ((srv = server_byaddr((struct sockaddr *) + &tls_conf.ss, tls_conf.port)) == NULL) { + log_debug("%s: server not found", __func__); + goto fail; + } + + 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); + + 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->srv_conf.tls_cert_len)) == NULL) + tls_conf.tls_cert_len)) == NULL) goto fail; - s += srv->srv_conf.tls_cert_len; + s += tls_conf.tls_cert_len; } - if (srv->srv_conf.tls_key_len != 0) { + 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->srv_conf.tls_key_len)) == NULL) + tls_conf.tls_key_len)) == NULL) goto fail; - s += srv->srv_conf.tls_key_len; + s += tls_conf.tls_key_len; } return (0); fail: - if (imsg->fd != -1) - close(imsg->fd); - if (srv != NULL) { - free(srv->srv_conf.tls_cert); - free(srv->srv_conf.tls_key); - } - free(srv); - return (-1); } diff --git a/httpd/httpd.conf.5 b/httpd/httpd.conf.5 index db73b8f..b3eaad8 100644 --- a/httpd/httpd.conf.5 +++ b/httpd/httpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: httpd.conf.5,v 1.63 2015/06/23 17:29:19 jmc Exp $ +.\" $OpenBSD: httpd.conf.5,v 1.64 2015/07/15 17:10:47 jsing Exp $ .\" .\" Copyright (c) 2014, 2015 Reyk Floeter .\" @@ -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: June 23 2015 $ +.Dd $Mdocdate: July 15 2015 $ .Dt HTTPD.CONF 5 .Os .Sh NAME @@ -412,6 +412,8 @@ Specify the certificate to use for this server. The .Ar file should contain a PEM encoded certificate. +The default is +.Pa /etc/ssl/server.crt . .It Ic ciphers Ar string Specify the TLS cipher string. If not specified, the default value @@ -438,6 +440,8 @@ should contain a PEM encoded private key and reside outside of the .Xr chroot 2 root directory of .Nm httpd . +The default is +.Pa /etc/ssl/private/server.key . .It Ic protocols Ar string Specify the TLS protocols to enable for this server. If not specified, the value diff --git a/httpd/httpd.h b/httpd/httpd.h index 20d75a7..2cb7934 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.84 2015/06/23 15:23:14 reyk Exp $ */ +/* $OpenBSD: httpd.h,v 1.88 2015/07/16 16:29:25 florian Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter @@ -34,6 +34,7 @@ #include #include #include +#include #include "patterns.h" @@ -47,6 +48,7 @@ #define HTTPD_LOGROOT "/logs" #define HTTPD_ACCESS_LOG "access.log" #define HTTPD_ERROR_LOG "error.log" +#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" @@ -64,6 +66,8 @@ #define SERVER_MAXREQUESTBODY 1048576 /* 1M */ #define SERVER_BACKLOG 10 #define SERVER_OUTOF_FD_RETRIES 5 +#define SERVER_MAX_PREFETCH 256 +#define SERVER_MIN_PREFETCHED 32 #define MEDIATYPE_NAMEMAX 128 /* file name extension */ #define MEDIATYPE_TYPEMAX 64 /* length of type/subtype */ @@ -201,6 +205,7 @@ enum imsg_type { IMSG_CTL_START, IMSG_CTL_REOPEN, IMSG_CFG_SERVER, + IMSG_CFG_TLS, IMSG_CFG_MEDIA, IMSG_CFG_AUTH, IMSG_CFG_DONE, @@ -442,6 +447,16 @@ struct server_config { }; TAILQ_HEAD(serverhosts, server_config); +struct tls_config { + u_int32_t id; + + in_port_t port; + struct sockaddr_storage ss; + + size_t tls_cert_len; + size_t tls_key_len; +}; + struct server { TAILQ_ENTRY(server) srv_entry; struct server_config srv_conf; @@ -680,7 +695,9 @@ int config_setreset(struct httpd *, u_int); int config_getreset(struct httpd *, struct imsg *); int config_getcfg(struct httpd *, struct imsg *); int config_setserver(struct httpd *, struct server *); +int config_settls(struct httpd *, struct server *); int config_getserver(struct httpd *, struct imsg *); +int config_gettls(struct httpd *, struct imsg *); int config_setmedia(struct httpd *, struct media_type *); int config_getmedia(struct httpd *, struct imsg *); int config_setauth(struct httpd *, struct auth *); diff --git a/httpd/parse.y b/httpd/parse.y index 1ba5cf3..0870819 100644 --- a/httpd/parse.y +++ b/httpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.68 2015/06/23 15:23:14 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.70 2015/07/16 19:05:28 reyk Exp $ */ /* * Copyright (c) 2007 - 2015 Reyk Floeter @@ -408,7 +408,9 @@ serveroptsl : LISTEN ON STRING opttls port { if (alias != NULL) { /* IP-based; use name match flags from parent */ - alias->flags = srv->srv_conf.flags; + alias->flags &= ~SRVFLAG_SERVER_MATCH; + alias->flags |= srv->srv_conf.flags & + SRVFLAG_SERVER_MATCH; TAILQ_INSERT_TAIL(&srv->srv_hosts, alias, entry); } diff --git a/httpd/patterns.7 b/httpd/patterns.7 index 7c951db..a01ede5 100644 --- a/httpd/patterns.7 +++ b/httpd/patterns.7 @@ -1,4 +1,4 @@ -.\" $OpenBSD: patterns.7,v 1.2 2015/06/23 17:29:19 jmc Exp $ +.\" $OpenBSD: patterns.7,v 1.5 2015/06/30 19:01:05 jmc Exp $ .\" .\" Copyright (c) 2015 Reyk Floeter .\" Copyright (C) 1994-2015 Lua.org, PUC-Rio. @@ -23,9 +23,9 @@ .\" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .\" .\" Derived from section 6.4.1 in manual.html of Lua 5.3.1: -.\" $Id: patterns.7,v 1.2 2015/06/23 17:29:19 jmc Exp $ +.\" $Id: patterns.7,v 1.5 2015/06/30 19:01:05 jmc Exp $ .\" -.Dd $Mdocdate: June 23 2015 $ +.Dd $Mdocdate: June 30 2015 $ .Dt PATTERNS 7 .Os .Sh NAME @@ -268,7 +268,7 @@ For instance, if we apply the pattern .Qq ()aa() on the string .Qq flaaap , -there will be two captures: 3 and 5. +there will be two captures: 2 and 4. .Sh SEE ALSO .Xr fnmatch 3 , .Xr re_format 7 , @@ -302,3 +302,8 @@ It was turned into a native C API for .Xr httpd 8 by .An Reyk Floeter Aq Mt reyk@openbsd.org . +.Sh CAVEATS +A notable difference with the Lua implementation is the position in the string +returned by captures. +It follows the C-style indexing (position starting from 0) +instead of Lua-style indexing (position starting from 1). diff --git a/httpd/patterns.c b/httpd/patterns.c index 3b2cbcc..27a813f 100644 --- a/httpd/patterns.c +++ b/httpd/patterns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: patterns.c,v 1.2 2015/06/23 15:35:20 semarie Exp $ */ +/* $OpenBSD: patterns.c,v 1.3 2015/06/26 10:07:48 semarie Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -26,16 +26,16 @@ /* * Derived from Lua 5.3.1: - * $Id: patterns.c,v 1.2 2015/06/23 15:35:20 semarie Exp $ + * $Id: patterns.c,v 1.3 2015/06/26 10:07:48 semarie Exp $ * Standard library for string operations and pattern-matching */ +#include +#include +#include #include #include #include -#include -#include -#include #include "patterns.h" @@ -98,7 +98,7 @@ classend(struct match_state *ms, const char *p) case L_ESC: if (p == ms->p_end) match_error(ms, - "malformed pattern (ends with '%%')"); + "malformed pattern (ends with '%')"); return p + 1; case '[': if (*p == '^') diff --git a/httpd/patterns.h b/httpd/patterns.h index e753849..74790b5 100644 --- a/httpd/patterns.h +++ b/httpd/patterns.h @@ -1,4 +1,4 @@ -/* $OpenBSD: patterns.h,v 1.1 2015/06/23 15:23:14 reyk Exp $ */ +/* $OpenBSD: patterns.h,v 1.2 2015/06/26 17:26:29 semarie Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -16,12 +16,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include - #ifndef PATTERNS_H #define PATTERNS_H +#include +#include + #define MAXCAPTURES 32 /* Max no. of allowed captures in pattern */ #define MAXCCALLS 200 /* Max recusion depth in pattern matching */ #define MAXREPETITION 0xfffff /* Max for repetition items */ diff --git a/httpd/server.c b/httpd/server.c index ca67a47..86d0dca 100644 --- a/httpd/server.c +++ b/httpd/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.63 2015/04/23 16:59:28 florian Exp $ */ +/* $OpenBSD: server.c,v 1.70 2015/07/16 16:29:25 florian Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter @@ -41,6 +41,7 @@ #include #include #include +#include #include "httpd.h" @@ -312,20 +313,31 @@ 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_cert); free(srv_conf->tls_key_file); - free(srv_conf->tls_key); + + if (srv_conf->tls_cert != NULL) { + explicit_bzero(srv_conf->tls_cert, srv_conf->tls_cert_len); + free(srv_conf->tls_cert); + } + + if (srv_conf->tls_key != NULL) { + explicit_bzero(srv_conf->tls_key, srv_conf->tls_key_len); + free(srv_conf->tls_key); + } } void serverconfig_reset(struct server_config *srv_conf) { - srv_conf->tls_cert_file = srv_conf->tls_key_file = NULL; - srv_conf->tls_cert = srv_conf->tls_key = NULL; - srv_conf->return_uri = NULL; srv_conf->auth = NULL; + srv_conf->return_uri = NULL; + srv_conf->tls_cert = NULL; + srv_conf->tls_cert_file = NULL; + srv_conf->tls_key = NULL; + srv_conf->tls_key_file = NULL; } struct server * @@ -571,6 +583,11 @@ server_tls_readcb(int fd, short event, void *arg) goto err; } + if (len == 0) { + what |= EVBUFFER_EOF; + goto err; + } + if (evbuffer_add(bufev->input, rbuf, len) == -1) { what |= EVBUFFER_ERROR; goto err; @@ -704,7 +721,7 @@ server_input(struct client *clt) /* Adjust write watermark to the socket buffer output size */ bufferevent_setwatermark(clt->clt_bev, EV_WRITE, - clt->clt_sndbufsiz, 0); + SERVER_MIN_PREFETCHED * clt->clt_sndbufsiz, 0); /* Read at most amount of data that fits in one fcgi record. */ bufferevent_setwatermark(clt->clt_bev, EV_READ, 0, FCGI_CONTENT_SIZE); @@ -729,6 +746,10 @@ server_write(struct bufferevent *bev, void *arg) goto done; bufferevent_enable(bev, EV_READ); + + if (clt->clt_srvbev && !(clt->clt_srvbev->enabled & EV_READ)) + bufferevent_enable(clt->clt_srvbev, EV_READ); + return; done: (*bev->errorcb)(bev, EVBUFFER_WRITE|EVBUFFER_EOF, bev->cbarg); @@ -769,6 +790,11 @@ server_read(struct bufferevent *bev, void *arg) goto fail; if (clt->clt_done) goto done; + + if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev)) > (size_t) + SERVER_MAX_PREFETCH * clt->clt_sndbufsiz) + bufferevent_disable(bev, EV_READ); + return; done: (*bev->errorcb)(bev, EVBUFFER_READ|EVBUFFER_EOF, bev->cbarg); @@ -919,7 +945,7 @@ server_accept(int fd, short event, void *arg) close(s); free(clt); /* - * the client struct was not completly set up, but still + * the client struct was not completely set up, but still * counted as an inflight client. account for this. */ server_inflight_dec(NULL, __func__); @@ -954,6 +980,7 @@ server_accept_tls(int fd, short event, void *arg) } 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; } @@ -1020,7 +1047,7 @@ server_log(struct client *clt, const char *msg) { char ibuf[HOST_NAME_MAX+1], obuf[HOST_NAME_MAX+1]; struct server_config *srv_conf = clt->clt_srv_conf; - char *ptr = NULL; + char *ptr = NULL, *vmsg = NULL; int debug_cmd = -1; extern int verbose; @@ -1050,13 +1077,14 @@ server_log(struct client *clt, const char *msg) if (EVBUFFER_LENGTH(clt->clt_log) && evbuffer_add_printf(clt->clt_log, "\n") != -1) ptr = evbuffer_readline(clt->clt_log); + (void)stravis(&vmsg, msg, HTTPD_LOGVIS); server_sendlog(srv_conf, debug_cmd, "server %s, " "client %d (%d active), %s:%u -> %s, " "%s%s%s", srv_conf->name, clt->clt_id, server_clients, - ibuf, ntohs(clt->clt_port), obuf, msg, + ibuf, ntohs(clt->clt_port), obuf, vmsg == NULL ? "" : vmsg, ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr); - if (ptr != NULL) - free(ptr); + free(vmsg); + free(ptr); } } @@ -1118,6 +1146,9 @@ server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) case IMSG_CFG_SERVER: config_getserver(env, imsg); break; + case IMSG_CFG_TLS: + config_gettls(env, imsg); + break; case IMSG_CFG_DONE: config_getcfg(env, imsg); break; diff --git a/httpd/server_file.c b/httpd/server_file.c index 52e50ff..16b47d0 100644 --- a/httpd/server_file.c +++ b/httpd/server_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_file.c,v 1.54 2015/05/05 11:10:13 florian Exp $ */ +/* $OpenBSD: server_file.c,v 1.55 2015/07/16 19:05:28 reyk Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter @@ -43,20 +43,20 @@ struct range { off_t end; }; -int server_file_access(struct httpd *, struct client *, +int server_file_access(struct httpd *, struct client *, char *, size_t); -int server_file_request(struct httpd *, struct client *, +int server_file_request(struct httpd *, struct client *, char *, struct stat *); -int server_partial_file_request(struct httpd *, struct client *, +int server_partial_file_request(struct httpd *, struct client *, char *, struct stat *, char *); -int server_file_index(struct httpd *, struct client *, +int server_file_index(struct httpd *, struct client *, struct stat *); int server_file_modified_since(struct http_descriptor *, struct stat *); -int server_file_method(struct client *); -int parse_range_spec(char *, size_t, struct range *); -struct range *parse_range(char *, size_t, int *); -int buffer_add_range(int, struct evbuffer *, struct range *); +int server_file_method(struct client *); +int parse_range_spec(char *, size_t, struct range *); +struct range *parse_range(char *, size_t, int *); +int buffer_add_range(int, struct evbuffer *, struct range *); int server_file_access(struct httpd *env, struct client *clt, @@ -296,9 +296,9 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path, struct range *range; struct evbuffer *evb = NULL; size_t content_length; - int code = 500, fd = -1, i, nranges, ret; + int code = 500, fd = -1, i, nranges, ret; uint32_t boundary; - char content_range[64]; + char content_range[64]; const char *errstr = NULL; /* Ignore range request for methods other than GET */ @@ -325,7 +325,7 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path, if (nranges == 1) { (void)snprintf(content_range, sizeof(content_range), - "bytes %lld-%lld/%lld", range->start, range->end, + "bytes %lld-%lld/%lld", range->start, range->end, st->st_size); if (kv_add(&resp->http_headers, "Content-Range", content_range) == NULL) @@ -347,8 +347,8 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path, content_length += i; if ((i = evbuffer_add_printf(evb, "Content-Type: %s/%s\r\n", - media == NULL ? "application" : media->media_type, - media == NULL ? + media == NULL ? "application" : media->media_type, + media == NULL ? "octet-stream" : media->media_subtype)) == -1) goto abort; @@ -374,10 +374,10 @@ server_partial_file_request(struct httpd *env, struct client *clt, char *path, /* prepare multipart/byteranges media type */ (void)strlcpy(multipart_media.media_type, "multipart", - sizeof(multipart_media.media_type)); + sizeof(multipart_media.media_type)); (void)snprintf(multipart_media.media_subtype, - sizeof(multipart_media.media_subtype), - "byteranges; boundary=%ud", boundary); + sizeof(multipart_media.media_subtype), + "byteranges; boundary=%ud", boundary); media = &multipart_media; } @@ -656,7 +656,7 @@ struct range * parse_range(char *str, size_t file_sz, int *nranges) { static struct range ranges[MAX_RANGES]; - int i = 0; + int i = 0; char *p, *q; /* Extract range unit */ @@ -692,7 +692,7 @@ parse_range(char *str, size_t file_sz, int *nranges) int parse_range_spec(char *str, size_t size, struct range *r) { - size_t start_str_len, end_str_len; + size_t start_str_len, end_str_len; char *p, *start_str, *end_str; const char *errstr; diff --git a/httpd/server_http.c b/httpd/server_http.c index 112bb00..9a6609e 100644 --- a/httpd/server_http.c +++ b/httpd/server_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_http.c,v 1.84 2015/06/23 17:25:01 semarie Exp $ */ +/* $OpenBSD: server_http.c,v 1.89 2015/07/16 19:05:28 reyk Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter @@ -35,6 +35,7 @@ #include #include #include +#include #include "httpd.h" #include "http.h" @@ -1007,7 +1008,7 @@ server_expand_http(struct client *clt, const char *val, char *buf, return (NULL); } if (strstr(val, "$SERVER_NAME") != NULL) { - if ((str = url_encode(srv_conf->name)) + if ((str = url_encode(srv_conf->name)) == NULL) return (NULL); ret = expand_string(buf, len, "$SERVER_NAME", str); @@ -1426,6 +1427,13 @@ server_log_http(struct client *clt, u_int code, size_t len) struct tm *tm; struct server_config *srv_conf; struct http_descriptor *desc; + int ret = -1; + char *user = NULL; + char *path = NULL; + char *query = NULL; + char *version = NULL; + char *referrer_v = NULL; + char *agent_v = NULL; if ((srv_conf = clt->clt_srv_conf) == NULL) return (-1); @@ -1454,18 +1462,34 @@ server_log_http(struct client *clt, u_int code, size_t len) */ switch (srv_conf->logformat) { case LOG_FORMAT_COMMON: - if (evbuffer_add_printf(clt->clt_log, + /* Use vis to encode input values from the header */ + if (clt->clt_remote_user && + stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1) + goto done; + if (desc->http_version && + stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1) + goto done; + + /* The following should be URL-encoded */ + if (desc->http_path && + (path = url_encode(desc->http_path)) == NULL) + goto done; + if (desc->http_query && + (query = url_encode(desc->http_query)) == NULL) + goto done; + + ret = evbuffer_add_printf(clt->clt_log, "%s %s - %s [%s] \"%s %s%s%s%s%s\" %03d %zu\n", srv_conf->name, ip, clt->clt_remote_user == NULL ? "-" : - clt->clt_remote_user, tstamp, + user, tstamp, server_httpmethod_byid(desc->http_method), - desc->http_path == NULL ? "" : desc->http_path, + desc->http_path == NULL ? "" : path, desc->http_query == NULL ? "" : "?", - desc->http_query == NULL ? "" : desc->http_query, + desc->http_query == NULL ? "" : query, desc->http_version == NULL ? "" : " ", - desc->http_version == NULL ? "" : desc->http_version, - code, len) == -1) - return (-1); + desc->http_version == NULL ? "" : version, + code, len); + break; case LOG_FORMAT_COMBINED: @@ -1479,29 +1503,64 @@ server_log_http(struct client *clt, u_int code, size_t len) agent->kv_value == NULL) agent = NULL; - if (evbuffer_add_printf(clt->clt_log, + /* Use vis to encode input values from the header */ + if (clt->clt_remote_user && + stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1) + goto done; + if (desc->http_version && + stravis(&version, desc->http_version, HTTPD_LOGVIS) == -1) + goto done; + if (agent && + stravis(&agent_v, agent->kv_value, HTTPD_LOGVIS) == -1) + goto done; + + /* The following should be URL-encoded */ + if (desc->http_path && + (path = url_encode(desc->http_path)) == NULL) + goto done; + if (desc->http_query && + (query = url_encode(desc->http_query)) == NULL) + goto done; + if (referrer && + (referrer_v = url_encode(referrer->kv_value)) == NULL) + goto done; + + ret = evbuffer_add_printf(clt->clt_log, "%s %s - %s [%s] \"%s %s%s%s%s%s\"" " %03d %zu \"%s\" \"%s\"\n", srv_conf->name, ip, clt->clt_remote_user == NULL ? "-" : - clt->clt_remote_user, tstamp, + user, tstamp, server_httpmethod_byid(desc->http_method), - desc->http_path == NULL ? "" : desc->http_path, + desc->http_path == NULL ? "" : path, desc->http_query == NULL ? "" : "?", - desc->http_query == NULL ? "" : desc->http_query, + desc->http_query == NULL ? "" : query, desc->http_version == NULL ? "" : " ", - desc->http_version == NULL ? "" : desc->http_version, + desc->http_version == NULL ? "" : version, code, len, - referrer == NULL ? "" : referrer->kv_value, - agent == NULL ? "" : agent->kv_value) == -1) - return (-1); + referrer == NULL ? "" : referrer_v, + agent == NULL ? "" : agent_v); + break; case LOG_FORMAT_CONNECTION: - if (evbuffer_add_printf(clt->clt_log, " [%s]", - desc->http_path == NULL ? "" : desc->http_path) == -1) - return (-1); + /* URL-encode the path */ + if (desc->http_path && + (path = url_encode(desc->http_path)) == NULL) + goto done; + + ret = evbuffer_add_printf(clt->clt_log, " [%s]", + desc->http_path == NULL ? "" : path); + break; } - return (0); +done: + free(user); + free(path); + free(query); + free(version); + free(referrer_v); + free(agent_v); + + return (ret); } -- cgit v1.2.3-54-g00ecf