#!/usr/bin/perl # LINUX AND WINDOWS # # Führt ein beliebiges Skript im Webspace aus. Dazu werden diese beiden Variablen # mitgegeben: # conncheck: Muss auf POSTCHECK gesetzt sein, so wird die POST-Verbindung gechecked # workdir: Arbeitsverzeichnis # scriptname: Skriptname # scriptargs: Kommandozeilenargumente für das Skript # timeout: Timeout, nach dem beendet werden soll. Geht bislang nur unter Linux # stdin: Daten, die an die Standardeingabe gegeben werden # # Das Resultat wird in einem urlencoded-String gespeichert: # status: 0=Alles OK, # 8=System-Fehlermeldung in stderr, SoftError # 9=System-Fehlermeldung in stderr, HardError # # # retcheck: RESULT muss übergeben werden zur Überprüfung # stdout: Standard-Ausgabe des Skripts # stderr: Standard-Fehlerausgabe des Skripts oder Fehlermeldung des Systems # exitcode: exitcode des Skripts # # Markus Henn, 21.10.03 # $|=1; require '../syncfg/syncfg.lib.pl'; use MIME::Base64; # -------------------------------------------------------------------------------- sub exitHard { my %vars=( 'retcheck' => 'RESULT', 'status' => '9', 'stderr' => $_[0], ); print urlencodeHash(\%vars)."\n"; exit(0); } sub exitSoft { my %vars=( 'retcheck' => 'RESULT', 'status' => '8', 'stderr' => $_[0], ); print urlencodeHash(\%vars)."\n"; exit(0); } # -------------------------------------------------------------------------------- print "Content-type: text/plain\n\n"; # Sich in das Verzeichnis begeben, in dem das Skript liegt (IIS) my $opsystem; if ($0=~/(.*)[\/\\](.+)$/) { chdir($1); $opsystem='windows'; } else { $opsystem='linux'; } # Home-Verzeichnis holen $HOME; if (open(hfile,'<../HOME')) { $HOME=join('',); $HOME=~s/[\r\n]//gs; close(hfile); } else { exitHard('Kann HOME-Datei nicht lesen'); } # CGI-Variablen lesen %cgi; if ($ENV{'REQUEST_METHOD'} eq 'POST') { my $poststream; read(STDIN, $poststream, $ENV{'CONTENT_LENGTH'}); %cgi=urldecodeHash_ascii($poststream); } else { exitHard('Ungültige Methode.'); } $form_daten = $ENV{'QUERY_STRING'}; if ($cgi{'conncheck'} ne 'POSTCHECK') { exitHard('Fehlerhafte Datenübermittlung ('.$cgi{'conncheck'}.').'); } # Ins Arbeitsverzeichnis wechseln if (chdir($HOME.'ftproot/'.$cgi{'workdir'})) { # OK } else { exitHard('Kann nicht auf das Arbeitsverzeichnis "'.$cgi{'workdir'}.'" zugreifen.'); } # Skript suchen my $scriptname=$HOME.'ftproot/'.$cgi{'scriptname'}; my %result; if (-f $scriptname) { # Temporäre Dateien festlegen if ($opsystem eq 'windows') { my $tmpfile_stdout=$ENV{'TEMP'}.'\\exectmps-'.time().rand(999999).'.tmp'; my $tmpfile_stderr=$ENV{'TEMP'}.'\\exectmpr-'.time().rand(999999).'.tmp'; # Befehl bauen $scriptname=~s/\//\\/g; if ($scriptname=~/\"/) { exitHard('Nicht erlaubte Zeichen im Skriptnamen.'); } elsif ($scriptname=~/\.pl$/) { $scriptname='perl "'.$scriptname.'" '; } elsif ($scriptname=~/\.php$/) { $ENV{'PATH_TRANSLATED'}=$scriptname; $scriptname='c:\\programme\\php\\php "'.$scriptname.'" '; } else { $scriptname='"'.$scriptname.'"'; } my $cmd=sprintf($scriptname,$cgi{'scriptargs'}).' > '.$tmpfile_stdout.' 2> '.$tmpfile_stderr; # Skript starten if (open(pp,'|'.$cmd)) { if ($cgi{'stdin'} ne '') { print pp $cgi{'stdin'}; } close(pp); %result=( 'retcheck' => 'RESULT', 'status' => 0, 'exitcode' => int($?/256), ); # Ausgabe lesen if (open(tfile,'<'.$tmpfile_stdout)) { binmode tfile; $result{'stdout'}=join('',); close(tfile); } else { exitHard("Kann temporäre Datei mit STDOUT des Skripts nicht lesen"); } if (open(tfile,'<'.$tmpfile_stderr)) { binmode tfile; $result{'stderr'}=join('',); close(tfile); } else { exitHard("Kann temporäre Datei mit STDERR des Skripts nicht lesen"); } unlink($tmpfile_stdout); unlink($tmpfile_stderr); } else { exitHard('Kann Benutzerskript nicht starten'); } } elsif ($opsystem eq 'linux') { # Ausführung unter Linux my $tmpfile_stdout='/tmp/exectmps-'.time().rand(999999).'.tmp'; my $tmpfile_stderr='/tmp/exectmpr-'.time().rand(999999).'.tmp'; # Befehl bauen $scriptname=~s/\\/\//g; $scriptname=~s/\/\//\//g; $scriptname=~s/\/\.\//\//g; if ($scriptname=~/\"/) { exitHard('Nicht erlaubte Zeichen im Skriptnamen.'); } elsif ($scriptname=~/\.pl$/) { $scriptname='perl "'.$scriptname.'" %s'; } elsif ($scriptname=~/\.php5$/) { $scriptname='( export REDIRECT_STATUS=301; export SCRIPT_FILENAME="'.$scriptname.'" ; /usr/bin/php5 '.$scriptname.' %s ) '; } elsif ($scriptname=~/\.php$/) { if (-f '/usr/bin/php4') { $scriptname='( export REDIRECT_STATUS=301; export SCRIPT_FILENAME="'.$scriptname.'" ; /usr/bin/php4 '.$scriptname.' %s ) '; } else { $scriptname='( export REDIRECT_STATUS=301; export SCRIPT_FILENAME="'.$scriptname.'" ; php ) '; } } else { $scriptname='"'.$scriptname.'"'; } my $cmd=sprintf($scriptname,$cgi{'scriptargs'}).' > '.$tmpfile_stdout.' 2> '.$tmpfile_stderr; # Skript starten eval { local $SIG{ALRM} = sub { die("alarm\n") }; alarm 60; # Nach dieser Zeit wird die Verbindung beendet while () { my $line=$_; $line=~s/[\r\n]//gs; push @resdata,$line; } if (open(pp,'|'.$cmd)) { if ($cgi{'stdin'} ne '') { print pp $cgi{'stdin'}; } close(pp); %result=( 'retcheck' => 'RESULT', 'status' => 0, 'exitcode' => int($?/256), ); # Ausgabe lesen if (open(tfile,'<'.$tmpfile_stdout)) { binmode tfile; $result{'stdout'}=join('',); close(tfile); } else { $result{'stderr'}.="Kann temporäre Datei mit STDOUT des Skripts nicht lesen\n"; } if (open(tfile,'<'.$tmpfile_stderr)) { binmode tfile; $result{'stderr'}=join('',); close(tfile); } else { $result{'stderr'}.="Kann temporäre Datei mit STDERR des Skripts nicht lesen\n"; } unlink($tmpfile_stdout); unlink($tmpfile_stderr); } else { exitHard('Kann Benutzerskript nicht starten'); } }; if ($@) { exitHard('Die Skriptverarbeitung dauerte zu lange.'); } } else { exitHard('Unbekanntes Server-Betriebssystem: '.$opsystem); } } else { exitHard('Kann die Datei "'.$scriptname.'" nicht finden.'); } # zurückgeben print urlencodeHash(\%result); exit(0);