-/* $OpenBSD: http.h,v 1.3 2014/07/13 15:11:23 reyk Exp $ */
+/* $OpenBSD: http.h,v 1.4 2014/07/25 23:23:39 reyk Exp $ */
/*
* Copyright (c) 2012 - 2014 Reyk Floeter <reyk@openbsd.org>
#ifndef _HTTP_H
#define _HTTP_H
+#define HTTP_PORT 80
+#define HTTPS_PORT 443
+
enum httpmethod {
HTTP_METHOD_NONE = 0,
#define query_key http_matchquery.kv_key
#define query_val http_matchquery.kv_value
- char *http_version;
+ char http_host[MAXHOSTNAMELEN];
enum httpmethod http_method;
int http_chunked;
+ char *http_version;
/* A tree of headers and attached lists for repeated headers. */
- struct kvtree http_headers;
struct kv *http_lastheader;
+ struct kvtree http_headers;
};
#endif /* _HTTP_H */
-/* $OpenBSD: httpd.h,v 1.13 2014/07/25 21:29:58 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.14 2014/07/25 23:23:39 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
void *clt_srv;
void *clt_srv_conf;
u_int32_t clt_srv_id;
+ struct sockaddr_storage clt_srv_ss;
int clt_s;
in_port_t clt_port;
void server_reset_http(struct client *);
void server_close_http(struct client *);
int server_response(struct httpd *, struct client *);
+const char *
+ server_http_host(struct sockaddr_storage *, char *, size_t);
/* server_file.c */
int server_file(struct httpd *, struct client *);
-/* $OpenBSD: server.c,v 1.11 2014/07/25 16:23:19 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.12 2014/07/25 23:23:39 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
clt->clt_srv_id = srv->srv_conf.id;
clt->clt_pid = getpid();
clt->clt_inflight = 1;
+
+ /* get local address */
+ slen = sizeof(clt->clt_srv_ss);
+ if (getsockname(s, (struct sockaddr *)&clt->clt_srv_ss,
+ &slen) == -1) {
+ server_close(clt, "listen address lookup failed");
+ return;
+ }
+
+ /* get client address */
+ memcpy(&clt->clt_ss, &ss, sizeof(clt->clt_ss));
+
+ /* get ports */
switch (ss.ss_family) {
case AF_INET:
clt->clt_port = ((struct sockaddr_in *)&ss)->sin_port;
clt->clt_port = ((struct sockaddr_in6 *)&ss)->sin6_port;
break;
}
- memcpy(&clt->clt_ss, &ss, sizeof(clt->clt_ss));
getmonotime(&clt->clt_tv_start);
memcpy(&clt->clt_tv_last, &clt->clt_tv_start, sizeof(clt->clt_tv_last));
void
server_close(struct client *clt, const char *msg)
{
- char ibuf[128], obuf[128], *ptr = NULL;
+ char ibuf[MAXHOSTNAMELEN], obuf[MAXHOSTNAMELEN];
+ char *ptr = NULL;
struct server *srv = clt->clt_srv;
struct server_config *srv_conf = clt->clt_srv_conf;
memset(&ibuf, 0, sizeof(ibuf));
memset(&obuf, 0, sizeof(obuf));
(void)print_host(&clt->clt_ss, ibuf, sizeof(ibuf));
- (void)print_host(&srv_conf->ss, obuf, sizeof(obuf));
+ (void)server_http_host(&clt->clt_srv_ss, obuf, sizeof(obuf));
if (EVBUFFER_LENGTH(clt->clt_log) &&
evbuffer_add_printf(clt->clt_log, "\r\n") != -1)
ptr = evbuffer_readline(clt->clt_log);
log_info("server %s, "
- "client %d (%d active), %s -> %s:%d, "
+ "client %d (%d active), %s:%u -> %s, "
"%s%s%s", srv_conf->name, clt->clt_id, server_clients,
- ibuf, obuf, ntohs(clt->clt_port), msg,
+ ibuf, ntohs(clt->clt_port), obuf, msg,
ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
if (ptr != NULL)
free(ptr);
-/* $OpenBSD: server_file.c,v 1.15 2014/07/25 21:29:58 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.16 2014/07/25 23:23:39 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
/* Redirect to path with trailing "/" */
if (path[strlen(path) - 1] != '/') {
- if (asprintf(&newpath, "%s/", desc->http_path) == -1)
+ if (asprintf(&newpath, "http://%s%s/",
+ desc->http_host, desc->http_path) == -1)
return (500);
free(desc->http_path);
desc->http_path = newpath;
-/* $OpenBSD: server_http.c,v 1.17 2014/07/25 21:48:05 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.18 2014/07/25 23:23:39 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm);
}
+const char *
+server_http_host(struct sockaddr_storage *ss, char *buf, size_t len)
+{
+ char hbuf[MAXHOSTNAMELEN];
+ in_port_t port;
+
+ if (print_host(ss, buf, len) == NULL)
+ return (NULL);
+
+ port = ntohs(server_socket_getport(ss));
+ if (port == HTTP_PORT)
+ return (buf);
+
+ switch (ss->ss_family) {
+ case AF_INET:
+ if ((size_t)snprintf(hbuf, sizeof(hbuf),
+ "%s:%u", buf, port) >= sizeof(hbuf))
+ return (NULL);
+ break;
+ case AF_INET6:
+ if ((size_t)snprintf(hbuf, sizeof(hbuf),
+ "[%s]:%u", buf, port) >= sizeof(hbuf))
+ return (NULL);
+ break;
+ }
+
+ if (strlcpy(buf, hbuf, len) >= len)
+ return (NULL);
+
+ return (buf);
+}
+
void
server_abort_http(struct client *clt, u_int code, const char *msg)
{
char path[MAXPATHLEN];
struct http_descriptor *desc = clt->clt_desc;
struct server *srv = clt->clt_srv;
- struct server_config *srv_conf;
- struct kv *kv, key;
+ struct server_config *srv_conf = &srv->srv_conf;
+ struct kv *kv, key, *host;
int ret;
/* Canonicalize the request path */
if ((desc->http_path = strdup(path)) == NULL)
goto fail;
+ key.kv_key = "Host";
+ if ((host = kv_find(&desc->http_headers, &key)) != NULL &&
+ host->kv_value == NULL)
+ host = NULL;
+
if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
/* Host header is mandatory */
- key.kv_key = "Host";
- if ((kv = kv_find(&desc->http_headers, &key)) == NULL)
+ if (host == NULL)
goto fail;
/* Is the connection persistent? */
* Do we have a Host header and matching configuration?
* XXX the Host can also appear in the URL path.
*/
- key.kv_key = "Host";
- if ((kv = kv_find(&desc->http_headers, &key)) != NULL) {
+ if (host != NULL) {
/* XXX maybe better to turn srv_hosts into a tree */
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
- if (fnmatch(srv_conf->name, kv->kv_value,
+ if (fnmatch(srv_conf->name, host->kv_value,
FNM_CASEFOLD) == 0) {
/* 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, desc->http_host,
+ sizeof(desc->http_host)) == NULL)
+ goto fail;
+ } else {
+ /* Host header was valid and found */
+ if (strlcpy(desc->http_host, host->kv_value,
+ sizeof(desc->http_host)) >= sizeof(desc->http_host))
+ goto fail;
+ }
+
if ((ret = server_file(httpd, clt)) == -1)
return (-1);