]> bicyclesonthemoon.info Git - yplom/proxy/commitdiff
Proxying works now!
authorb <b@05ce6ebb-7522-4a6e-a768-0026ae12be9f>
Fri, 13 Nov 2015 15:22:20 +0000 (15:22 +0000)
committerb <b@05ce6ebb-7522-4a6e-a768-0026ae12be9f>
Fri, 13 Nov 2015 15:22:20 +0000 (15:22 +0000)
git-svn-id: svn://botcastle1b/yplom/proxy@6 05ce6ebb-7522-4a6e-a768-0026ae12be9f

proxy.1.pl

index bf614ac4d9f4af8a1e76491d5801e37f18b8fd75..ad41fa31aae43a121f7feb65cb235b0cfc40d637 100755 (executable)
@@ -19,7 +19,6 @@ use POSIX qw(strftime);
 
 use constant REQUEST_HEADER_BLOCK => qr/^(accept-encoding|connection|te|transfer-encoding|via)$/;
 use constant RESPONSE_HEADER_BLOCK => qr/^(connection|content-encoding|content-length|trailer|transfer-encoding)$/;
-
 $accesstime = time();
 $timeout_unlock = TIMEOUT_UNLOCK*60;
 $timeout_inact = TIMEOUT_INACT*60;
@@ -27,16 +26,16 @@ $timeout_inact = TIMEOUT_INACT*60;
 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
 ###PATH;
 
-if (($ENV{'HTTP_HOST'} =~ UNLOCK_PROXY_HOST) and ($ENV{'PATH_INFO'} =~ UNLOCK_PROXY_PATH)){
+if (($ENV{'HTTP_HOST'} =~ UNLOCK_PROXY_HOST) and (urldecode($ENV{'PATH_INFO'}) =~ UNLOCK_PROXY_PATH)){
        unlock();
 }
 else {
-#      if(access()) {
+       if(access()) {
                proxy();
-#      }
-#      else {
-#              noaccess();
-#      }
+       }
+       else {
+               noaccess();
+       }
 }
 
 sub proxy {
@@ -46,29 +45,25 @@ sub proxy {
                return fail("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The proxy does not support the $ENV{'REQUEST_METHOD'} method.");
        }
        
-       if ($ENV{'REQUEST_URI'} =~ /^([a-z]*(:[0-9]*)?:\/\/.*)$/){
-               $URL=$1;
+       if ($ENV{'REQUEST_URI'} =~ /^[a-z]*(:[0-9]*)?:\/\/.*$/){
+               $URL=$ENV{'REQUEST_URI'};
        }
        else{
-               $URL=($ENV{'HTTPS'} eq 'on' ? 'https://' : 'http://');.$ENV{'HTTP_HOST'}.$ENV{'REQUEST_URI'};
+               $URL=($ENV{'HTTPS'} eq 'on' ? 'https://' : 'http://').$ENV{'HTTP_HOST'}.$ENV{'REQUEST_URI'};
        }
        
-       #HTTP_HOST might theoretically not agree with REQUESR_URI.
-       if ($URL =~ /^https*:\/\/(.*)$/) {
-               $host= $1;
-               $host =~ s/\/.*$//;
-               if($host =~ /^(.*):([0-9]+)$/) {
-                       $host=$1;
-                       $port=$2;
-               }
-               else {
-                       $port=($ENV{'HTTPS'} eq 'on' ? '443' : '80');
-               }
+       if (validateurl($URL)) { #validate URL against illegal characters
+               $URL =~ /^(.*)$/;
+               $URL = $1;
        }
        else {
-               return fail("Status: 400 Bad Request\n","400 Bad Request","The proxy couldn't understand this URL: $URL.");
+               return fail("Status: 400 Bad Request\n","400 Bad Request","Invalid URL: $URL.");
        }
        
+       if ($port eq ''){
+               $port=($ENV{'HTTPS'} eq 'on' ? '443' : '80');
+       }
+               
        if ($host =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) {#IP instead of hostname
                if ($host =~ /^((0*10\..*)|(0*127\..*)|(0*172\.0*((1[6-9])|(2[0-9])|(3[0-1]))\..*)|(0*192\.0*168\..*))$/) {
                        return fail("Status: 403 Forbidden\n","403 Forbidden","The proxy does not accept a private IP address $host as hostname.");
@@ -90,7 +85,9 @@ sub proxy {
                $uppath=$temppath.'u';
        } while (( -e $headpath) or ( -e $downpath) or ( -e $uppath));
        
-       @curl_arg=(CURL_PATH,'-s','-o',$downpath,'-D',$headpath); #-s
+       # @curl_arg=(CURL_PATH,'-o',$downpath,'-D',$headpath); #-s
+       @curl_arg=(CURL_PATH,'-i','-#'); #-s
+
        if ($ENV{'REQUEST_METHOD'} eq 'HEAD'){
                push @curl_arg, '-I';
        }
@@ -111,52 +108,193 @@ sub proxy {
                push @curl_arg, '--data-binary';
                push @curl_arg, '@'.$uppath;
        }
-       # foreach $envk (keys %ENV) { 
-               # if ($envk =~ /^HTTP_/) {
-                       # $headname=formatheader($envk);
-                       # $headval=$ENV{$envk};
-                       # if ($headname !~ /^[A-Za-z\-]+$/) {
-                               # next;
-                       # }
-                       # if(lc($headname) =~ REQUEST_HEADER_BLOCK) {
-                               # next;
-                       # }
-                       # unless (exists $ENV{'HTTP_USER_AGENT'}) {
-                               # push @curl_arg, '-H';
-                               # push @curl_arg, 'User-Agent:';
-                       # }
-                       # unless (exists $ENV{'HTTP_ACCEPT'}) {
-                               # push @curl_arg, '-H';
-                               # push @curl_arg, 'ACCEPT:';
-                       # }
-                       # $headval=~ s/[\r\n]//g;
-                       # $headarg=$headname.(($headval eq '')?';':': '.$headval);
-                       # push @curl_arg, '-H';
-                       # push @curl_arg, $headarg;
-               # }
-       # }
+       foreach $envk (keys %ENV) { 
+               if ($envk =~ /^(HTTP_[A-Z_]+)$/) {
+                       $headname=formatheader($1);
+                       if ($ENV{$envk} =~ /^([\x20-\x7e]*)$/) {
+                               $headval=$1;
+                       }
+                       if(lc($headname) =~ REQUEST_HEADER_BLOCK) {
+                               next;
+                       }
+                       unless (exists $ENV{'HTTP_USER_AGENT'}) {
+                               push @curl_arg, '-H';
+                               push @curl_arg, 'User-Agent:';
+                       }
+                       unless (exists $ENV{'HTTP_ACCEPT'}) {
+                               push @curl_arg, '-H';
+                               push @curl_arg, 'ACCEPT:';
+                       }
+                       $headval=~ s/[\r\n]//g;
+                       $headarg=$headname.(($headval eq '')?';':': '.$headval);
+                       push @curl_arg, '-H';
+                       push @curl_arg, $headarg;
+               }
+       }
        
        push @curl_arg, $URL;
        
+       pipe ($STDREAD, $STDWRITE) or return fail("Status: 500 Internal Server Error\n","500 Internal Server Error","Failed to create stdout pipe.");
+       pipe ($ERRREAD, $ERRWRITE) or return fail("Status: 500 Internal Server Error\n","500 Internal Server Error","Failed to create stderr pipe.");
+       
+       $curlpid = fork();
+       unless (defined $curlpid) {
+               return fail("Status: 500 Internal Server Error\n","500 Internal Server Error","fork() failed.");
+       }
+       unless ($curlpid) {
+               close ($STDREAD);
+               close ($ERRREAD);
+               
+               open(STDERR, ">&=" . fileno($ERRWRITE)) or die "Failed to open stderr pipe.\n";
+               open(STDOUT, ">&=" . fileno($STDWRITE)) or die "Failed to open stdout pipe.\n";
+               
+               exec @curl_arg;
+               exit 1;
+       }
+       
+       close ($STDWRITE);
+       close ($ERRWRITE);
        
-       ##DO REAL WORK HERE!
        
+       $safelength=1;
+       $definedlength=0;
+       $safeerror=1;
+       $lastskipped=1;
+       $forceexit=0;
        
-       print "Content-type:  text/plain\n\n";
-       print "host: $host\nport: $port\n\n";
-       foreach $yyyb (@curl_arg) {
-               print "$yyyb\n";
+       if ($line = <$STDREAD>) {
+               $line =~ s/\r?\n$//;
+               if ($line =~ /^HTTP\/[0-9]+\.[0-9]+ ([0-9]+ .*)$/) {
+                       @resphead=('Status: '.$1);
+                       while ($line = <$STDREAD>) {
+                               $line =~ s/[\r\n]$//g;
+                               
+                               if($line eq ''){
+                                       last;
+                               }
+                               
+                               if($line =~ /^[ \t](.*)$/){
+                                       if ($lastskipped) {
+                                               next;
+                                       }
+                                       else {
+                                               #$lastline = pop @resphead;
+                                               #push @resphead, $lastline.$1;
+                                               push @resphead, $line;
+                                               }
+                                       }
+                               
+                               if ($line =~ /^([^:]*):(.*)$/) {
+                                       $headname=lc($1);
+                                       $headvalue=$2;
+                               }
+                               else {
+                                       $lastskipped=1;
+                                       next;
+                               }
+                               
+                               if($headname eq 'transfer-encoding') {
+                                       $safelength = 0;
+                               }
+                               if($headname eq 'content-encoding') {
+                                       if($headvalue !~ /^[\r\n \t]*identity[\r\n \t]*$/) {
+                                               $safelength = 0;
+                                       }
+                               }
+                               if($headname eq 'content-length') {
+                                       $definedlength=1;
+                                       $headvalue =~ s/^[\r\n \t]*//;
+                                       $headvalue =~ s/[\r\n \t]*$//;
+                                       $contentlength = int($headvalue);
+                               }
+                               if($headname =~ RESPONSE_HEADER_BLOCK) {
+                                       $lastskipped =1;
+                                       next;
+                               }
+                               $line;
+                               $lastskipped=0;
+                               push @resphead, $line;
+                       }
+                       
+                       if ($lengthdefined and ($lengthsafe or ($contentlength==0))) {
+                               push @resphead, 'Content-length: '.$contentlength;
+                       }
+                       
+                       #! write this to file (h) too ! {
+                       $safeerror=0;
+                       foreach $line (@resphead) {
+                               print $line."\n";
+                       }
+                       print "\n";
+                       #! }
+                       
+                       if ( ! binmode ($STDREAD)) {
+                               print "FAIL 1\n";
+                               $forceexit=1;
+                       }
+                       elsif ( ! binmode (STDOUT) ) {
+                               print "FAIL 2\n";
+                               $forceexit=1;
+                       }
+                       else {
+                               
+                               #! write this to file (c) too ! {
+                               while (read ($STDREAD,$buffer,65536)) {
+                                       unless (print (STDOUT $buffer)) {
+                                               $forceexit=1;
+                                               next;
+                                       }
+                               }
+                               #! }
+                       }
+               }
+               else {
+                       $errormsg="Server respose is not HTTP: $line";
+               }
        }
-       #print "\n".(system @curl_arg)."\n";
        
-       unlink $headpath;
-       unlink $downpath;
-       unlink $uppath;
        
+       # print "Content-type:  text/plain\n\n";
        
-       print "\nDEBUGINFO:\n";
+       # print"\n";
        
-       return debag();
+       waitpid($curlpid,0);
+       if ($? != 0) {
+               if ($safeerror) {
+                       $errormsg='';
+                               while ($line = <$ERRREAD>) {
+                                       $line =~ s/\r?\n/<br>/g;
+                                       $errormsg=$errormsg.$line;
+                       }
+               }
+               else {
+                       $forceexit=1;
+               }
+       }
+       close(STDREAD);
+       close(ERRREAD);
+       
+       if($safeerror){
+               return fail("Status: 500 Internal Server Error\n","500 Internal Server Error",$errormsg);
+       }
+       elsif ($forceexit) {
+               exit 1;
+       }
+       
+       # print "host: $host\nport: $port\n\n";
+       # foreach $yyyb (@curl_arg) {
+               # print "$yyyb\n";
+       # }
+       # #print "\n".(system @curl_arg)."\n";
+       
+       # unlink $headpath;
+       # unlink $downpath;
+       # unlink $uppath;
+       
+       
+       # print "\nDEBUGINFO:\n";
+       
+       # return debag();
        
 }
 
@@ -398,3 +536,74 @@ sub debag {
        }       
        print 'URL: ',$URL,"\n";
 }
+
+sub validateurl {
+       my $url = $_[0];
+       my $prot;
+       my $hostportpathquery;
+       my $hostportpath;
+       $query;
+       my $hostport;
+       $path;
+       my $part;
+       $host;
+       $port;
+       
+       if ($url =~ /^([A-Za-z]+):\/\/(.*)/) {
+               $prot = $1;
+               $hostportpathquery = $2;
+       }
+       else {
+               return 0;
+       }
+       
+       if ($prot !~ /^https?$/) {
+               return 0;
+       }
+       
+       if ($hostportpathquery eq ''){
+               return 0;
+       }
+       
+       if ($hostportpathquery =~ /^([^?]+)\?(.*)$/) {
+               $hostportpath = $1;
+               $query = $2;
+               
+               if ($query !~ /^((%[0-9A-Fa-f][0-9A-Fa-f])|([A-Za-z0-9;\/\?:@&=\+\$\,\-_\.~\*'\(\)]))*$/) {
+                       return 0;
+               }
+       }
+       else {
+               $hostportpath = $hostportpathquery;
+               $query = '';
+       }
+       
+       if($hostportpath =~ /^([^\/]+)(\/.*)$/){
+               $hostport = $1;
+               $path = $2;
+               
+               if ($path !~ /^((%[0-9A-Fa-f][0-9A-Fa-f])|([A-Za-z0-9:;@&=\+\$\,-_\.~\*'\(\)]))*$/) {
+                       return 0;
+               }
+               
+       }
+       else {
+               $hostport = $hostportpath;
+               $path = '';
+       }
+       
+       if ($hostport =~ /^(.*):([0-9]+)$/) {
+               $host = $1;
+               $port = $2;
+       }
+       else {
+               $host=$hostport;
+               $port='';
+       }
+       
+       if ($host !~ /^[A-Za-z0-9\-\.]+$/) {
+               return 0;
+       }
+       
+       return 1;       
+}