From 991795c2969157049f77a8e979b9cd842d747a61 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Thu, 2 Oct 2025 15:52:14 +0300 Subject: [PATCH 1/2] Fix to redirect to HTTPS when we get the host from the browser URL --- miniserv.pl | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/miniserv.pl b/miniserv.pl index 01a67253d..3edfbb758 100755 --- a/miniserv.pl +++ b/miniserv.pl @@ -1381,33 +1381,8 @@ $method = $page = $request_uri = undef; print DEBUG "handle_request reqline=$reqline\n"; alarm(0); if (!$use_ssl && $config{'ssl'} && $config{'ssl_enforce'}) { - # This is an http request when https must be enforced - local $hostname = $host; - if ($hostname !~ /\./) { - my $system_hostname = &get_system_hostname(); - $hostname = $system_hostname if ($system_hostname =~ /\./); - } - local $urlhost = $config{'musthost'} || $hostname; - $urlhost = "[".$urlhost."]" if (&check_ip6address($urlhost)); - local $wantport = $port; - if ($wantport == 80 && - &indexof(443, @listening_on_ports) >= 0) { - # Connection was to port 80, but since we are also - # accepting on port 443, redirect to that - $wantport = 443; - } - local $url = $wantport == 443 - ? "https://$urlhost/" - : "https://$urlhost:$wantport/"; - &write_data("HTTP/1.0 302 Moved Temporarily\r\n"); - &write_data("Date: $datestr\r\n"); - &write_data("Server: @{[&server_info()]}\r\n"); - &write_data("Location: $url\r\n"); - &write_keep_alive(0); - &write_data("\r\n"); - &log_error("Redirecting HTTP request to HTTPS using $urlhost host"); - &log_request($loghost, $authuser, $reqline, 302, 0); - return 0; + # This is an http request when https must be enforced later when + # we know the requested host } elsif (!$reqline && $checked_timeout > 1) { # An empty request .. just close the connection @@ -1510,6 +1485,31 @@ if (defined($header{'host'})) { } } +# This is an http request when https must be enforced +if (!$use_ssl && $config{'ssl'} && $config{'ssl_enforce'}) { + local $urlhost = $config{'musthost'} || $host; + $urlhost = "[".$urlhost."]" if (&check_ip6address($urlhost)); + local $wantport = $port; + if ($wantport == 80 && + &indexof(443, @listening_on_ports) >= 0) { + # Connection was to port 80, but since we are also + # accepting on port 443, redirect to that + $wantport = 443; + } + local $url = $wantport == 443 + ? "https://$urlhost/" + : "https://$urlhost:$wantport/"; + &write_data("HTTP/1.0 302 Moved Temporarily\r\n"); + &write_data("Date: $datestr\r\n"); + &write_data("Server: @{[&server_info()]}\r\n"); + &write_data("Location: $url\r\n"); + &write_keep_alive(0); + &write_data("\r\n"); + &log_error("Redirecting HTTP request to HTTPS using $urlhost host"); + &log_request($loghost, $authuser, $reqline, 302, 0); + return 0; + } + # Create strings for use in redirects $ssl = $config{'redirect_ssl'} ne '' ? $config{'redirect_ssl'} : $use_ssl; $redirport = $config{'redirect_port'} || $port; From d694649872573faedb75967ec74657a80b3709b5 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Fri, 3 Oct 2025 03:19:54 +0300 Subject: [PATCH 2/2] Fix to safely get user hostname from URL --- miniserv.pl | 71 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/miniserv.pl b/miniserv.pl index 3edfbb758..985196ec4 100755 --- a/miniserv.pl +++ b/miniserv.pl @@ -1381,8 +1381,50 @@ $method = $page = $request_uri = undef; print DEBUG "handle_request reqline=$reqline\n"; alarm(0); if (!$use_ssl && $config{'ssl'} && $config{'ssl_enforce'}) { - # This is an http request when https must be enforced later when - # we know the requested host + # This is an HTTP request when HTTPS should be enforced + my $musthost = $config{'musthost'}; + my $hostheader; + if (!$musthost) { + # Read host HTTP header because we want one earlier + alarm(10); + local $SIG{'ALRM'} = sub { die "timeout" }; + while (defined(my $line = &read_line())) { + $line =~ s/\r|\n//g; + last if $line eq ''; + if ($line =~ /^host:\s*(.*)$/i) { + $hostheader = "https://$1"; + last; + } + } + alarm(0); + } + # Host header must already contain full URL + my $url = $hostheader; + if (!$url) { + # No host header + local $urlhost = $musthost || $host; + $urlhost = "[".$urlhost."]" if (&check_ip6address($urlhost)); + local $wantport = $port; + if ($wantport == 80 && + &indexof(443, @listening_on_ports) >= 0) { + # Connection was to port 80, but since we are also + # accepting on port 443, redirect to that + $wantport = 443; + } + $url = $wantport == 443 + ? "https://$urlhost/" + : "https://$urlhost:$wantport/"; + } + # Enforce HTTPS + &write_data("HTTP/1.0 302 Moved Temporarily\r\n"); + &write_data("Date: $datestr\r\n"); + &write_data("Server: @{[&server_info()]}\r\n"); + &write_data("Location: $url\r\n"); + &write_keep_alive(0); + &write_data("\r\n"); + &log_error("Redirecting HTTP request to $url"); + &log_request($loghost, $authuser, $reqline, 302, 0); + return 0; } elsif (!$reqline && $checked_timeout > 1) { # An empty request .. just close the connection @@ -1485,31 +1527,6 @@ if (defined($header{'host'})) { } } -# This is an http request when https must be enforced -if (!$use_ssl && $config{'ssl'} && $config{'ssl_enforce'}) { - local $urlhost = $config{'musthost'} || $host; - $urlhost = "[".$urlhost."]" if (&check_ip6address($urlhost)); - local $wantport = $port; - if ($wantport == 80 && - &indexof(443, @listening_on_ports) >= 0) { - # Connection was to port 80, but since we are also - # accepting on port 443, redirect to that - $wantport = 443; - } - local $url = $wantport == 443 - ? "https://$urlhost/" - : "https://$urlhost:$wantport/"; - &write_data("HTTP/1.0 302 Moved Temporarily\r\n"); - &write_data("Date: $datestr\r\n"); - &write_data("Server: @{[&server_info()]}\r\n"); - &write_data("Location: $url\r\n"); - &write_keep_alive(0); - &write_data("\r\n"); - &log_error("Redirecting HTTP request to HTTPS using $urlhost host"); - &log_request($loghost, $authuser, $reqline, 302, 0); - return 0; - } - # Create strings for use in redirects $ssl = $config{'redirect_ssl'} ne '' ? $config{'redirect_ssl'} : $use_ssl; $redirport = $config{'redirect_port'} || $port;