improve error page/httpd logging and file permissions
authorAndrew Lorimer <andrew@lorimer.id.au>
Tue, 15 Oct 2019 11:22:54 +0000 (22:22 +1100)
committerAndrew Lorimer <andrew@lorimer.id.au>
Tue, 15 Oct 2019 11:22:54 +0000 (22:22 +1100)
gitweb/gitweb.perl
index 6f6c2e0de7ae73530bf1741412705e986870b999..49ed13b9dea06618cdc87481f55613c3cd7f6191 100755 (executable)
@@ -5,6 +5,8 @@
 # (C) 2005-2006, Kay Sievers <kay.sievers@vrfy.org>
 # (C) 2005, Christian Gierke
 #
 # (C) 2005-2006, Kay Sievers <kay.sievers@vrfy.org>
 # (C) 2005, Christian Gierke
 #
+# Modified by Andrew Lorimer, 2019
+#
 # This program is licensed under the GPLv2
 
 use 5.008;
 # This program is licensed under the GPLv2
 
 use 5.008;
@@ -14,7 +16,8 @@
 use filetest 'access';
 use CGI qw(:standard :escapeHTML -nosticky);
 use CGI::Util qw(unescape);
 use filetest 'access';
 use CGI qw(:standard :escapeHTML -nosticky);
 use CGI::Util qw(unescape);
-use CGI::Carp qw(fatalsToBrowser set_message);
+#use CGI::Carp qw(fatalsToBrowser set_message);
+use CGI::Carp qw(set_message);
 use Encode;
 use Fcntl ':mode';
 use File::Find qw();
 use Encode;
 use Fcntl ':mode';
 use File::Find qw();
@@ -972,7 +975,9 @@ sub evaluate_path_info {
        while ($project && !check_head_link("$projectroot/$project")) {
                $project =~ s,/*[^/]*$,,;
        }
        while ($project && !check_head_link("$projectroot/$project")) {
                $project =~ s,/*[^/]*$,,;
        }
-       return unless $project;
+        if (!$project) {
+          die_error(404, "Project $path_info not found");
+        }
        $input_params{'project'} = $project;
 
        # do not change any parameters if an action is given using the query string
        $input_params{'project'} = $project;
 
        # do not change any parameters if an action is given using the query string
@@ -1265,7 +1270,7 @@ sub handle_errors_html {
        # HTTP headers are already written, so it cannot write them itself
        die_error(undef, undef, $msg, -error_handler => 1, -no_http_header => 1);
 }
        # HTTP headers are already written, so it cannot write them itself
        die_error(undef, undef, $msg, -error_handler => 1, -no_http_header => 1);
 }
-#set_message(\&handle_errors_html);
+set_message(\&handle_errors_html);
 
 # dispatch
 sub dispatch {
 
 # dispatch
 sub dispatch {
@@ -1318,11 +1323,11 @@ sub run_request {
 
        # $projectroot and $projects_list might be set in gitweb config file
        $projects_list ||= $projectroot;
 
        # $projectroot and $projects_list might be set in gitweb config file
        $projects_list ||= $projectroot;
+       evaluate_git_dir();
 
        evaluate_query_params();
        evaluate_path_info();
        evaluate_and_validate_params();
 
        evaluate_query_params();
        evaluate_path_info();
        evaluate_and_validate_params();
-       evaluate_git_dir();
 
        configure_gitweb_features();
 
 
        configure_gitweb_features();
 
@@ -2717,6 +2722,7 @@ sub get_feed_info {
 # returns path to the core git executable and the --git-dir parameter as list
 sub git_cmd {
        $number_of_git_cmds++;
 # returns path to the core git executable and the --git-dir parameter as list
 sub git_cmd {
        $number_of_git_cmds++;
+        evaluate_git_dir();
        return $GIT, '--git-dir='.$git_dir;
 }
 
        return $GIT, '--git-dir='.$git_dir;
 }
 
@@ -4188,6 +4194,7 @@ sub print_nav_breadcrumbs {
                print_nav_breadcrumbs_path(@dirname);
                print $cgi->a({-href => href(action=>"summary")}, esc_html($projectbasename));
                if (defined $action) {
                print_nav_breadcrumbs_path(@dirname);
                print $cgi->a({-href => href(action=>"summary")}, esc_html($projectbasename));
                if (defined $action) {
+                        $action =~ s/_/ /;
                        my $action_print = $action ;
                        if (defined $opts{-action_extra}) {
                                $action_print = $cgi->a({-href => href(action=>$action)},
                        my $action_print = $action ;
                        if (defined $opts{-action_extra}) {
                                $action_print = $cgi->a({-href => href(action=>$action)},
@@ -4421,19 +4428,21 @@ sub die_error {
                500 => '500 Internal Server Error',
                503 => '503 Service Unavailable',
        );
                500 => '500 Internal Server Error',
                503 => '503 Service Unavailable',
        );
-       git_header_html($http_responses{$status}, undef, %opts);
-       print <<EOF;
+        git_header_html($http_responses{$status}, undef, %opts);
+
+        print <<EOF;
 <br /><br />
 <br /><br />
-$status - $error
-<br />
+<h1 id="error-code" class="$status">$status</h1>
+<p id="error-msg" class="$status">$error</p>
+<p id="error-link" class="$status"><a href="$base_url">go home</a></p>
 EOF
 EOF
-       if (defined $extra) {
+        if (defined $extra) {
                print "<hr />\n" .
                      "$extra\n";
        }
 
        git_footer_html();
                print "<hr />\n" .
                      "$extra\n";
        }
 
        git_footer_html();
-       goto DONE_GITWEB
+        die "$status - $error"
                unless ($opts{'-error_handler'});
 }
 
                unless ($opts{'-error_handler'});
 }
 
@@ -7195,18 +7204,24 @@ sub git_blob_plain {
        my $type = shift;
        my $expires;
 
        my $type = shift;
        my $expires;
 
+        my $base = $hash_base || git_get_head_hash($project);
        if (!defined $hash) {
                if (defined $file_name) {
        if (!defined $hash) {
                if (defined $file_name) {
-                       my $base = $hash_base || git_get_head_hash($project);
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
                                or die_error(404, "Cannot find file");
                } else {
                        die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^$oid_regex$/) {
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
                                or die_error(404, "Cannot find file");
                } else {
                        die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^$oid_regex$/) {
+                $file_name = git_get_path_by_hash($base, $hash);
                # blobs defined by non-textual hash id's can be cached
                $expires = "+1d";
        }
                # blobs defined by non-textual hash id's can be cached
                $expires = "+1d";
        }
+        my @treefilter_pattern = gitweb_get_feature('tree_filter');
+        if (not $file_name =~ /@treefilter_pattern/) {
+          die_error(403, "Access denied ($file_name)");
+        }
+
 
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
                or die_error(500, "Open git-cat-file blob '$hash' failed");
 
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
                or die_error(500, "Open git-cat-file blob '$hash' failed");
@@ -7256,18 +7271,23 @@ sub git_blob_plain {
 sub git_blob {
        my $expires;
 
 sub git_blob {
        my $expires;
 
+        my $base = $hash_base || git_get_head_hash($project);
        if (!defined $hash) {
                if (defined $file_name) {
        if (!defined $hash) {
                if (defined $file_name) {
-                       my $base = $hash_base || git_get_head_hash($project);
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
                                or die_error(404, "Cannot find file");
                } else {
                        die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^$oid_regex$/) {
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
                                or die_error(404, "Cannot find file");
                } else {
                        die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^$oid_regex$/) {
+                $file_name = git_get_path_by_hash($base, $hash);
                # blobs defined by non-textual hash id's can be cached
                $expires = "+1d";
        }
                # blobs defined by non-textual hash id's can be cached
                $expires = "+1d";
        }
+        my @treefilter_pattern = gitweb_get_feature('tree_filter');
+        if (not $file_name =~ /@treefilter_pattern/) {
+          die_error(403, "Access denied ($file_name)");
+        }
 
        my $have_blame = gitweb_check_feature('blame');
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
 
        my $have_blame = gitweb_check_feature('blame');
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash