Handle hostnames with upper-case letters
[webmin.git] / miniserv.pl
index 8c95226..2975c84 100755 (executable)
@@ -879,13 +879,6 @@ while(1) {
                                $SIG{'HUP'} = 'IGNORE';
                                $SIG{'USR1'} = 'IGNORE';
 
-                               # Initialize SSL for this connection
-                               if ($use_ssl) {
-                                       $ssl_con = &ssl_connection_for_ip(
-                                                       SOCK, $ipv6fhs{$s});
-                                       $ssl_con || exit;
-                                       }
-
                                # Close the file handle for the session DBM
                                dbmclose(%sessiondb);
 
@@ -897,6 +890,13 @@ while(1) {
                                &close_all_sockets();
                                close(LISTEN);
 
+                               # Initialize SSL for this connection
+                               if ($use_ssl) {
+                                       $ssl_con = &ssl_connection_for_ip(
+                                                       SOCK, $ipv6fhs{$s});
+                                       $ssl_con || exit;
+                                       }
+
                                print DEBUG
                                  "main: Starting handle_request loop pid=$$\n";
                                while(&handle_request($peera, $locala,
@@ -1457,6 +1457,11 @@ if ($method eq 'POST' &&
        print DEBUG "handle_request: posted_data=$posted_data\n";
        }
 
+# Reject CONNECT request, which isn't supported
+if ($method eq "CONNECT") {
+       &http_error(405, "Method $method is not supported");
+       }
+
 # work out accepted encodings
 %acceptenc = map { $_, 1 } split(/,/, $header{'accept-encoding'});
 
@@ -1880,7 +1885,7 @@ if ($config{'userfile'}) {
                                &write_data("WWW-authenticate: Basic ".
                                           "realm=\"$config{'realm'}\"\r\n");
                                &write_keep_alive(0);
-                               &write_data("Content-type: text/html\r\n");
+                               &write_data("Content-type: text/html; Charset=iso-8859-1\r\n");
                                &write_data("\r\n");
                                &reset_byte_count();
                                &write_data("<html>\n");
@@ -2137,7 +2142,7 @@ if (-d _) {
        local $resp = "HTTP/1.0 $ok_code $ok_message\r\n".
                      "Date: $datestr\r\n".
                      "Server: $config{server}\r\n".
-                     "Content-type: text/html\r\n";
+                     "Content-type: text/html; Charset=iso-8859-1\r\n";
        &write_data($resp);
        &write_keep_alive(0);
        &write_data("\r\n");
@@ -2226,7 +2231,7 @@ if (&get_type($full) eq "internal/cgi" && $validated != 4) {
                }
        $ENV{"QUERY_STRING"} = $querystring;
        $ENV{"MINISERV_CONFIG"} = $config_file;
-       $ENV{"HTTPS"} = "ON" if ($use_ssl || $config{'inetd_ssl'});
+       $ENV{"HTTPS"} = $use_ssl || $config{'inetd_ssl'} ? "ON" : "";
        $ENV{"MINISERV_PID"} = $miniserv_main_pid;
        $ENV{"SESSION_ID"} = $session_id if ($session_id);
        $ENV{"LOCAL_USER"} = $localauth_user if ($localauth_user);
@@ -2550,7 +2555,7 @@ else {
        &write_data("HTTP/1.0 $_[0] $_[1]\r\n");
        &write_data("Server: $config{server}\r\n");
        &write_data("Date: $datestr\r\n");
-       &write_data("Content-type: text/html\r\n");
+       &write_data("Content-type: text/html; Charset=iso-8859-1\r\n");
        &write_keep_alive(0);
        &write_data("\r\n");
        &reset_byte_count();
@@ -3711,9 +3716,14 @@ return $get_socket_name_cache{$myaddr};
 sub run_login_script
 {
 if ($config{'login_script'}) {
-       system($config{'login_script'}.
-              " ".join(" ", map { quotemeta($_) || '""' } @_).
-              " >/dev/null 2>&1 </dev/null");
+       alarm(5);
+       $SIG{'ALRM'} = sub { die "timeout" };
+       eval {
+               system($config{'login_script'}.
+                      " ".join(" ", map { quotemeta($_) || '""' } @_).
+                      " >/dev/null 2>&1 </dev/null");
+               };
+       alarm(0);
        }
 }
 
@@ -3721,9 +3731,14 @@ if ($config{'login_script'}) {
 sub run_logout_script
 {
 if ($config{'logout_script'}) {
-       system($config{'logout_script'}.
-              " ".join(" ", map { quotemeta($_) || '""' } @_).
-              " >/dev/null 2>&1 </dev/null");
+       alarm(5);
+       $SIG{'ALRM'} = sub { die "timeout" };
+       eval {
+               system($config{'logout_script'}.
+                      " ".join(" ", map { quotemeta($_) || '""' } @_).
+                      " >/dev/null 2>&1 </dev/null");
+               };
+       alarm(0);
        }
 }
 
@@ -5170,7 +5185,9 @@ if (!$pid) {
        close(STDIN); close(STDOUT); close(STDERR);
        untie(*STDIN); untie(*STDOUT); untie(*STDERR);
        close($PASSINw); close($PASSOUTr);
-       $( = $uinfo[3]; $) = "$uinfo[3] $uinfo[3]";
+       ($(, $)) = ( $uinfo[3],
+                     "$uinfo[3] ".join(" ", $uinfo[3],
+                                            &other_groups($uinfo[0])) );
        ($>, $<) = ($uinfo[2], $uinfo[2]);
 
        close(SUDOw);
@@ -5215,6 +5232,19 @@ if ($PASSINw) {
 return $ok;
 }
 
+sub other_groups
+{
+my ($user) = @_;
+my @rv;
+setgrent();
+while(my @g = getgrent()) {
+        my @m = split(/\s+/, $g[3]);
+        push(@rv, $g[2]) if (&indexof($user, @m) >= 0);
+        }
+endgrent();
+return @rv;
+}
+
 # is_mobile_useragent(agent)
 # Returns 1 if some user agent looks like a cellphone or other mobile device,
 # such as a treo.
@@ -5255,19 +5285,24 @@ local @substrings = (
     "iPhone",            # Apple iPhone KHTML browser
     "iPod",              # iPod touch browser
     "MobileSafari",      # HTTP client in iPhone
-    "Android",           # gPhone
     "Opera Mini",        # Opera Mini
     "HTC_P3700",         # HTC mobile device
     "Pre/",              # Palm Pre
     "webOS/",            # Palm WebOS
     "Nintendo DS",       # DSi / DSi-XL
     );
+local @regexps = (
+    "Android.*Mobile",   # Android phone
+    );
 foreach my $p (@prefixes) {
        return 1 if ($agent =~ /^\Q$p\E/);
        }
 foreach my $s (@substrings, @mobile_agents) {
        return 1 if ($agent =~ /\Q$s\E/);
        }
+foreach my $s (@regexps) {
+       return 1 if ($agent =~ /$s/);
+       }
 return 0;
 }