Tags:
create new tag
, view all tags

Bug: Redirection from view to viewauth can fail if the RewriteEngine is used

The function view in lib/TWiki/UI/View.pm assumes that REQUEST_URI contains "/view". If URIs are rewritten using Apache's RewriteEngine, this assumption is not necessarily true, resulting in a redirection endless loop.

Test case

Add a rewrite rule in Apache's httpd.conf file

RewriteEngine on
RewriteRule ^/main/(.*) /twiki/bin/view/Main/$1 [l,pt]

Using "http://127.0.0.1/main/WebHome" and other existing Topics works correctly as expected. Whereas accessing "http://127.0.0.1/main/NotExistingTopic" will fail with an unlimited redirection browser error message.

The httpd access log file shows a series of redirections to the same URL (in the un-rewritten form). If the rewrite logging is activated, it shows the correct URL rewriting from "/main/NotExistingTopic" to "/twiki/bin/view/Main/NotExistingTopic". Thus the RewriteRule is applied correctly.

The problem lays in the hardcoded replacement of "/view" by "/viewauth" in the view function in lib/TWiki/UI/View.pm for non-existing topics. For rewritten URLs the environment variable REQUEST_URI holds the original URL which does not contain "/view". Thus the replacement leaves the URI unchanged. As a result the client's browser is redirected to the same location over and over.

This can be fixed by testing for "/view" in REQUEST_URI.

A second bug exists in the original code if REQUEST_URI is empty. For this case the redirection is constructed using SCRIPT_FILENAME which is prefixed by the $TWiki::scriptUrlPath. SCRIPT_FILENAME is usually an absolute path name of the CGI script, thus the absolute part of the path name (including the $TWiki::scriptUrlPath part) has to be deleted before the redirection URI is constructed. Otherwise the browser will be redirected to something like "http://127.0.0.1/twiki/bin//usr/local/httpd/twiki/bin/viewauth/Main/NotExistingTopic".

This can be fixed by stripping off the prefix before "/viewauth". In addition one can use the environment variable SCRIPT_NAME containing the relative URL to the CGI script instead if it exists.

Environment

TWiki version: TWikiBetaRelease2004x07x29
TWiki plugins: DefaultPlugin, EmptyPlugin, InterwikiPlugin
Server OS: SuSE Linux 7.3
Web server: Apache 1.3.20
Perl version: 5.6.1
Client OS:  
Web Browser:  

-- BerndRaichle - 06 Aug 2004

Follow up

Here is a fix proposal.

Fix record

*** lib/TWiki/UI/View.pm_ORIG   Sat Jul 10 10:15:22 2004
--- lib/TWiki/UI/View.pm   Fri Aug  6 14:46:59 2004
***************
*** 257,266 ****
        # instead of non authenticated view script
        my $url = $ENV{"REQUEST_URI"};
!       if( $url ) {
          # $url i.e. is "twiki/bin/view.cgi/Web/Topic?cms1=val1&cmd2=val2"
          $url =~ s|/view|/viewauth|o;
          $url = "$TWiki::urlHost$url";
        } else {
          $url = "$TWiki::urlHost$TWiki::scriptUrlPath/$viewauthFile/$webName/$topic";
        }
        TWiki::UI::redirect( $url );
--- 257,277 ----
        # instead of non authenticated view script
        my $url = $ENV{"REQUEST_URI"};
!       if( $url && $url =~ m|/view| ) {
          # $url i.e. is "twiki/bin/view.cgi/Web/Topic?cms1=val1&cmd2=val2"
          $url =~ s|/view|/viewauth|o;
          $url = "$TWiki::urlHost$url";
        } else {
+         # If REQUEST_URI is rewritten and does not contain the name "view"
+         # try looking at the CGI environment variable SCRIPT_NAME.
+         $url = $ENV{'SCRIPT_NAME'};
+         if ($url && $url =~ m|/view| ) {
+           $url =~ s|/view|/viewauth|o;
+           $url = "$TWiki::urlHost$url/$webName/$topic";
+         } else {
+           # If SCRIPT_NAME doesn not contain the name "view"
+           # the last hope is to try the SCRIPT_FILENAME ...
+           $viewauthFile =~ s|^.*/viewauth|/viewauth|o;  # strip off $Twiki::scriptUrlPath
            $url = "$TWiki::urlHost$TWiki::scriptUrlPath/$viewauthFile/$webName/$topic";
+         }
        }
        TWiki::UI::redirect( $url );

-- BerndRaichle - 06 Aug 2004

Fix commited to SVN, thankyou very much for the patch! - sorry for the delay.

-- SvenDowideit - 22 Aug 2004

I have not tested this, but reading the code it looks like the spec changes and possibly introduces a new bug. Assuming the full URL path is /rewritten/Web/Topic?cmd1=val1&cmd2=val2, it will go into the first else part, then into the second else where it builds the URL and throws away the extended path cmd1=val1&cmd2=val2.

-- PeterThoeny - 22 Aug 2004

This is true. Btw., the second else in the original code has the same restriction (it is now the third else). But in the original code the else branch is only executed if REQUEST_URI has no value, which doesn't happen if an httpd like Apache is used.

To fix this problem one can either assemble the URL using SCRIPT_NAME, PATH_INFO, and QUERY_STRING or disassemble REQUEST_URI into the part before $webName/$topic, and the part after it. Looking at the CGI 1.1 standard, SCRIPT_NAME, PATH_INFO, and QUERY_STRING are in the canonical list of request variables, whereas REQUEST_URI is not. Thus I prefer to use the assembling approach.

Fix record (second try)

*** View.pm   Fri Aug  6 14:46:59 2004
--- View.pm   Mon Aug 23 16:45:14 2004
***************
*** 264,276 ****
          # If REQUEST_URI is rewritten and does not contain the name "view"
          # try looking at the CGI environment variable SCRIPT_NAME.
!         $url = $ENV{'SCRIPT_NAME'};
!         if ($url && $url =~ m|/view| ) {
!           $url =~ s|/view|/viewauth|o;
!           $url = "$TWiki::urlHost$url/$webName/$topic";
          } else {
!           # If SCRIPT_NAME doesn not contain the name "view"
            # the last hope is to try the SCRIPT_FILENAME ...
            $viewauthFile =~ s|^.*/viewauth|/viewauth|o;  # strip off $Twiki::scriptUrlPath
!           $url = "$TWiki::urlHost$TWiki::scriptUrlPath/$viewauthFile/$webName/$topic";
          }
        }
--- 264,284 ----
          # If REQUEST_URI is rewritten and does not contain the name "view"
          # try looking at the CGI environment variable SCRIPT_NAME.
!         #
!         # Assemble the new URL using the host, the changed script name,
!         # the path info, and the query string.  All three query variables
!         # are in the list of the canonical request meta variables in CGI 1.1.
!         my $script      = $ENV{'SCRIPT_NAME'};
!         my $pathInfo    = $ENV{'PATH_INFO'};
!         my $queryString = $ENV{'QUERY_STRING'};
!         $pathInfo    = '/' . $pathInfo    if ($pathInfo);
!         $queryString = '?' . $queryString if ($queryString);
!         if ($script && $script =~ m|/view| ) {
!           $script =~ s|/view|/viewauth|o;
!           $url = "$TWiki::urlHost$script$pathInfo$queryString";
          } else {
!           # If SCRIPT_NAME does not contain the name "view"
            # the last hope is to try the SCRIPT_FILENAME ...
            $viewauthFile =~ s|^.*/viewauth|/viewauth|o;  # strip off $Twiki::scriptUrlPath
!           $url = "$TWiki::urlHost$TWiki::scriptUrlPath/$viewauthFile$pathInfo$queryString";
          }
        }

-- BerndRaichle - 23 Aug 2004

Edit | Attach | Watch | Print version | History: r4 < r3 < r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r4 - 2004-08-23 - BerndRaichle
 
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.