Back to index

php5  5.3.10
server.inc
Go to the documentation of this file.
00001 <?php
00002 
00003 $socket = null;
00004 $errno = 0;
00005 $context = stream_context_create(array('ssl' => array('local_cert' => dirname(__FILE__).'/cert.pem', 'passphrase' => 'pass')));
00006 
00007 for ($i=0; $i<10 && !$socket; ++$i) {
00008        $port = rand(50000, 65535);
00009        
00010        $socket = stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
00011 }
00012 //set anther random port that is not the same as $port
00013 do{
00014        $pasv_port = rand(50000, 65535);
00015 }while($pasv_port == $port);
00016 
00017 if (!$socket) {
00018        die("could not start/bind the ftp server\n");
00019 }
00020 
00021 
00022 
00023 
00024 $pid = pcntl_fork();
00025 
00026 
00027 
00028 function pasv_listen($action){
00029        global $pasv_port, $tmp_file;
00030        $tmp_file = 'nm2.php';
00031        $pid = pcntl_fork();
00032        if($pid === 0){
00033               $soc  = stream_socket_server("tcp://127.0.0.1:$pasv_port");
00034               $fs = stream_socket_accept($soc, 3);
00035               switch ($action) {
00036                      case 'fget':
00037                      case 'get':
00038                      //listen for 3 seconds 3 seconds
00039                      fputs($fs, "I am passive.\r\n");
00040                      break;
00041                      case 'put':
00042                      file_put_contents($tmp_file,  stream_get_contents($fs));
00043                      break;
00044                      case 'list':
00045                      fputs($fs, "drwxr-x---   3 owner  group      4096 Jul 12 12:16 .\r\n");
00046                      fputs($fs, "drwxr-x---   3 owner  group      4096 Jul 12 12:16 ..\r\n");
00047                      fputs($fs, "drwxr-x---   3 owner  group      4096 Jul 12 12:16 public_ftp\r\n");
00048                      break;
00049                      case 'list_null':
00050                      fputs($fs, "\r\n");
00051                      break;
00052               }
00053               fclose($fs);
00054               exit;
00055        }
00056 }
00057 
00058 
00059 
00060 if ($pid) {
00061 
00062        function dump_and_exit($buf)
00063        {
00064               var_dump($buf);
00065               fclose($GLOBALS['s']);
00066               exit;
00067        }
00068 
00069        function anonymous()
00070        {
00071               return $GLOBALS['user'] === 'anonymous';
00072        }
00073 
00074        /* quick&dirty realpath() like function */
00075        function change_dir($dir)
00076        {
00077               global $cwd;
00078 
00079               if ($dir[0] == '/') {
00080                      $cwd = $dir;
00081                      return;
00082               }
00083 
00084               $cwd = "$cwd/$dir";
00085 
00086               do {
00087                      $old = $cwd;
00088                      $cwd = preg_replace('@/?[^/]+/\.\.@', '', $cwd);
00089               } while ($old != $cwd);
00090 
00091               $cwd = strtr($cwd, array('//' => '/'));
00092               if (!$cwd) $cwd = '/';
00093        }
00094 
00095        $s = stream_socket_accept($socket);
00096 
00097        if (!$s) die("Error accepting a new connection\n");
00098 
00099        fputs($s, "220----- PHP FTP server 0.3 -----\r\n220 Service ready\r\n");
00100        $buf = fread($s, 2048);
00101 
00102 
00103        function user_auth($buf) {
00104               global $user, $s, $ssl, $bug37799;
00105 
00106               if (!empty($ssl)) {
00107                      if ($buf !== "AUTH TLS\r\n") {
00108                             fputs($s, "500 Syntax error, command unrecognized.\r\n");
00109                             dump_and_exit($buf);
00110                      }
00111 
00112                      if (empty($bug37799)) {
00113                             fputs($s, "234 auth type accepted\r\n");
00114                      } else {
00115                             fputs($s, "666 dummy\r\n");
00116                             fputs($s, "666 bogus msg\r\n");
00117                             exit;
00118                      }
00119 
00120                      if (!stream_socket_enable_crypto($s, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER)) {
00121                             die("SSLv23 handshake failed.\n");
00122                      }
00123 
00124                      if (!preg_match('/^PBSZ \d+\r\n$/', $buf = fread($s, 2048))) {
00125                             fputs($s, "501 bogus data\r\n");
00126                             dump_and_exit($buf);
00127                      }
00128 
00129                      fputs($s, "200 OK\r\n");
00130                      $buf = fread($s, 2048);
00131 
00132                      if ($buf !== "PROT P\r\n") {
00133                             fputs($s, "504 Wrong protection.\r\n");
00134                             dump_and_exit($buf);
00135                      }
00136 
00137                      fputs($s, "200 OK\r\n");
00138 
00139                      $buf = fread($s, 2048);
00140               }
00141 
00142               if (!preg_match('/^USER (\w+)\r\n$/', $buf, $m)) {
00143                      fputs($s, "500 Syntax error, command unrecognized.\r\n");
00144                      dump_and_exit($buf);
00145               }
00146               $user = $m[1];
00147               if ($user !== 'user' && $user !== 'anonymous') {
00148                      fputs($s, "530 Not logged in.\r\n");
00149                      fclose($s);
00150                      exit;
00151               }
00152 
00153               if (anonymous()) {
00154                      fputs($s, "230 Anonymous user logged in\r\n");
00155 
00156               } else {
00157                      fputs($s, "331 User name ok, need password\r\n");
00158 
00159                      if (!preg_match('/^PASS (\w+)\r\n$/', $buf = fread($s, 100), $m)) {
00160                             fputs($s, "500 Syntax error, command unrecognized.\r\n");
00161                             dump_and_exit($buf);
00162                      }
00163 
00164                      $pass = $m[1];
00165                      if ($pass === 'pass') {
00166                             fputs($s, "230 User logged in\r\n");
00167                      } else {
00168                             fputs($s, "530 Not logged in.\r\n");
00169                             fclose($s);
00170                             exit;
00171                      }
00172               }
00173        }
00174 
00175        user_auth($buf);
00176 
00177        $cwd = '/';
00178        $num_bogus_cmds = 0;
00179 
00180        while($buf = fread($s, 4098)) {
00181               if (!empty($bogus)) {
00182                      fputs($s, "502 Command not implemented (".$num_bogus_cmds++.").\r\n");
00183 
00184               } else if ($buf === "HELP\r\n") {
00185                      fputs($s, "214-There is help available for the following commands:\r\n");
00186                      fputs($s, " USER\r\n");
00187                      fputs($s, " HELP\r\n");
00188                      fputs($s, "214 end of list\r\n");
00189 
00190               } elseif ($buf === "HELP HELP\r\n") {
00191                      fputs($s, "214 Syntax: HELP [<SP> <string>] <CRLF>\r\n");
00192 
00193               } elseif ($buf === "PWD\r\n") {
00194                      fputs($s, "257 \"$cwd\" is current directory.\r\n");
00195 
00196               } elseif ($buf === "CDUP\r\n") {
00197                      change_dir('..');
00198                      fputs($s, "250 CDUP command successful.\r\n");
00199 
00200               } elseif ($buf === "SYST\r\n") {
00201                      if (isset($bug27809)) {
00202                             fputs($s, "215   OS/400 is the remote operating system. The TCP/IP version is \"V5R2M0\"\r\n");
00203                      } else {
00204                             fputs($s, "215 UNIX Type: L8.\r\n");
00205                      }
00206 
00207               } elseif ($buf === "TYPE A\r\n") {
00208                      $ascii = true;
00209                      fputs($s, "200 OK\r\n");
00210 
00211               } elseif ($buf === "TYPE I\r\n") {
00212                      $ascii = false;
00213                      fputs($s, "200 OK\r\n");
00214 
00215               } elseif ($buf === "QUIT\r\n") {
00216                      break;
00217 
00218               } elseif (preg_match("~^PORT (\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\r\n$~", $buf, $m)) {
00219                      $host = "$m[1].$m[2].$m[3].$m[4]";
00220                      $port = ((int)$m[5] << 8) + (int)$m[6];
00221                      fputs($s, "200 OK.\r\n");
00222 
00223               } elseif (preg_match("~^STOR ([\w/.-]+)\r\n$~", $buf, $m)) {
00224                      fputs($s, "150 File status okay; about to open data connection\r\n");
00225 
00226                      if(empty($pasv))
00227                      {
00228                             if (!$fs = stream_socket_client("tcp://$host:$port")) {
00229                                    fputs($s, "425 Can't open data connection\r\n");
00230                                    continue;
00231                             }
00232 
00233                             $data = stream_get_contents($fs);
00234                             $orig = file_get_contents(dirname(__FILE__).'/'.$m[1]);
00235 
00236 
00237                             if (isset($ascii) && !$ascii && $orig === $data) {
00238                                    fputs($s, "226 Closing data Connection.\r\n");
00239 
00240                             } elseif ((!empty($ascii) || isset($bug39583)) && $data === strtr($orig, array("\r\n" => "\n", "\r" => "\n", "\n" => "\r\n"))) {
00241                                    fputs($s, "226 Closing data Connection.\r\n");
00242 
00243                             } else {
00244                                    var_dump($data);
00245                                    var_dump($orig);
00246                                    fputs($s, "552 Requested file action aborted.\r\n");
00247                             }
00248                             fclose($fs);
00249                      }else{
00250                             $data = file_get_contents('nm2.php');
00251                             $orig = file_get_contents(dirname(__FILE__).'/'.$m[1]);
00252                             if ( $orig === $data) {
00253                                    fputs($s, "226 Closing data Connection.\r\n");
00254 
00255                             } else {
00256                                    var_dump($data);
00257                                    var_dump($orig);
00258                                    fputs($s, "552 Requested file action aborted.\r\n");
00259                             }
00260                      }
00261 
00262               } elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
00263                      change_dir($m[1]);
00264                      fputs($s, "250 CWD command successful.\r\n");
00265 
00266               } elseif (preg_match("~^NLST(?: ([A-Za-z./]+))?\r\n$~", $buf, $m)) {
00267 
00268                      if (isset($m[1]) && $m[1] === 'bogusdir') {
00269                             fputs($s, "250 $m[1]: No such file or directory\r\n");
00270                             continue;
00271                      }
00272 
00273                      // there are some servers that don't open the ftp-data socket if there's nothing to send
00274                      if (isset($bug39458) && isset($m[1]) && $m[1] === 'emptydir') {
00275                             fputs($s, "226 Transfer complete.\r\n");
00276                             continue;
00277                      }
00278 
00279                      fputs($s, "150 File status okay; about to open data connection\r\n");
00280 
00281                      if (!$fs = stream_socket_client("tcp://$host:$port")) {
00282                             fputs($s, "425 Can't open data connection\r\n");
00283                             continue;
00284                      }
00285 
00286                      if (empty($m[1]) || $m[1] !== 'emptydir') {
00287                             fputs($fs, "file1\r\nfile1\r\nfile\nb0rk\r\n");
00288                      }
00289 
00290                      fputs($s, "226 Closing data Connection.\r\n");
00291                      fclose($fs);
00292 
00293               } elseif (preg_match("~^MKD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
00294                      if (isset($bug7216)) {
00295                             fputs($s, "257 OK.\r\n");
00296                      } else {
00297                             fputs($s, "257 \"/path/to/ftproot$cwd$m[1]\" created.\r\n");
00298                      }
00299 
00300               } elseif (preg_match('/^USER /', $buf)) {
00301                      user_auth($buf);
00302 
00303               } elseif (preg_match('/^MDTM ([\w\h]+)/', $buf, $matches)) {
00304                      switch ($matches [1]){
00305                             case "A":
00306                             fputs($s, "213 19980615100045.014\r\n");
00307                             break;
00308                             case "B":
00309                             fputs($s, "213 19980615100045.014\r\n");
00310                             break;
00311                             case "C":
00312                             fputs($s, "213 19980705132316\r\n");
00313                             break;
00314                             case "19990929043300 File6":
00315                             fputs($s, "213 19991005213102\r\n");
00316                             break;
00317                             default :
00318                             fputs($s, "550 No file named \"{$matches [1]}\"\r\n");
00319                             break;
00320                      }
00321               }elseif (preg_match('/^RETR ([\w\h]+)/', $buf, $matches)) {
00322                      if(!empty($pasv)){
00323                             ;
00324                      }
00325                      else if (!$fs = stream_socket_client("tcp://$host:$port")) {
00326                             fputs($s, "425 Can't open data connection\r\n");
00327                             continue;
00328                      }
00329 
00330                      switch($matches[1]){
00331 
00332                             case "pasv":
00333                                    fputs($s, "150 File status okay; about to open data connection.\r\n");
00334                                    //the data connection is handled in another forked process
00335                                    // called from outside this while loop
00336                                    fputs($s, "226 Closing data Connection.\r\n");
00337                                    break;
00338                             case "a story":
00339                                    fputs($s, "150 File status okay; about to open data connection.\r\n");
00340                                    fputs($fs, "For sale: baby shoes, never worn.\r\n");
00341                                    fputs($s, "226 Closing data Connection.\r\n");
00342                                    break;
00343                             case "binary data":
00344                                    fputs($s, "150 File status okay; about to open data connection.\r\n");
00345                                    $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
00346                                    fputs($fs, $transfer_type."Foo\0Bar\r\n");
00347                                    fputs($s, "226 Closing data Connection.\r\n");
00348                                    break;
00349                             case "fget":
00350                                    fputs($s, "150 File status okay; about to open data connection.\r\n");
00351                                    $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
00352                                    fputs($fs, $transfer_type."FooBar\r\n");
00353                                    fputs($s, "226 Closing data Connection.\r\n");
00354                                    break;
00355                             case "fgetresume":
00356                                    fputs($s, "150 File status okay; about to open data connection.\r\n");
00357                                    $transfer_type = $ascii? 'ASCII' : 'BINARY' ;
00358                                    fputs($fs, "Bar\r\n");
00359                                    fputs($s, "226 Closing data Connection.\r\n");
00360                                    break;
00361                             default:
00362                                    fputs($s, "550 {$matches[1]}: No such file or directory \r\n");
00363                                    break;
00364                      }
00365                      if(isset($fs))
00366                             fclose($fs);
00367 
00368 
00369               }elseif (preg_match('/^PASV/', $buf, $matches)) {
00370                      $port = $pasv_port;
00371                      $p2 = $port % ((int) 1 << 8);
00372                      $p1 = ($port-$p2)/((int) 1 << 8);
00373                      $host = "127.0.0.1";
00374                      fputs($s, "227 Entering Passive Mode. (127,0,0,1,{$p1},{$p2})\r\n");
00375 
00376 
00377               } elseif (preg_match('/^SITE EXEC/', $buf, $matches)) {
00378                      fputs($s, "200 OK\r\n");
00379 
00380               } elseif (preg_match('/^RMD/', $buf, $matches)) {
00381                      fputs($s, "250 OK\r\n");
00382 
00383               } elseif (preg_match('/^SITE CHMOD/', $buf, $matches)) {
00384                      fputs($s, "200 OK\r\n");
00385 
00386               } elseif (preg_match('/^ALLO (\d+)/', $buf, $matches)) {
00387                      fputs($s, "200 " . $matches[1] . " bytes allocated\r\n");
00388 
00389               }elseif (preg_match('/^LIST www\//', $buf, $matches)) {
00390                      fputs($s, "150 Opening ASCII mode data connection for file list\r\n");
00391                      fputs($s, "226 Transfer complete\r\n");
00392 
00393               }elseif (preg_match('/^LIST no_exists\//', $buf, $matches)) {
00394                      fputs($s, "425 Error establishing connection\r\n");
00395 
00396               }elseif (preg_match('/^REST \d+/', $buf, $matches)) {
00397                      fputs($s, "350 OK\r\n");
00398               }
00399 
00400               else {
00401                      fputs($s, "500 Syntax error, command unrecognized.\r\n");
00402                      dump_and_exit($buf);
00403               }
00404        }
00405        fclose($s);
00406        exit;
00407 }
00408 
00409 fclose($socket);
00410 ?>