On Mon, Jul 30, 2018 at 10:24:03AM -0600, Base Pr1me wrote:
> Sorry, this time with the correct diff.
>
> On 7/25/18 4:15 PM, Base Pr1me wrote:
> > Hi,
> >
> > I discovered that the wrong server configuration is evaluated in the
> > server_read_http function. Only the first server in httpd.conf is checked.
> > For
> > example, I have five servers setup in httpd.conf and the third server is the
> > only one with connection { max request body ####} set, because I desire it
> > to
> > accept larger uploads than the other servers. When the upload is initiated,
> > server one dictates the max request body size, globally.
> >
> > The attached diff moves the queue loop out of the server_response function
> > in to
> > its own function, as to not duplicate code.
> >
> > I don't know if this is the only place the wrong information is evaluated.
> > Also,
> > I'm not sure this is the best method to fix the problem, but it should
> > point the
> > powers that be in the right direction.
> >
> > Thanks,
> >
> > Tracey
> >
>
Hello,
I reworked the last sent diff. I missed fixing up the hostname. This was causing
an incorrect 301 on urls not containing an ending slash. I also moved the
srv_conf assignment into the new function.
Again, this is to use the correct server config information from the queue for
server_read_http and remove code duplication.
If anyone is willing to look at this and make suggestions, that'd be great. If
not, that'd be great too! LOL. Have a great weekend.
Thanks,
Tracey
Index: src/usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.142
diff -u -p -u -r1.142 httpd.h
--- src/usr.sbin/httpd/httpd.h 11 Oct 2018 09:52:22 -0000 1.142
+++ src/usr.sbin/httpd/httpd.h 26 Oct 2018 20:52:26 -0000
@@ -691,6 +691,8 @@ const char *
char *server_http_parsehost(char *, char *, size_t, int *);
ssize_t server_http_time(time_t, char *, size_t);
int server_log_http(struct client *, unsigned int, size_t);
+int server_check_client_config(struct server_config *, struct client *,
+ struct kv *, char *);
/* server_file.c */
int server_file(struct httpd *, struct client *);
Index: src/usr.sbin/httpd/server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.126
diff -u -p -u -r1.126 server_http.c
--- src/usr.sbin/httpd/server_http.c 15 Oct 2018 08:16:17 -0000 1.126
+++ src/usr.sbin/httpd/server_http.c 26 Oct 2018 20:52:26 -0000
@@ -204,7 +204,7 @@ server_read_http(struct bufferevent *bev
char *line = NULL, *key, *value;
const char *errstr;
size_t size, linelen;
- struct kv *hdr = NULL;
+ struct kv *hdr = NULL, kv_key, *host;
getmonotime(&clt->clt_tv_last);
@@ -344,6 +344,15 @@ server_read_http(struct bufferevent *bev
goto abort;
}
+ kv_key.kv_key = "Host";
+ if ((host = kv_find(&desc->http_headers, &kv_key)) !=
+ NULL && host->kv_value == NULL)
+ host = NULL;
+
+ if (server_check_client_config(srv_conf, clt, host,
+ NULL))
+ goto fail;
+
/*
* Need to read data from the client after the
* HTTP header.
@@ -1183,10 +1192,7 @@ server_response(struct httpd *httpd, str
struct server *srv = clt->clt_srv;
struct server_config *srv_conf = &srv->srv_conf;
struct kv *kv, key, *host;
- struct str_find sm;
- int portval = -1, ret;
- char *hostval, *query;
- const char *errstr = NULL;
+ char *query;
/* Decode the URL */
if (desc->http_path == NULL ||
@@ -1234,58 +1240,8 @@ server_response(struct httpd *httpd, str
if (clt->clt_pipelining && clt->clt_toread > 0)
clt->clt_persist = 0;
- /*
- * Do we have a Host header and matching configuration?
- * XXX the Host can also appear in the URL path.
- */
- if (host != NULL) {
- if ((hostval = server_http_parsehost(host->kv_value,
- hostname, sizeof(hostname), &portval)) == NULL)
- goto fail;
-
- TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
-#ifdef DEBUG
- if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
- DPRINTF("%s: virtual host \"%s:%u\""
- " host \"%s\" (\"%s\")",
- __func__, srv_conf->name,
- ntohs(srv_conf->port), host->kv_value,
- hostname);
- }
-#endif
- if (srv_conf->flags & SRVFLAG_LOCATION)
- continue;
- else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
- str_find(hostname, srv_conf->name,
- &sm, 1, &errstr);
- ret = errstr == NULL ? 0 : -1;
- } else {
- ret = fnmatch(srv_conf->name,
- hostname, FNM_CASEFOLD);
- }
- if (ret == 0 &&
- (portval == -1 ||
- (portval != -1 && portval == srv_conf->port))) {
- /* Replace host configuration */
- clt->clt_srv_conf = srv_conf;
- srv_conf = NULL;
- break;
- }
- }
- }
-
- if (srv_conf != NULL) {
- /* Use the actual server IP address */
- if (server_http_host(&clt->clt_srv_ss, hostname,
- sizeof(hostname)) == NULL)
- goto fail;
- } else {
- /* Host header was valid and found */
- if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=
- sizeof(hostname))
- goto fail;
- srv_conf = clt->clt_srv_conf;
- }
+ if (server_check_client_config(srv_conf, clt, host, hostname))
+ goto fail;
if ((desc->http_host = strdup(hostname)) == NULL)
goto fail;
@@ -1764,4 +1720,69 @@ done:
free(agent_v);
return (ret);
+}
+
+int
+server_check_client_config(struct server_config *srv_conf, struct client *clt,
+ struct kv *host, char *hostname)
+{
+ struct server *srv = clt->clt_srv;
+ struct str_find sm;
+ size_t len = HOST_NAME_MAX+1;
+ int portval = -1, ret;
+ char *hostval;
+ const char *errstr = NULL;
+
+ /*
+ * Do we have a Host header and matching configuration?
+ * XXX the Host can also appear in the URL path.
+ */
+ if (host != NULL) {
+ if ((hostval = server_http_parsehost(host->kv_value,
+ hostname, len, &portval)) == NULL)
+ return(-1);
+
+ TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
+ DPRINTF("%s: virtual host \"%s:%u\""
+ " host \"%s\" (\"%s\")",
+ __func__, srv_conf->name,
+ ntohs(srv_conf->port), host->kv_value,
+ hostname);
+ }
+#endif
+ if (srv_conf->flags & SRVFLAG_LOCATION)
+ continue;
+ else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
+ str_find(hostname, srv_conf->name,
+ &sm, 1, &errstr);
+ ret = errstr == NULL ? 0 : -1;
+ } else {
+ ret = fnmatch(srv_conf->name,
+ hostname, FNM_CASEFOLD);
+ }
+ if (ret == 0 &&
+ (portval == -1 ||
+ (portval != -1 && portval == srv_conf->port))) {
+ /* Replace host configuration */
+ clt->clt_srv_conf = srv_conf;
+ srv_conf = NULL;
+ break;
+ }
+ }
+ }
+
+ if (srv_conf != NULL) {
+ /* Use the actual server IP address */
+ if (server_http_host(&clt->clt_srv_ss, hostname,
+ len) == NULL)
+ return(-1);
+ } else {
+ /* Host header was valid and found */
+ if (strlcpy(hostname, host->kv_value, len) >= len)
+ return(-1);
+ srv_conf = clt->clt_srv_conf;
+ }
+ return(0);
}
Index: src/usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.142
diff -u -p -u -r1.142 httpd.h
--- src/usr.sbin/httpd/httpd.h 11 Oct 2018 09:52:22 -0000 1.142
+++ src/usr.sbin/httpd/httpd.h 26 Oct 2018 20:52:26 -0000
@@ -691,6 +691,8 @@ const char *
char *server_http_parsehost(char *, char *, size_t, int *);
ssize_t server_http_time(time_t, char *, size_t);
int server_log_http(struct client *, unsigned int, size_t);
+int server_check_client_config(struct server_config *, struct client *,
+ struct kv *, char *);
/* server_file.c */
int server_file(struct httpd *, struct client *);
Index: src/usr.sbin/httpd/server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.126
diff -u -p -u -r1.126 server_http.c
--- src/usr.sbin/httpd/server_http.c 15 Oct 2018 08:16:17 -0000 1.126
+++ src/usr.sbin/httpd/server_http.c 26 Oct 2018 20:52:26 -0000
@@ -204,7 +204,7 @@ server_read_http(struct bufferevent *bev
char *line = NULL, *key, *value;
const char *errstr;
size_t size, linelen;
- struct kv *hdr = NULL;
+ struct kv *hdr = NULL, kv_key, *host;
getmonotime(&clt->clt_tv_last);
@@ -344,6 +344,15 @@ server_read_http(struct bufferevent *bev
goto abort;
}
+ kv_key.kv_key = "Host";
+ if ((host = kv_find(&desc->http_headers, &kv_key)) !=
+ NULL && host->kv_value == NULL)
+ host = NULL;
+
+ if (server_check_client_config(srv_conf, clt, host,
+ NULL))
+ goto fail;
+
/*
* Need to read data from the client after the
* HTTP header.
@@ -1183,10 +1192,7 @@ server_response(struct httpd *httpd, str
struct server *srv = clt->clt_srv;
struct server_config *srv_conf = &srv->srv_conf;
struct kv *kv, key, *host;
- struct str_find sm;
- int portval = -1, ret;
- char *hostval, *query;
- const char *errstr = NULL;
+ char *query;
/* Decode the URL */
if (desc->http_path == NULL ||
@@ -1234,58 +1240,8 @@ server_response(struct httpd *httpd, str
if (clt->clt_pipelining && clt->clt_toread > 0)
clt->clt_persist = 0;
- /*
- * Do we have a Host header and matching configuration?
- * XXX the Host can also appear in the URL path.
- */
- if (host != NULL) {
- if ((hostval = server_http_parsehost(host->kv_value,
- hostname, sizeof(hostname), &portval)) == NULL)
- goto fail;
-
- TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
-#ifdef DEBUG
- if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
- DPRINTF("%s: virtual host \"%s:%u\""
- " host \"%s\" (\"%s\")",
- __func__, srv_conf->name,
- ntohs(srv_conf->port), host->kv_value,
- hostname);
- }
-#endif
- if (srv_conf->flags & SRVFLAG_LOCATION)
- continue;
- else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
- str_find(hostname, srv_conf->name,
- &sm, 1, &errstr);
- ret = errstr == NULL ? 0 : -1;
- } else {
- ret = fnmatch(srv_conf->name,
- hostname, FNM_CASEFOLD);
- }
- if (ret == 0 &&
- (portval == -1 ||
- (portval != -1 && portval == srv_conf->port))) {
- /* Replace host configuration */
- clt->clt_srv_conf = srv_conf;
- srv_conf = NULL;
- break;
- }
- }
- }
-
- if (srv_conf != NULL) {
- /* Use the actual server IP address */
- if (server_http_host(&clt->clt_srv_ss, hostname,
- sizeof(hostname)) == NULL)
- goto fail;
- } else {
- /* Host header was valid and found */
- if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=
- sizeof(hostname))
- goto fail;
- srv_conf = clt->clt_srv_conf;
- }
+ if (server_check_client_config(srv_conf, clt, host, hostname))
+ goto fail;
if ((desc->http_host = strdup(hostname)) == NULL)
goto fail;
@@ -1764,4 +1720,69 @@ done:
free(agent_v);
return (ret);
+}
+
+int
+server_check_client_config(struct server_config *srv_conf, struct client *clt,
+ struct kv *host, char *hostname)
+{
+ struct server *srv = clt->clt_srv;
+ struct str_find sm;
+ size_t len = HOST_NAME_MAX+1;
+ int portval = -1, ret;
+ char *hostval;
+ const char *errstr = NULL;
+
+ /*
+ * Do we have a Host header and matching configuration?
+ * XXX the Host can also appear in the URL path.
+ */
+ if (host != NULL) {
+ if ((hostval = server_http_parsehost(host->kv_value,
+ hostname, len, &portval)) == NULL)
+ return(-1);
+
+ TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
+#ifdef DEBUG
+ if ((srv_conf->flags & SRVFLAG_LOCATION) == 0) {
+ DPRINTF("%s: virtual host \"%s:%u\""
+ " host \"%s\" (\"%s\")",
+ __func__, srv_conf->name,
+ ntohs(srv_conf->port), host->kv_value,
+ hostname);
+ }
+#endif
+ if (srv_conf->flags & SRVFLAG_LOCATION)
+ continue;
+ else if (srv_conf->flags & SRVFLAG_SERVER_MATCH) {
+ str_find(hostname, srv_conf->name,
+ &sm, 1, &errstr);
+ ret = errstr == NULL ? 0 : -1;
+ } else {
+ ret = fnmatch(srv_conf->name,
+ hostname, FNM_CASEFOLD);
+ }
+ if (ret == 0 &&
+ (portval == -1 ||
+ (portval != -1 && portval == srv_conf->port))) {
+ /* Replace host configuration */
+ clt->clt_srv_conf = srv_conf;
+ srv_conf = NULL;
+ break;
+ }
+ }
+ }
+
+ if (srv_conf != NULL) {
+ /* Use the actual server IP address */
+ if (server_http_host(&clt->clt_srv_ss, hostname,
+ len) == NULL)
+ return(-1);
+ } else {
+ /* Host header was valid and found */
+ if (strlcpy(hostname, host->kv_value, len) >= len)
+ return(-1);
+ srv_conf = clt->clt_srv_conf;
+ }
+ return(0);
}