summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/httpd/httpd.c36
-rw-r--r--usr.sbin/httpd/httpd.h3
-rw-r--r--usr.sbin/httpd/server_fcgi.c60
3 files changed, 74 insertions, 25 deletions
diff --git a/usr.sbin/httpd/httpd.c b/usr.sbin/httpd/httpd.c
index 4b631ec7353..720d1880d2b 100644
--- a/usr.sbin/httpd/httpd.c
+++ b/usr.sbin/httpd/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.19 2014/08/13 16:04:28 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.20 2014/09/01 09:32:43 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -631,6 +631,40 @@ socket_rlimit(int maxfd)
}
char *
+evbuffer_getline(struct evbuffer *evb)
+{
+ u_int8_t *ptr = EVBUFFER_DATA(evb);
+ size_t len = EVBUFFER_LENGTH(evb);
+ char *str;
+ u_int i;
+
+ /* Safe version of evbuffer_readline() */
+ if ((str = get_string(ptr, len)) == NULL)
+ return (NULL);
+
+ for (i = 0; str[i] != '\0'; i++) {
+ if (str[i] == '\r' || str[i] == '\n')
+ break;
+ }
+
+ if (i == len) {
+ free(str);
+ return (NULL);
+ }
+
+ str[i] = '\0';
+
+ if ((i + 1) < len) {
+ if (ptr[i] == '\r' && ptr[i + 1] == '\n')
+ i++;
+ }
+
+ evbuffer_drain(evb, ++i);
+
+ return (str);
+}
+
+char *
get_string(u_int8_t *ptr, size_t len)
{
size_t i;
diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h
index 04b1f052309..586ec09a192 100644
--- a/usr.sbin/httpd/httpd.h
+++ b/usr.sbin/httpd/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.55 2014/08/29 13:01:46 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.56 2014/09/01 09:32:43 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -543,6 +543,7 @@ 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);
void socket_rlimit(int);
+char *evbuffer_getline(struct evbuffer *);
char *get_string(u_int8_t *, size_t);
void *get_data(u_int8_t *, size_t);
int sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
diff --git a/usr.sbin/httpd/server_fcgi.c b/usr.sbin/httpd/server_fcgi.c
index fe97be040cb..c4d56c3c7de 100644
--- a/usr.sbin/httpd/server_fcgi.c
+++ b/usr.sbin/httpd/server_fcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_fcgi.c,v 1.35 2014/08/29 13:01:46 reyk Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.36 2014/09/01 09:32:43 reyk Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
@@ -87,9 +87,9 @@ struct server_fcgi_param {
int server_fcgi_header(struct client *, u_int);
void server_fcgi_read(struct bufferevent *, void *);
int server_fcgi_writeheader(struct client *, struct kv *, void *);
+int server_fcgi_getheaders(struct client *);
int fcgi_add_param(struct server_fcgi_param *, const char *, const char *,
struct client *);
-int get_status(struct evbuffer *);
int
server_fcgi(struct httpd *env, struct client *clt)
@@ -503,7 +503,7 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
EVBUFFER_LENGTH(clt->clt_srvevb) > 0) {
if (++clt->clt_chunk == 1)
server_fcgi_header(clt,
- get_status(clt->clt_srvevb));
+ server_fcgi_getheaders(clt));
server_bufferevent_write_buffer(clt,
clt->clt_srvevb);
}
@@ -569,7 +569,8 @@ server_fcgi_header(struct client *clt, u_int code)
/* Write initial header (fcgi might append more) */
if (server_writeresponse_http(clt) == -1 ||
server_bufferevent_print(clt, "\r\n") == -1 ||
- server_headers(clt, resp, server_writeheader_http, NULL) == -1)
+ server_headers(clt, resp, server_writeheader_http, NULL) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
return (-1);
return (0);
@@ -617,26 +618,39 @@ server_fcgi_writeheader(struct client *clt, struct kv *hdr, void *arg)
}
int
-get_status(struct evbuffer *bev)
+server_fcgi_getheaders(struct client *clt)
{
- int code;
- char *statusline, *tok;
- const char *errstr;
-
- /* XXX This is a hack. We need to parse the response header. */
- code = 200;
- if (strncmp(EVBUFFER_DATA(bev), "Status: ", strlen("Status: ")) == 0) {
- statusline = get_string(EVBUFFER_DATA(bev),
- EVBUFFER_LENGTH(bev));
- if (strtok(statusline, " ") != NULL) {
- if ((tok = strtok(NULL, " ")) != NULL) {
- code = (int) strtonum(tok, 100, 600, &errstr);
- if (errstr != NULL || server_httperror_byid(
- code) == NULL)
- code = 200;
- }
+ struct http_descriptor *resp = clt->clt_descresp;
+ struct evbuffer *evb = clt->clt_srvevb;
+ int code = 200;
+ char *line, *key, *value;
+ const char *errstr;
+
+ while ((line = evbuffer_getline(evb)) != NULL && *line != '\0') {
+ key = line;
+
+ if ((value = strchr(key, ':')) == NULL)
+ break;
+ if (*value == ':') {
+ *value++ = '\0';
+ value += strspn(value, " \t");
+ } else {
+ *value++ = '\0';
}
- free(statusline);
+
+ DPRINTF("%s: %s: %s", __func__, key, value);
+
+ if (strcasecmp("Status", key) == 0) {
+ value[strcspn(value, " \t")] = '\0';
+ code = (int)strtonum(value, 100, 600, &errstr);
+ if (errstr != NULL || server_httperror_byid(
+ code) == NULL)
+ code = 200;
+ } else {
+ (void)kv_add(&resp->http_headers, key, value);
+ }
+ free(line);
}
- return code;
+
+ return (code);
}