Fix to safely get user hostname from URL

This commit is contained in:
Ilia Ross
2025-10-03 03:19:54 +03:00
parent 991795c296
commit d694649872

View File

@@ -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;