aboutsummaryrefslogtreecommitdiff
path: root/httpd/server_fcgi.c
diff options
context:
space:
mode:
Diffstat (limited to 'httpd/server_fcgi.c')
-rw-r--r--httpd/server_fcgi.c117
1 files changed, 63 insertions, 54 deletions
diff --git a/httpd/server_fcgi.c b/httpd/server_fcgi.c
index 21ebeed..920b2cf 100644
--- a/httpd/server_fcgi.c
+++ b/httpd/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.68 2016/04/24 20:09:45 chrisz Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.75 2017/07/31 08:02:49 ians Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -120,7 +120,6 @@ server_fcgi(struct httpd *env, struct client *clt)
goto fail;
} else {
struct sockaddr_un sun;
- size_t len;
if ((fd = socket(AF_UNIX,
SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
@@ -128,21 +127,21 @@ server_fcgi(struct httpd *env, struct client *clt)
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
- len = strlcpy(sun.sun_path,
- srv_conf->socket, sizeof(sun.sun_path));
- if (len >= sizeof(sun.sun_path)) {
- errstr = "socket path too long";
+ if (strlcpy(sun.sun_path, srv_conf->socket,
+ sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
+ errstr = "socket path to long";
goto fail;
}
- sun.sun_len = len;
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
goto fail;
}
memset(hbuf, 0, sizeof(hbuf));
- clt->clt_fcgi_state = FCGI_READ_HEADER;
- clt->clt_fcgi_toread = sizeof(struct fcgi_record_header);
+ clt->clt_fcgi.state = FCGI_READ_HEADER;
+ clt->clt_fcgi.toread = sizeof(struct fcgi_record_header);
+ clt->clt_fcgi.status = 200;
+ clt->clt_fcgi.headersdone = 0;
if (clt->clt_srvevb != NULL)
evbuffer_free(clt->clt_srvevb);
@@ -387,13 +386,13 @@ server_fcgi(struct httpd *env, struct client *clt)
}
if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
- clt->clt_fcgi_chunked = 1;
+ clt->clt_fcgi.chunked = 1;
} else {
/* HTTP/1.0 does not support chunked encoding */
- clt->clt_fcgi_chunked = 0;
+ clt->clt_fcgi.chunked = 0;
clt->clt_persist = 0;
}
- clt->clt_fcgi_end = 0;
+ clt->clt_fcgi.end = 0;
clt->clt_done = 0;
free(script);
@@ -499,36 +498,36 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
char *ptr;
do {
- len = bufferevent_read(bev, buf, clt->clt_fcgi_toread);
+ len = bufferevent_read(bev, buf, clt->clt_fcgi.toread);
if (evbuffer_add(clt->clt_srvevb, buf, len) == -1) {
server_abort_http(clt, 500, "short write");
return;
}
- clt->clt_fcgi_toread -= len;
+ clt->clt_fcgi.toread -= len;
DPRINTF("%s: len: %lu toread: %d state: %d type: %d",
- __func__, len, clt->clt_fcgi_toread,
- clt->clt_fcgi_state, clt->clt_fcgi_type);
+ __func__, len, clt->clt_fcgi.toread,
+ clt->clt_fcgi.state, clt->clt_fcgi.type);
- if (clt->clt_fcgi_toread != 0)
+ if (clt->clt_fcgi.toread != 0)
return;
- switch (clt->clt_fcgi_state) {
+ switch (clt->clt_fcgi.state) {
case FCGI_READ_HEADER:
- clt->clt_fcgi_state = FCGI_READ_CONTENT;
+ clt->clt_fcgi.state = FCGI_READ_CONTENT;
h = (struct fcgi_record_header *)
EVBUFFER_DATA(clt->clt_srvevb);
DPRINTF("%s: record header: version %d type %d id %d "
"content len %d padding %d", __func__,
h->version, h->type, ntohs(h->id),
ntohs(h->content_len), h->padding_len);
- clt->clt_fcgi_type = h->type;
- clt->clt_fcgi_toread = ntohs(h->content_len);
- clt->clt_fcgi_padding_len = h->padding_len;
+ clt->clt_fcgi.type = h->type;
+ clt->clt_fcgi.toread = ntohs(h->content_len);
+ clt->clt_fcgi.padding_len = h->padding_len;
evbuffer_drain(clt->clt_srvevb,
EVBUFFER_LENGTH(clt->clt_srvevb));
- if (clt->clt_fcgi_toread != 0)
+ if (clt->clt_fcgi.toread != 0)
break;
- else if (clt->clt_fcgi_type == FCGI_STDOUT &&
+ else if (clt->clt_fcgi.type == FCGI_STDOUT &&
!clt->clt_chunk) {
server_abort_http(clt, 500, "empty stdout");
return;
@@ -536,7 +535,7 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
/* fallthrough if content_len == 0 */
case FCGI_READ_CONTENT:
- switch (clt->clt_fcgi_type) {
+ switch (clt->clt_fcgi.type) {
case FCGI_STDERR:
if (EVBUFFER_LENGTH(clt->clt_srvevb) > 0 &&
(ptr = get_string(
@@ -549,13 +548,20 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
}
break;
case FCGI_STDOUT:
- if (++clt->clt_chunk == 1) {
- if (server_fcgi_header(clt,
- server_fcgi_getheaders(clt))
- == -1) {
- server_abort_http(clt, 500,
- "malformed fcgi headers");
- return;
+ ++clt->clt_chunk;
+ if (!clt->clt_fcgi.headersdone) {
+ clt->clt_fcgi.headersdone =
+ server_fcgi_getheaders(clt);
+ if (clt->clt_fcgi.headersdone) {
+ if (server_fcgi_header(clt,
+ clt->clt_fcgi.status)
+ == -1) {
+ server_abort_http(clt,
+ 500,
+ "malformed fcgi "
+ "headers");
+ return;
+ }
}
if (!EVBUFFER_LENGTH(clt->clt_srvevb))
break;
@@ -571,21 +577,21 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
}
evbuffer_drain(clt->clt_srvevb,
EVBUFFER_LENGTH(clt->clt_srvevb));
- if (!clt->clt_fcgi_padding_len) {
- clt->clt_fcgi_state = FCGI_READ_HEADER;
- clt->clt_fcgi_toread =
+ if (!clt->clt_fcgi.padding_len) {
+ clt->clt_fcgi.state = FCGI_READ_HEADER;
+ clt->clt_fcgi.toread =
sizeof(struct fcgi_record_header);
} else {
- clt->clt_fcgi_state = FCGI_READ_PADDING;
- clt->clt_fcgi_toread =
- clt->clt_fcgi_padding_len;
+ clt->clt_fcgi.state = FCGI_READ_PADDING;
+ clt->clt_fcgi.toread =
+ clt->clt_fcgi.padding_len;
}
break;
case FCGI_READ_PADDING:
evbuffer_drain(clt->clt_srvevb,
EVBUFFER_LENGTH(clt->clt_srvevb));
- clt->clt_fcgi_state = FCGI_READ_HEADER;
- clt->clt_fcgi_toread =
+ clt->clt_fcgi.state = FCGI_READ_HEADER;
+ clt->clt_fcgi.toread =
sizeof(struct fcgi_record_header);
break;
}
@@ -618,7 +624,7 @@ server_fcgi_header(struct client *clt, unsigned int code)
return (-1);
/* Set chunked encoding */
- if (clt->clt_fcgi_chunked) {
+ if (clt->clt_fcgi.chunked) {
/* XXX Should we keep and handle Content-Length instead? */
key.kv_key = "Content-Length";
if ((kv = kv_find(&resp->http_headers, &key)) != NULL)
@@ -655,8 +661,10 @@ server_fcgi_header(struct client *clt, unsigned int code)
}
/* Date header is mandatory and should be added as late as possible */
- if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
- kv_add(&resp->http_headers, "Date", tmbuf) == NULL)
+ key.kv_key = "Date";
+ if ((kv = kv_find(&resp->http_headers, &key)) == NULL &&
+ (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 ||
+ kv_add(&resp->http_headers, "Date", tmbuf) == NULL))
return (-1);
/* Write initial header (fcgi might append more) */
@@ -727,14 +735,14 @@ server_fcgi_writechunk(struct client *clt)
struct evbuffer *evb = clt->clt_srvevb;
size_t len;
- if (clt->clt_fcgi_type == FCGI_END_REQUEST) {
+ if (clt->clt_fcgi.type == FCGI_END_REQUEST) {
len = 0;
} else
len = EVBUFFER_LENGTH(evb);
- if (clt->clt_fcgi_chunked) {
+ if (clt->clt_fcgi.chunked) {
/* If len is 0, make sure to write the end marker only once */
- if (len == 0 && clt->clt_fcgi_end++)
+ if (len == 0 && clt->clt_fcgi.end++)
return (0);
if (server_bufferevent_printf(clt, "%zx\r\n", len) == -1 ||
server_bufferevent_write_chunk(clt, evb, len) == -1 ||
@@ -751,7 +759,7 @@ server_fcgi_getheaders(struct client *clt)
{
struct http_descriptor *resp = clt->clt_descresp;
struct evbuffer *evb = clt->clt_srvevb;
- int code = 200;
+ int code, ret;
char *line, *key, *value;
const char *errstr;
@@ -760,12 +768,9 @@ server_fcgi_getheaders(struct client *clt)
if ((value = strchr(key, ':')) == NULL)
break;
- if (*value == ':') {
- *value++ = '\0';
- value += strspn(value, " \t");
- } else {
- *value++ = '\0';
- }
+
+ *value++ = '\0';
+ value += strspn(value, " \t");
DPRINTF("%s: %s: %s", __func__, key, value);
@@ -775,11 +780,15 @@ server_fcgi_getheaders(struct client *clt)
if (errstr != NULL || server_httperror_byid(
code) == NULL)
code = 200;
+ clt->clt_fcgi.status = code;
} else {
(void)kv_add(&resp->http_headers, key, value);
}
free(line);
}
- return (code);
+ ret = (line != NULL && *line == '\0');
+
+ free(line);
+ return ret;
}