X-Git-Url: http://git.openwrt.org//?a=blobdiff_plain;f=client.c;h=05044ed9d38dc3755a80a9cd8e2c7cc2cbf631c9;hb=242401f544df790b1df7d12b3be5f5b429da091c;hp=0d7029bbccfbe0233455fa97123679d38a09ca69;hpb=248d682e3b3887a535d4ba81fab65f3463373ac8;p=project%2Fuhttpd.git diff --git a/client.c b/client.c index 0d7029b..05044ed 100644 --- a/client.c +++ b/client.c @@ -45,8 +45,10 @@ const char * const http_methods[] = { void uh_http_header(struct client *cl, int code, const char *summary) { struct http_request *r = &cl->request; + struct blob_attr *cur; const char *enc = "Transfer-Encoding: chunked\r\n"; const char *conn; + int rem; cl->http_code = code; @@ -64,6 +66,10 @@ void uh_http_header(struct client *cl, int code, const char *summary) if (!r->connection_close) ustream_printf(cl->us, "Keep-Alive: timeout=%d\r\n", conf.http_keepalive); + + blobmsg_for_each_attr(cur, cl->hdr_response.head, rem) + ustream_printf(cl->us, "%s: %s\r\n", blobmsg_name(cur), + blobmsg_get_string(cur)); } static void uh_connection_close(struct client *cl) @@ -114,6 +120,7 @@ void uh_request_done(struct client *cl) { uh_chunk_eof(cl); uh_dispatch_done(cl); + blob_buf_init(&cl->hdr_response, 0); memset(&cl->dispatch, 0, sizeof(cl->dispatch)); if (!conf.http_keepalive || cl->request.connection_close) @@ -228,6 +235,52 @@ static bool rfc1918_filter_check(struct client *cl) return false; } +static bool tls_redirect_check(struct client *cl) +{ + int rem, port; + struct blob_attr *cur; + char *ptr, *url = NULL, *host = NULL; + + if (cl->tls || !conf.tls_redirect) + return true; + + if ((port = uh_first_tls_port(cl->srv_addr.family)) == -1) + return true; + + blob_for_each_attr(cur, cl->hdr.head, rem) { + if (!strcmp(blobmsg_name(cur), "host")) + host = blobmsg_get_string(cur); + + if (!strcmp(blobmsg_name(cur), "URL")) + url = blobmsg_get_string(cur); + + if (url && host) + break; + } + + if (!url || !host) + return true; + + if ((ptr = strchr(host, ']')) != NULL) + *(ptr+1) = 0; + else if ((ptr = strchr(host, ':')) != NULL) + *ptr = 0; + + cl->request.disable_chunked = true; + cl->request.connection_close = true; + + uh_http_header(cl, 307, "Temporary Redirect"); + + if (port != 443) + ustream_printf(cl->us, "Location: https://%s:%d%s\r\n\r\n", host, port, url); + else + ustream_printf(cl->us, "Location: https://%s%s\r\n\r\n", host, url); + + uh_request_done(cl); + + return false; +} + static void client_header_complete(struct client *cl) { struct http_request *r = &cl->request; @@ -235,6 +288,9 @@ static void client_header_complete(struct client *cl) if (!rfc1918_filter_check(cl)) return; + if (!tls_redirect_check(cl)) + return; + if (r->expect_cont) ustream_printf(cl->us, "HTTP/1.1 100 Continue\r\n\r\n"); @@ -481,6 +537,7 @@ static void client_close(struct client *cl) close(cl->sfd.fd.fd); list_del(&cl->list); blob_buf_free(&cl->hdr); + blob_buf_free(&cl->hdr_response); free(cl); uh_unblock_listeners();