summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2015-02-24 08:57:19 +0100
committerReyk Floeter <reyk@esdenera.com>2015-02-24 08:57:19 +0100
commitbe1b7213b8e8d0de98b5a6445504a583e8c9a064 (patch)
treeb7360e53b785340929ce2e4722703fd97c121f26
parent8a2934048ba934e50ecc1736d554036fc39f6752 (diff)
downloadhttpd-OPENBSD_5_7_BASE.tar.gz
httpd-OPENBSD_5_7_BASE.zip
Allow to specify CGI variables as macros in redirection strings, eg.OPENBSD_5_7_BASE
block return 301 "http://www.example.com/$REQUEST_URI" OK tedu@ florian@ Add return_uri to serverconfig_reset() to avoid using garbage from the imsg buffer. Debugging & OK halex@ Change TLS_PROTOCOLS_DEFAULT to be TLSv1.2 only. Add a TLS_PROTOCOLS_ALL that includes all currently supported protocols (TLSv1.0, TLSv1.1 and TLSv1.2). Change all users of libtls to use TLS_PROTOCOLS_ALL so that they maintain existing behaviour. Discussed with tedu@ and reyk@.
-rw-r--r--Makefile4
-rw-r--r--config.c27
-rw-r--r--http.h9
-rw-r--r--httpd.c91
-rw-r--r--httpd.conf.539
-rw-r--r--httpd.h6
-rw-r--r--parse.y25
-rw-r--r--server.c6
-rw-r--r--server_fcgi.c4
-rw-r--r--server_file.c21
-rw-r--r--server_http.c110
11 files changed, 310 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index 441e02c..885ad42 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.26 2014/10/31 13:49:52 jsing Exp $
+# $OpenBSD: Makefile,v 1.27 2015/02/23 10:39:10 reyk Exp $
PROG= httpd
SRCS= parse.y
@@ -8,7 +8,7 @@ MAN= httpd.8 httpd.conf.5
LDADD= -levent -ltls -lssl -lcrypto -lutil
DPADD= ${LIBEVENT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL}
-#DEBUG= -g -DDEBUG=3
+#DEBUG= -g -DDEBUG=3 -O0
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
diff --git a/config.c b/config.c
index f631214..2dc9159 100644
--- a/config.c
+++ b/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.35 2015/02/07 23:56:02 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.36 2015/02/23 11:48:41 reyk Exp $ */
/*
* Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -272,6 +272,17 @@ config_getserver_config(struct httpd *env, struct server *srv,
if (config_getserver_auth(env, srv_conf) != 0)
goto fail;
+ /*
+ * Get variable-length values for the virtual host. The tls_* ones
+ * aren't needed in the virtual hosts unless we implement SNI.
+ */
+ if (srv_conf->return_uri_len != 0) {
+ if ((srv_conf->return_uri = get_data(p + s,
+ srv_conf->return_uri_len)) == NULL)
+ goto fail;
+ s += srv_conf->return_uri_len;
+ }
+
if (srv_conf->flags & SRVFLAG_LOCATION) {
/* Inherit configuration from the parent */
f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
@@ -344,6 +355,7 @@ config_getserver_config(struct httpd *env, struct server *srv,
f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK;
if ((srv_conf->flags & f) == 0) {
+ free(srv_conf->return_uri);
srv_conf->flags |= parent->flags & f;
srv_conf->return_code = parent->return_code;
srv_conf->return_uri_len = parent->return_uri_len;
@@ -351,13 +363,6 @@ config_getserver_config(struct httpd *env, struct server *srv,
(srv_conf->return_uri =
strdup(parent->return_uri)) == NULL)
goto fail;
- } else {
- if (srv_conf->return_uri_len != 0) {
- if ((srv_conf->return_uri = get_data(p + s,
- srv_conf->return_uri_len)) == NULL)
- goto fail;
- s += srv_conf->return_uri_len;
- }
}
memcpy(&srv_conf->timeout, &parent->timeout,
@@ -408,7 +413,8 @@ config_getserver(struct httpd *env, struct imsg *imsg)
serverconfig_reset(&srv_conf);
if ((IMSG_DATA_SIZE(imsg) - s) <
- (srv_conf.tls_cert_len + srv_conf.tls_key_len)) {
+ (srv_conf.tls_cert_len + srv_conf.tls_key_len +
+ srv_conf.return_uri_len)) {
log_debug("%s: invalid message length", __func__);
goto fail;
}
@@ -450,6 +456,9 @@ config_getserver(struct httpd *env, struct imsg *imsg)
srv->srv_conf.name, srv->srv_conf.id,
printb_flags(srv->srv_conf.flags, SRVFLAG_BITS));
+ /*
+ * Get all variable-length values for the parent server.
+ */
if (srv->srv_conf.return_uri_len != 0) {
if ((srv->srv_conf.return_uri = get_data(p + s,
srv->srv_conf.return_uri_len)) == NULL)
diff --git a/http.h b/http.h
index 59d1c10..00cf235 100644
--- a/http.h
+++ b/http.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http.h,v 1.11 2015/01/13 09:21:15 reyk Exp $ */
+/* $OpenBSD: http.h,v 1.12 2015/02/11 12:52:01 florian Exp $ */
/*
* Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -172,7 +172,8 @@ struct http_error {
{ 415, "Unsupported Media Type" }, \
{ 416, "Range Not Satisfiable" }, \
{ 417, "Expectation Failed" }, \
- /* 418-421 unassigned */ \
+ { 418, "I'm a teapot" }, \
+ /* 419-421 unassigned */ \
{ 420, "Enhance Your Calm" }, \
{ 422, "Unprocessable Entity" }, \
{ 423, "Locked" }, \
@@ -184,7 +185,9 @@ struct http_error {
{ 429, "Too Many Requests" }, \
/* 430 unassigned */ \
{ 431, "Request Header Fields Too Large" }, \
- /* 432-499 unassigned */ \
+ /* 432-450 unassigned */ \
+ { 451, "Unavailable For Legal Reasons" }, \
+ /* 452-499 unassigned */ \
{ 500, "Internal Server Error" }, \
{ 501, "Not Implemented" }, \
{ 502, "Bad Gateway" }, \
diff --git a/httpd.c b/httpd.c
index f640dc2..c6f183f 100644
--- a/httpd.c
+++ b/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.32 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.35 2015/02/23 18:43:18 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -494,6 +494,39 @@ event_again(struct event *ev, int fd, short event,
event_add(ev, &tv);
}
+int
+expand_string(char *label, size_t len, const char *srch, const char *repl)
+{
+ char *tmp;
+ char *p, *q;
+
+ if ((tmp = calloc(1, len)) == NULL) {
+ log_debug("%s: calloc", __func__);
+ return (-1);
+ }
+ p = q = label;
+ while ((q = strstr(p, srch)) != NULL) {
+ *q = '\0';
+ if ((strlcat(tmp, p, len) >= len) ||
+ (strlcat(tmp, repl, len) >= len)) {
+ log_debug("%s: string too long", __func__);
+ free(tmp);
+ return (-1);
+ }
+ q += strlen(srch);
+ p = q;
+ }
+ if (strlcat(tmp, p, len) >= len) {
+ log_debug("%s: string too long", __func__);
+ free(tmp);
+ return (-1);
+ }
+ (void)strlcpy(label, tmp, len); /* always fits */
+ free(tmp);
+
+ return (0);
+}
+
const char *
canonicalize_host(const char *host, char *name, size_t len)
{
@@ -671,6 +704,62 @@ path_info(char *path)
return (p - start);
}
+char *
+url_encode(const char *src)
+{
+ static char hex[] = "0123456789ABCDEF";
+ char *dp, *dst;
+ unsigned char c;
+
+ /* We need 3 times the memory if every letter is encoded. */
+ if ((dst = calloc(3, strlen(src) + 1)) == NULL)
+ return (NULL);
+
+ for (dp = dst; *src != 0; src++) {
+ c = (unsigned char) *src;
+ if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' ||
+ c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) {
+ *dp++ = '%';
+ *dp++ = hex[c >> 4];
+ *dp++ = hex[c & 0x0f];
+ } else
+ *dp++ = *src;
+ }
+ return (dst);
+}
+
+char*
+escape_html(const char* src)
+{
+ char *dp, *dst;
+
+ /* We need 5 times the memory if every letter is "<" or ">". */
+ if ((dst = calloc(5, strlen(src) + 1)) == NULL)
+ return NULL;
+
+ for (dp = dst; *src != 0; src++) {
+ if (*src == '<') {
+ *dp++ = '&';
+ *dp++ = 'l';
+ *dp++ = 't';
+ *dp++ = ';';
+ } else if (*src == '>') {
+ *dp++ = '&';
+ *dp++ = 'g';
+ *dp++ = 't';
+ *dp++ = ';';
+ } else if (*src == '&') {
+ *dp++ = '&';
+ *dp++ = 'a';
+ *dp++ = 'm';
+ *dp++ = 'p';
+ *dp++ = ';';
+ } else
+ *dp++ = *src;
+ }
+ return (dst);
+}
+
void
socket_rlimit(int maxfd)
{
diff --git a/httpd.conf.5 b/httpd.conf.5
index f93b57e..da51ad3 100644
--- a/httpd.conf.5
+++ b/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.50 2015/02/07 08:12:30 jmc Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.53 2015/02/23 18:43:18 reyk 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: February 7 2015 $
+.Dd $Mdocdate: February 23 2015 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -157,13 +157,38 @@ Close the connection and send an error page.
If the optional return code is not specified,
.Xr httpd 8
denies access with a
-.Sq 404 Forbidden
+.Sq 403 Forbidden
response.
The optional
.Ar uri
argument can be used with return codes in the 3xx range to send a
.Sq Location:
header for redirection to a specified URI.
+.Pp
+The
+.Ar url
+may contain predefined macros that will be expanded at runtime:
+.Pp
+.Bl -tag -width $DOCUMENT_URI -offset indent -compact
+.It Ic $DOCUMENT_URI
+The request path.
+.It Ic $QUERY_STRING
+The optional query string of 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 for HTTP authentication.
+.It Ic $REQUEST_URI
+The request path and optional query string.
+.It Ic $SERVER_ADDR
+The configured IP address of the relay.
+.It Ic $SERVER_PORT
+The configured TCP server port of the relay.
+.It Ic $SERVER_NAME
+The name of the server.
+.El
.It Ic connection Ar option
Set the specified options and limits for HTTP connections.
Valid options are:
@@ -367,6 +392,14 @@ should contain a PEM encoded private key and reside outside of the
.Xr chroot 2
root directory of
.Nm httpd .
+.It Ic protocols Ar string
+Specify the TLS protocols to enable for this server.
+If not specified, the default value
+.Qq all
+will be used (all available protocols).
+Refer to the
+.Xr tls_config_parse_protocols 3
+function for other valid protocol string values.
.El
.El
.Sh TYPES
diff --git a/httpd.h b/httpd.h
index 98096c9..28e02a5 100644
--- a/httpd.h
+++ b/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.77 2015/02/07 23:56:02 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.81 2015/02/23 18:43:18 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -410,6 +410,7 @@ struct server_config {
u_int8_t *tls_key;
size_t tls_key_len;
char *tls_key_file;
+ u_int32_t tls_protocols;
u_int32_t flags;
int strip;
@@ -583,10 +584,13 @@ int fcgi_add_stdin(struct client *, struct evbuffer *);
void event_again(struct event *, int, short,
void (*)(int, short, void *),
struct timeval *, struct timeval *, void *);
+int expand_string(char *, size_t, const char *, const char *);
const char *url_decode(char *);
+char *url_encode(const char *);
const char *canonicalize_host(const char *, char *, size_t);
const char *canonicalize_path(const char *, char *, size_t);
size_t path_info(char *);
+char *escape_html(const char *);
void imsg_event_add(struct imsgev *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
pid_t, int, void *, u_int16_t);
diff --git a/parse.y b/parse.y
index 51f7d98..7e48aba 100644
--- a/parse.y
+++ b/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.64 2015/02/08 04:50:32 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.65 2015/02/12 04:40:23 jsing Exp $ */
/*
* Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -131,8 +131,9 @@ typedef struct {
%token ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON
%token COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY LISTEN
-%token LOCATION LOG LOGDIR MAXIMUM NO NODELAY ON PORT PREFORK REQUEST REQUESTS
-%token ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT TLS TYPES
+%token LOCATION LOG LOGDIR MAXIMUM NO NODELAY ON PORT PREFORK PROTOCOLS
+%token REQUEST REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT
+%token TLS TYPES
%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
%token <v.string> STRING
%token <v.number> NUMBER
@@ -236,6 +237,7 @@ server : SERVER STRING {
s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY;
s->srv_conf.flags |= SRVFLAG_LOG;
s->srv_conf.logformat = LOG_FORMAT_COMMON;
+ s->srv_conf.tls_protocols = TLS_PROTOCOLS_ALL;
if ((s->srv_conf.tls_cert_file =
strdup(HTTPD_TLS_CERT)) == NULL)
fatal("out of memory");
@@ -297,6 +299,13 @@ server : SERVER STRING {
YYERROR;
}
+ if ((srv->srv_conf.flags & SRVFLAG_TLS) &&
+ srv->srv_conf.tls_protocols == 0) {
+ yyerror("no TLS protocols");
+ free(srv);
+ YYERROR;
+ }
+
if (server_tls_load_keypair(srv) == -1) {
yyerror("failed to load public/private keys "
"for server %s", srv->srv_conf.name);
@@ -643,6 +652,15 @@ tlsopts : CERTIFICATE STRING {
}
free($2);
}
+ | PROTOCOLS STRING {
+ if (tls_config_parse_protocols(
+ &srv_conf->tls_protocols, $2) != 0) {
+ yyerror("invalid TLS protocols");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
;
root : ROOT rootflags
@@ -1097,6 +1115,7 @@ lookup(char *s)
{ "pass", PASS },
{ "port", PORT },
{ "prefork", PREFORK },
+ { "protocols", PROTOCOLS },
{ "request", REQUEST },
{ "requests", REQUESTS },
{ "return", RETURN },
diff --git a/server.c b/server.c
index 6e63120..813f945 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.57 2015/02/07 23:56:02 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.60 2015/02/23 09:52:28 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -175,6 +175,9 @@ server_tls_init(struct server *srv)
return (-1);
}
+ tls_config_set_protocols(srv->srv_tls_config,
+ srv->srv_conf.tls_protocols);
+
if (tls_config_set_ciphers(srv->srv_tls_config,
srv->srv_conf.tls_ciphers) != 0) {
log_warn("%s: failed to set tls ciphers", __func__);
@@ -320,6 +323,7 @@ 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;
}
diff --git a/server_fcgi.c b/server_fcgi.c
index 563ffe5..33603a0 100644
--- a/server_fcgi.c
+++ b/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.51 2015/01/21 22:23:24 reyk Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.52 2015/02/23 19:22:43 chrisz Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -242,7 +242,7 @@ server_fcgi(struct httpd *env, struct client *clt)
errstr = "failed to encode param";
goto fail;
}
- if (fcgi_add_param(&param, "DOCUMENT_URI", desc->http_path,
+ if (fcgi_add_param(&param, "DOCUMENT_URI", alias,
clt) == -1) {
errstr = "failed to encode param";
goto fail;
diff --git a/server_file.c b/server_file.c
index b24f0c0..f697504 100644
--- a/server_file.c
+++ b/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.49 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.51 2015/02/12 10:05:29 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -274,6 +274,7 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
struct evbuffer *evb = NULL;
struct media_type *media;
const char *stripped, *style;
+ char *escapeduri, *escapedhtml, *escapedpath;
struct tm tm;
time_t t, dir_mtime;
@@ -304,6 +305,9 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
/* Indicate failure but continue going through the list */
skip = 0;
+ if ((escapedpath = escape_html(desc->http_path)) == NULL)
+ goto fail;
+
/* A CSS stylesheet allows minimal customization by the user */
style = "body { background-color: white; color: black; font-family: "
"sans-serif; }\nhr { border: 0; border-bottom: 1px dashed; }\n";
@@ -318,9 +322,11 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
"<body>\n"
"<h1>Index of %s</h1>\n"
"<hr>\n<pre>\n",
- desc->http_path, style, desc->http_path) == -1)
+ escapedpath, style, escapedpath) == -1)
skip = 1;
+ free(escapedpath);
+
for (i = 0; i < namesize; i++) {
dp = namelist[i];
@@ -335,6 +341,11 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
strftime(tmstr, sizeof(tmstr), "%d-%h-%Y %R", &tm);
namewidth = 51 - strlen(dp->d_name);
+ if ((escapeduri = url_encode(dp->d_name)) == NULL)
+ goto fail;
+ if ((escapedhtml = escape_html(dp->d_name)) == NULL)
+ goto fail;
+
if (dp->d_name[0] == '.' &&
!(dp->d_name[1] == '.' && dp->d_name[2] == '\0')) {
/* ignore hidden files starting with a dot */
@@ -342,17 +353,19 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
namewidth -= 1; /* trailing slash */
if (evbuffer_add_printf(evb,
"<a href=\"%s\">%s/</a>%*s%s%20s\n",
- dp->d_name, dp->d_name,
+ escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ", tmstr, "-") == -1)
skip = 1;
} else if (S_ISREG(st->st_mode)) {
if (evbuffer_add_printf(evb,
"<a href=\"%s\">%s</a>%*s%s%20llu\n",
- dp->d_name, dp->d_name,
+ escapeduri, escapedhtml,
MAXIMUM(namewidth, 0), " ",
tmstr, st->st_size) == -1)
skip = 1;
}
+ free(escapeduri);
+ free(escapedhtml);
free(dp);
}
free(namelist);
diff --git a/server_http.c b/server_http.c
index d4d3c97..b63fc22 100644
--- a/server_http.c
+++ b/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.74 2015/02/08 00:00:59 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.75 2015/02/23 18:43:18 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -42,7 +42,9 @@ static int server_httpmethod_cmp(const void *, const void *);
static int server_httperror_cmp(const void *, const void *);
void server_httpdesc_free(struct http_descriptor *);
int server_http_authenticate(struct server_config *,
- struct client *);
+ struct client *);
+char *server_expand_http(struct client *, const char *,
+ char *, size_t);
static struct httpd *env = NULL;
@@ -735,6 +737,7 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
const char *httperr = NULL, *style;
char *httpmsg, *body = NULL, *extraheader = NULL;
char tmbuf[32], hbuf[128];
+ char buf[IBUF_READ_SIZE], *ptr = NULL;
int bodylen;
if (code == 0) {
@@ -762,10 +765,20 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
switch (code) {
case 301:
case 302:
- if (asprintf(&extraheader, "Location: %s\r\n", msg) == -1) {
+ case 303:
+ if (msg == NULL)
+ break;
+ memset(buf, 0, sizeof(buf));
+ if ((ptr = server_expand_http(clt, msg,
+ buf, sizeof(buf))) == NULL)
+ goto done;
+ if ((ptr = url_encode(ptr)) == NULL)
+ goto done;
+ if (asprintf(&extraheader, "Location: %s\r\n", ptr) == -1) {
code = 500;
extraheader = NULL;
}
+ msg = ptr;
break;
case 401:
if (asprintf(&extraheader,
@@ -829,12 +842,15 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
done:
free(body);
free(extraheader);
+ if (msg == NULL)
+ msg = "\"\"";
if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1) {
server_close(clt, msg);
} else {
server_close(clt, httpmsg);
free(httpmsg);
}
+ free(ptr);
}
void
@@ -855,6 +871,94 @@ server_close_http(struct client *clt)
clt->clt_remote_user = NULL;
}
+char *
+server_expand_http(struct client *clt, const char *val, char *buf,
+ size_t len)
+{
+ struct http_descriptor *desc = clt->clt_descreq;
+ struct server_config *srv_conf = clt->clt_srv_conf;
+ char ibuf[128], *str;
+
+ if (strlcpy(buf, val, len) >= len)
+ return (NULL);
+
+ if (strstr(val, "$DOCUMENT_URI") != NULL) {
+ if (expand_string(buf, len, "$DOCUMENT_URI",
+ desc->http_path) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$QUERY_STRING") != NULL) {
+ if (expand_string(buf, len, "$QUERY_STRING",
+ desc->http_query == NULL ? "" :
+ desc->http_query) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$REMOTE_") != NULL) {
+ if (strstr(val, "$REMOTE_ADDR") != NULL) {
+ if (print_host(&clt->clt_ss,
+ ibuf, sizeof(ibuf)) == NULL)
+ return (NULL);
+ if (expand_string(buf, len,
+ "$REMOTE_ADDR", ibuf) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$REMOTE_PORT") != NULL) {
+ snprintf(ibuf, sizeof(ibuf),
+ "%u", ntohs(clt->clt_port));
+ if (expand_string(buf, len,
+ "$REMOTE_PORT", ibuf) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$REMOTE_USER") != NULL) {
+ if ((srv_conf->flags & SRVFLAG_AUTH) &&
+ clt->clt_remote_user != NULL)
+ str = clt->clt_remote_user;
+ else
+ str = "";
+ if (expand_string(buf, len,
+ "$REMOTE_USER", str) != 0)
+ return (NULL);
+ }
+ }
+ if (strstr(val, "$REQUEST_URI") != NULL) {
+ if (desc->http_query == NULL) {
+ if ((str = strdup(desc->http_path)) == NULL)
+ return (NULL);
+ } else if (asprintf(&str, "%s?%s",
+ desc->http_path, desc->http_query) == -1)
+ return (NULL);
+ if (expand_string(buf, len, "$REQUEST_URI", str) != 0) {
+ free(str);
+ return (NULL);
+ }
+ free(str);
+ }
+ if (strstr(val, "$SERVER_") != NULL) {
+ if (strstr(val, "$SERVER_ADDR") != NULL) {
+ if (print_host(&srv_conf->ss,
+ ibuf, sizeof(ibuf)) == NULL)
+ return (NULL);
+ if (expand_string(buf, len,
+ "$SERVER_ADDR", ibuf) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$SERVER_PORT") != NULL) {
+ snprintf(ibuf, sizeof(ibuf), "%u",
+ ntohs(srv_conf->port));
+ if (expand_string(buf, len,
+ "$SERVER_PORT", ibuf) != 0)
+ return (NULL);
+ }
+ if (strstr(val, "$SERVER_NAME") != NULL) {
+ if (expand_string(buf, len,
+ "$SERVER_NAME", srv_conf->name) != 0)
+ return (NULL);
+ }
+ }
+
+ return (buf);
+}
+
int
server_response(struct httpd *httpd, struct client *clt)
{