1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl 2*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 3*6236dae4SAndroid Build Coastguard Worker# _ _ ____ _ 4*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 5*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 6*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 7*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 8*6236dae4SAndroid Build Coastguard Worker# 9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 10*6236dae4SAndroid Build Coastguard Worker# 11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 14*6236dae4SAndroid Build Coastguard Worker# 15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 18*6236dae4SAndroid Build Coastguard Worker# 19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 21*6236dae4SAndroid Build Coastguard Worker# 22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 23*6236dae4SAndroid Build Coastguard Worker# 24*6236dae4SAndroid Build Coastguard Worker########################################################################### 25*6236dae4SAndroid Build Coastguard Worker 26*6236dae4SAndroid Build Coastguard Worker# This is a server designed for the curl test suite. 27*6236dae4SAndroid Build Coastguard Worker# 28*6236dae4SAndroid Build Coastguard Worker# In December 2009 we started remaking the server to support more protocols 29*6236dae4SAndroid Build Coastguard Worker# that are similar in spirit. Like POP3, IMAP and SMTP in addition to the FTP 30*6236dae4SAndroid Build Coastguard Worker# it already supported since a long time. Note that it still only supports one 31*6236dae4SAndroid Build Coastguard Worker# protocol per invoke. You need to start multiple servers to support multiple 32*6236dae4SAndroid Build Coastguard Worker# protocols simultaneously. 33*6236dae4SAndroid Build Coastguard Worker# 34*6236dae4SAndroid Build Coastguard Worker# It is meant to exercise curl, it is not meant to be a fully working 35*6236dae4SAndroid Build Coastguard Worker# or even very standard compliant server. 36*6236dae4SAndroid Build Coastguard Worker# 37*6236dae4SAndroid Build Coastguard Worker# You may optionally specify port on the command line, otherwise it'll 38*6236dae4SAndroid Build Coastguard Worker# default to port 8921. 39*6236dae4SAndroid Build Coastguard Worker# 40*6236dae4SAndroid Build Coastguard Worker# All socket/network/TCP related stuff is done by the 'sockfilt' program. 41*6236dae4SAndroid Build Coastguard Worker# 42*6236dae4SAndroid Build Coastguard Worker 43*6236dae4SAndroid Build Coastguard Workeruse strict; 44*6236dae4SAndroid Build Coastguard Workeruse warnings; 45*6236dae4SAndroid Build Coastguard Worker 46*6236dae4SAndroid Build Coastguard WorkerBEGIN { 47*6236dae4SAndroid Build Coastguard Worker push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'}); 48*6236dae4SAndroid Build Coastguard Worker push(@INC, "."); 49*6236dae4SAndroid Build Coastguard Worker} 50*6236dae4SAndroid Build Coastguard Worker 51*6236dae4SAndroid Build Coastguard Workeruse IPC::Open2; 52*6236dae4SAndroid Build Coastguard Workeruse Digest::MD5; 53*6236dae4SAndroid Build Coastguard Workeruse File::Basename; 54*6236dae4SAndroid Build Coastguard Worker 55*6236dae4SAndroid Build Coastguard Workeruse directories; 56*6236dae4SAndroid Build Coastguard Worker 57*6236dae4SAndroid Build Coastguard Workeruse getpart qw( 58*6236dae4SAndroid Build Coastguard Worker getpartattr 59*6236dae4SAndroid Build Coastguard Worker getpart 60*6236dae4SAndroid Build Coastguard Worker loadtest 61*6236dae4SAndroid Build Coastguard Worker ); 62*6236dae4SAndroid Build Coastguard Worker 63*6236dae4SAndroid Build Coastguard Workeruse processhelp; 64*6236dae4SAndroid Build Coastguard Worker 65*6236dae4SAndroid Build Coastguard Workeruse serverhelp qw( 66*6236dae4SAndroid Build Coastguard Worker logmsg 67*6236dae4SAndroid Build Coastguard Worker $logfile 68*6236dae4SAndroid Build Coastguard Worker servername_str 69*6236dae4SAndroid Build Coastguard Worker server_pidfilename 70*6236dae4SAndroid Build Coastguard Worker server_logfilename 71*6236dae4SAndroid Build Coastguard Worker mainsockf_pidfilename 72*6236dae4SAndroid Build Coastguard Worker mainsockf_logfilename 73*6236dae4SAndroid Build Coastguard Worker datasockf_pidfilename 74*6236dae4SAndroid Build Coastguard Worker datasockf_logfilename 75*6236dae4SAndroid Build Coastguard Worker ); 76*6236dae4SAndroid Build Coastguard Worker 77*6236dae4SAndroid Build Coastguard Workeruse pathhelp qw( 78*6236dae4SAndroid Build Coastguard Worker exe_ext 79*6236dae4SAndroid Build Coastguard Worker ); 80*6236dae4SAndroid Build Coastguard Worker 81*6236dae4SAndroid Build Coastguard Workeruse globalconfig qw( 82*6236dae4SAndroid Build Coastguard Worker $SERVERCMD 83*6236dae4SAndroid Build Coastguard Worker $LOCKDIR 84*6236dae4SAndroid Build Coastguard Worker ); 85*6236dae4SAndroid Build Coastguard Worker 86*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 87*6236dae4SAndroid Build Coastguard Worker# global vars... 88*6236dae4SAndroid Build Coastguard Worker# 89*6236dae4SAndroid Build Coastguard Workermy $verbose = 0; # set to 1 for debugging 90*6236dae4SAndroid Build Coastguard Workermy $idstr = ""; # server instance string 91*6236dae4SAndroid Build Coastguard Workermy $idnum = 1; # server instance number 92*6236dae4SAndroid Build Coastguard Workermy $ipvnum = 4; # server IPv number (4 or 6) 93*6236dae4SAndroid Build Coastguard Workermy $proto = 'ftp'; # default server protocol 94*6236dae4SAndroid Build Coastguard Workermy $srcdir; # directory where ftpserver.pl is located 95*6236dae4SAndroid Build Coastguard Workermy $srvrname; # server name for presentation purposes 96*6236dae4SAndroid Build Coastguard Workermy $cwd_testno; # test case numbers extracted from CWD command 97*6236dae4SAndroid Build Coastguard Workermy $testno = 0; # test case number (read from server.cmd) 98*6236dae4SAndroid Build Coastguard Workermy $path = '.'; 99*6236dae4SAndroid Build Coastguard Workermy $logdir = $path .'/log'; 100*6236dae4SAndroid Build Coastguard Workermy $piddir; 101*6236dae4SAndroid Build Coastguard Worker 102*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 103*6236dae4SAndroid Build Coastguard Worker# global vars used for server address and primary listener port 104*6236dae4SAndroid Build Coastguard Worker# 105*6236dae4SAndroid Build Coastguard Workermy $port = 8921; # default primary listener port 106*6236dae4SAndroid Build Coastguard Workermy $listenaddr = '127.0.0.1'; # default address for listener port 107*6236dae4SAndroid Build Coastguard Worker 108*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 109*6236dae4SAndroid Build Coastguard Worker# global vars used for file names 110*6236dae4SAndroid Build Coastguard Worker# 111*6236dae4SAndroid Build Coastguard Workermy $PORTFILE="ftpserver.port"; # server port file name 112*6236dae4SAndroid Build Coastguard Workermy $portfile; # server port file path 113*6236dae4SAndroid Build Coastguard Workermy $pidfile; # server pid file name 114*6236dae4SAndroid Build Coastguard Workermy $mainsockf_pidfile; # pid file for primary connection sockfilt process 115*6236dae4SAndroid Build Coastguard Workermy $mainsockf_logfile; # log file for primary connection sockfilt process 116*6236dae4SAndroid Build Coastguard Workermy $datasockf_pidfile; # pid file for secondary connection sockfilt process 117*6236dae4SAndroid Build Coastguard Workermy $datasockf_logfile; # log file for secondary connection sockfilt process 118*6236dae4SAndroid Build Coastguard Worker 119*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 120*6236dae4SAndroid Build Coastguard Worker# global vars used for server logs advisor read lock handling 121*6236dae4SAndroid Build Coastguard Worker# 122*6236dae4SAndroid Build Coastguard Workermy $serverlogs_lockfile; 123*6236dae4SAndroid Build Coastguard Workermy $serverlogslocked = 0; 124*6236dae4SAndroid Build Coastguard Worker 125*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 126*6236dae4SAndroid Build Coastguard Worker# global vars used for child processes PID tracking 127*6236dae4SAndroid Build Coastguard Worker# 128*6236dae4SAndroid Build Coastguard Workermy $sfpid; # PID for primary connection sockfilt process 129*6236dae4SAndroid Build Coastguard Workermy $slavepid; # PID for secondary connection sockfilt process 130*6236dae4SAndroid Build Coastguard Worker 131*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 132*6236dae4SAndroid Build Coastguard Worker# global typeglob filehandle vars to read/write from/to sockfilters 133*6236dae4SAndroid Build Coastguard Worker# 134*6236dae4SAndroid Build Coastguard Workerlocal *SFREAD; # used to read from primary connection 135*6236dae4SAndroid Build Coastguard Workerlocal *SFWRITE; # used to write to primary connection 136*6236dae4SAndroid Build Coastguard Workerlocal *DREAD; # used to read from secondary connection 137*6236dae4SAndroid Build Coastguard Workerlocal *DWRITE; # used to write to secondary connection 138*6236dae4SAndroid Build Coastguard Worker 139*6236dae4SAndroid Build Coastguard Workermy $sockfilt_timeout = 5; # default timeout for sockfilter eXsysreads 140*6236dae4SAndroid Build Coastguard Worker 141*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 142*6236dae4SAndroid Build Coastguard Worker# global vars which depend on server protocol selection 143*6236dae4SAndroid Build Coastguard Worker# 144*6236dae4SAndroid Build Coastguard Workermy %commandfunc; # protocol command specific function callbacks 145*6236dae4SAndroid Build Coastguard Workermy %displaytext; # text returned to client before callback runs 146*6236dae4SAndroid Build Coastguard Worker 147*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 148*6236dae4SAndroid Build Coastguard Worker# global vars customized for each test from the server commands file 149*6236dae4SAndroid Build Coastguard Worker# 150*6236dae4SAndroid Build Coastguard Workermy $ctrldelay; # set if server should throttle ctrl stream 151*6236dae4SAndroid Build Coastguard Workermy $datadelay; # set if server should throttle data stream 152*6236dae4SAndroid Build Coastguard Workermy $retrweirdo; # set if ftp server should use RETRWEIRDO 153*6236dae4SAndroid Build Coastguard Workermy $retrnosize; # set if ftp server should use RETRNOSIZE 154*6236dae4SAndroid Build Coastguard Workermy $retrsize; # set if ftp server should use RETRSIZE 155*6236dae4SAndroid Build Coastguard Workermy $pasvbadip; # set if ftp server should use PASVBADIP 156*6236dae4SAndroid Build Coastguard Workermy $nosave; # set if ftp server should not save uploaded data 157*6236dae4SAndroid Build Coastguard Workermy $nodataconn; # set if ftp srvr doesn't establish or accepts data channel 158*6236dae4SAndroid Build Coastguard Workermy $nodataconn425; # set if ftp srvr doesn't establish data ch and replies 425 159*6236dae4SAndroid Build Coastguard Workermy $nodataconn421; # set if ftp srvr doesn't establish data ch and replies 421 160*6236dae4SAndroid Build Coastguard Workermy $nodataconn150; # set if ftp srvr doesn't establish data ch and replies 150 161*6236dae4SAndroid Build Coastguard Workermy $storeresp; 162*6236dae4SAndroid Build Coastguard Workermy $postfetch; 163*6236dae4SAndroid Build Coastguard Workermy @capabilities; # set if server supports capability commands 164*6236dae4SAndroid Build Coastguard Workermy @auth_mechs; # set if server supports authentication commands 165*6236dae4SAndroid Build Coastguard Workermy %fulltextreply; # 166*6236dae4SAndroid Build Coastguard Workermy %commandreply; # 167*6236dae4SAndroid Build Coastguard Workermy %customcount; # 168*6236dae4SAndroid Build Coastguard Workermy %delayreply; # 169*6236dae4SAndroid Build Coastguard Worker 170*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 171*6236dae4SAndroid Build Coastguard Worker# global variables for to test ftp wildcardmatching or other test that 172*6236dae4SAndroid Build Coastguard Worker# need flexible LIST responses.. and corresponding files. 173*6236dae4SAndroid Build Coastguard Worker# $ftptargetdir is keeping the fake "name" of LIST directory. 174*6236dae4SAndroid Build Coastguard Worker# 175*6236dae4SAndroid Build Coastguard Workermy $ftplistparserstate; 176*6236dae4SAndroid Build Coastguard Workermy $ftptargetdir=""; 177*6236dae4SAndroid Build Coastguard Worker 178*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 179*6236dae4SAndroid Build Coastguard Worker# global variables used when running a ftp server to keep state info 180*6236dae4SAndroid Build Coastguard Worker# relative to the secondary or data sockfilt process. Values of these 181*6236dae4SAndroid Build Coastguard Worker# variables should only be modified using datasockf_state() sub, given 182*6236dae4SAndroid Build Coastguard Worker# that they are closely related and relationship is a bit awkward. 183*6236dae4SAndroid Build Coastguard Worker# 184*6236dae4SAndroid Build Coastguard Workermy $datasockf_state = 'STOPPED'; # see datasockf_state() sub 185*6236dae4SAndroid Build Coastguard Workermy $datasockf_mode = 'none'; # ['none','active','passive'] 186*6236dae4SAndroid Build Coastguard Workermy $datasockf_runs = 'no'; # ['no','yes'] 187*6236dae4SAndroid Build Coastguard Workermy $datasockf_conn = 'no'; # ['no','yes'] 188*6236dae4SAndroid Build Coastguard Worker 189*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 190*6236dae4SAndroid Build Coastguard Worker# global vars used for signal handling 191*6236dae4SAndroid Build Coastguard Worker# 192*6236dae4SAndroid Build Coastguard Workermy $got_exit_signal = 0; # set if program should finish execution ASAP 193*6236dae4SAndroid Build Coastguard Workermy $exit_signal; # first signal handled in exit_signal_handler 194*6236dae4SAndroid Build Coastguard Worker 195*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 196*6236dae4SAndroid Build Coastguard Worker# Mail related definitions 197*6236dae4SAndroid Build Coastguard Worker# 198*6236dae4SAndroid Build Coastguard Workermy $TEXT_PASSWORD = "secret"; 199*6236dae4SAndroid Build Coastguard Workermy $POP3_TIMESTAMP = "<1972.987654321\@curl>"; 200*6236dae4SAndroid Build Coastguard Worker 201*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 202*6236dae4SAndroid Build Coastguard Worker# exit_signal_handler will be triggered to indicate that the program 203*6236dae4SAndroid Build Coastguard Worker# should finish its execution in a controlled way as soon as possible. 204*6236dae4SAndroid Build Coastguard Worker# For now, program will also terminate from within this handler. 205*6236dae4SAndroid Build Coastguard Worker# 206*6236dae4SAndroid Build Coastguard Workersub exit_signal_handler { 207*6236dae4SAndroid Build Coastguard Worker my $signame = shift; 208*6236dae4SAndroid Build Coastguard Worker # For now, simply mimic old behavior. 209*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose); 210*6236dae4SAndroid Build Coastguard Worker unlink($pidfile); 211*6236dae4SAndroid Build Coastguard Worker unlink($portfile); 212*6236dae4SAndroid Build Coastguard Worker if($serverlogslocked) { 213*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 214*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 215*6236dae4SAndroid Build Coastguard Worker } 216*6236dae4SAndroid Build Coastguard Worker exit; 217*6236dae4SAndroid Build Coastguard Worker} 218*6236dae4SAndroid Build Coastguard Worker 219*6236dae4SAndroid Build Coastguard Workersub ftpmsg { 220*6236dae4SAndroid Build Coastguard Worker # append to the server.input file 221*6236dae4SAndroid Build Coastguard Worker open(my $input, ">>", "$logdir/server$idstr.input") || 222*6236dae4SAndroid Build Coastguard Worker logmsg "failed to open $logdir/server$idstr.input\n"; 223*6236dae4SAndroid Build Coastguard Worker 224*6236dae4SAndroid Build Coastguard Worker print $input @_; 225*6236dae4SAndroid Build Coastguard Worker close($input); 226*6236dae4SAndroid Build Coastguard Worker 227*6236dae4SAndroid Build Coastguard Worker # use this, open->print->close system only to make the file 228*6236dae4SAndroid Build Coastguard Worker # open as little as possible, to make the test suite run 229*6236dae4SAndroid Build Coastguard Worker # better on Windows/Cygwin 230*6236dae4SAndroid Build Coastguard Worker} 231*6236dae4SAndroid Build Coastguard Worker 232*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 233*6236dae4SAndroid Build Coastguard Worker# eXsysread is a wrapper around perl's sysread() function. This will 234*6236dae4SAndroid Build Coastguard Worker# repeat the call to sysread() until it has actually read the complete 235*6236dae4SAndroid Build Coastguard Worker# number of requested bytes or an unrecoverable condition occurs. 236*6236dae4SAndroid Build Coastguard Worker# On success returns a positive value, the number of bytes requested. 237*6236dae4SAndroid Build Coastguard Worker# On failure or timeout returns zero. 238*6236dae4SAndroid Build Coastguard Worker# 239*6236dae4SAndroid Build Coastguard Workersub eXsysread { 240*6236dae4SAndroid Build Coastguard Worker my $FH = shift; 241*6236dae4SAndroid Build Coastguard Worker my $scalar = shift; 242*6236dae4SAndroid Build Coastguard Worker my $nbytes = shift; 243*6236dae4SAndroid Build Coastguard Worker my $timeout = shift; # A zero timeout disables eXsysread() time limit 244*6236dae4SAndroid Build Coastguard Worker # 245*6236dae4SAndroid Build Coastguard Worker my $time_limited = 0; 246*6236dae4SAndroid Build Coastguard Worker my $timeout_rest = 0; 247*6236dae4SAndroid Build Coastguard Worker my $start_time = 0; 248*6236dae4SAndroid Build Coastguard Worker my $nread = 0; 249*6236dae4SAndroid Build Coastguard Worker my $rc; 250*6236dae4SAndroid Build Coastguard Worker 251*6236dae4SAndroid Build Coastguard Worker $$scalar = ""; 252*6236dae4SAndroid Build Coastguard Worker 253*6236dae4SAndroid Build Coastguard Worker if((not defined $nbytes) || ($nbytes < 1)) { 254*6236dae4SAndroid Build Coastguard Worker logmsg "Error: eXsysread() failure: " . 255*6236dae4SAndroid Build Coastguard Worker "length argument must be positive\n"; 256*6236dae4SAndroid Build Coastguard Worker return 0; 257*6236dae4SAndroid Build Coastguard Worker } 258*6236dae4SAndroid Build Coastguard Worker if((not defined $timeout) || ($timeout < 0)) { 259*6236dae4SAndroid Build Coastguard Worker logmsg "Error: eXsysread() failure: " . 260*6236dae4SAndroid Build Coastguard Worker "timeout argument must be zero or positive\n"; 261*6236dae4SAndroid Build Coastguard Worker return 0; 262*6236dae4SAndroid Build Coastguard Worker } 263*6236dae4SAndroid Build Coastguard Worker if($timeout > 0) { 264*6236dae4SAndroid Build Coastguard Worker # caller sets eXsysread() time limit 265*6236dae4SAndroid Build Coastguard Worker $time_limited = 1; 266*6236dae4SAndroid Build Coastguard Worker $timeout_rest = $timeout; 267*6236dae4SAndroid Build Coastguard Worker $start_time = int(time()); 268*6236dae4SAndroid Build Coastguard Worker } 269*6236dae4SAndroid Build Coastguard Worker 270*6236dae4SAndroid Build Coastguard Worker while($nread < $nbytes) { 271*6236dae4SAndroid Build Coastguard Worker if($time_limited) { 272*6236dae4SAndroid Build Coastguard Worker eval { 273*6236dae4SAndroid Build Coastguard Worker local $SIG{ALRM} = sub { die "alarm\n"; }; 274*6236dae4SAndroid Build Coastguard Worker alarm $timeout_rest; 275*6236dae4SAndroid Build Coastguard Worker $rc = sysread($FH, $$scalar, $nbytes - $nread, $nread); 276*6236dae4SAndroid Build Coastguard Worker alarm 0; 277*6236dae4SAndroid Build Coastguard Worker }; 278*6236dae4SAndroid Build Coastguard Worker $timeout_rest = $timeout - (int(time()) - $start_time); 279*6236dae4SAndroid Build Coastguard Worker if($timeout_rest < 1) { 280*6236dae4SAndroid Build Coastguard Worker logmsg "Error: eXsysread() failure: timed out\n"; 281*6236dae4SAndroid Build Coastguard Worker return 0; 282*6236dae4SAndroid Build Coastguard Worker } 283*6236dae4SAndroid Build Coastguard Worker } 284*6236dae4SAndroid Build Coastguard Worker else { 285*6236dae4SAndroid Build Coastguard Worker $rc = sysread($FH, $$scalar, $nbytes - $nread, $nread); 286*6236dae4SAndroid Build Coastguard Worker } 287*6236dae4SAndroid Build Coastguard Worker if($got_exit_signal) { 288*6236dae4SAndroid Build Coastguard Worker logmsg "Error: eXsysread() failure: signalled to die\n"; 289*6236dae4SAndroid Build Coastguard Worker return 0; 290*6236dae4SAndroid Build Coastguard Worker } 291*6236dae4SAndroid Build Coastguard Worker if(not defined $rc) { 292*6236dae4SAndroid Build Coastguard Worker if($!{EINTR}) { 293*6236dae4SAndroid Build Coastguard Worker logmsg "Warning: retrying sysread() interrupted system call\n"; 294*6236dae4SAndroid Build Coastguard Worker next; 295*6236dae4SAndroid Build Coastguard Worker } 296*6236dae4SAndroid Build Coastguard Worker if($!{EAGAIN}) { 297*6236dae4SAndroid Build Coastguard Worker logmsg "Warning: retrying sysread() due to EAGAIN\n"; 298*6236dae4SAndroid Build Coastguard Worker next; 299*6236dae4SAndroid Build Coastguard Worker } 300*6236dae4SAndroid Build Coastguard Worker if($!{EWOULDBLOCK}) { 301*6236dae4SAndroid Build Coastguard Worker logmsg "Warning: retrying sysread() due to EWOULDBLOCK\n"; 302*6236dae4SAndroid Build Coastguard Worker next; 303*6236dae4SAndroid Build Coastguard Worker } 304*6236dae4SAndroid Build Coastguard Worker logmsg "Error: sysread() failure: $!\n"; 305*6236dae4SAndroid Build Coastguard Worker return 0; 306*6236dae4SAndroid Build Coastguard Worker } 307*6236dae4SAndroid Build Coastguard Worker if($rc < 0) { 308*6236dae4SAndroid Build Coastguard Worker logmsg "Error: sysread() failure: returned negative value $rc\n"; 309*6236dae4SAndroid Build Coastguard Worker return 0; 310*6236dae4SAndroid Build Coastguard Worker } 311*6236dae4SAndroid Build Coastguard Worker if($rc == 0) { 312*6236dae4SAndroid Build Coastguard Worker logmsg "Error: sysread() failure: read zero bytes\n"; 313*6236dae4SAndroid Build Coastguard Worker return 0; 314*6236dae4SAndroid Build Coastguard Worker } 315*6236dae4SAndroid Build Coastguard Worker $nread += $rc; 316*6236dae4SAndroid Build Coastguard Worker } 317*6236dae4SAndroid Build Coastguard Worker return $nread; 318*6236dae4SAndroid Build Coastguard Worker} 319*6236dae4SAndroid Build Coastguard Worker 320*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 321*6236dae4SAndroid Build Coastguard Worker# read_mainsockf attempts to read the given amount of output from the 322*6236dae4SAndroid Build Coastguard Worker# sockfilter which is in use for the main or primary connection. This 323*6236dae4SAndroid Build Coastguard Worker# reads untranslated sockfilt lingo which may hold data read from the 324*6236dae4SAndroid Build Coastguard Worker# main or primary socket. On success returns 1, otherwise zero. 325*6236dae4SAndroid Build Coastguard Worker# 326*6236dae4SAndroid Build Coastguard Workersub read_mainsockf { 327*6236dae4SAndroid Build Coastguard Worker my $scalar = shift; 328*6236dae4SAndroid Build Coastguard Worker my $nbytes = shift; 329*6236dae4SAndroid Build Coastguard Worker my $timeout = shift; # Optional argument, if zero blocks indefinitely 330*6236dae4SAndroid Build Coastguard Worker my $FH = \*SFREAD; 331*6236dae4SAndroid Build Coastguard Worker 332*6236dae4SAndroid Build Coastguard Worker if(not defined $timeout) { 333*6236dae4SAndroid Build Coastguard Worker $timeout = $sockfilt_timeout + ($nbytes >> 12); 334*6236dae4SAndroid Build Coastguard Worker } 335*6236dae4SAndroid Build Coastguard Worker if(eXsysread($FH, $scalar, $nbytes, $timeout) != $nbytes) { 336*6236dae4SAndroid Build Coastguard Worker my ($fcaller, $lcaller) = (caller)[1,2]; 337*6236dae4SAndroid Build Coastguard Worker logmsg "Error: read_mainsockf() failure at $fcaller " . 338*6236dae4SAndroid Build Coastguard Worker "line $lcaller. Due to eXsysread() failure\n"; 339*6236dae4SAndroid Build Coastguard Worker return 0; 340*6236dae4SAndroid Build Coastguard Worker } 341*6236dae4SAndroid Build Coastguard Worker return 1; 342*6236dae4SAndroid Build Coastguard Worker} 343*6236dae4SAndroid Build Coastguard Worker 344*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 345*6236dae4SAndroid Build Coastguard Worker# read_datasockf attempts to read the given amount of output from the 346*6236dae4SAndroid Build Coastguard Worker# sockfilter which is in use for the data or secondary connection. This 347*6236dae4SAndroid Build Coastguard Worker# reads untranslated sockfilt lingo which may hold data read from the 348*6236dae4SAndroid Build Coastguard Worker# data or secondary socket. On success returns 1, otherwise zero. 349*6236dae4SAndroid Build Coastguard Worker# 350*6236dae4SAndroid Build Coastguard Workersub read_datasockf { 351*6236dae4SAndroid Build Coastguard Worker my $scalar = shift; 352*6236dae4SAndroid Build Coastguard Worker my $nbytes = shift; 353*6236dae4SAndroid Build Coastguard Worker my $timeout = shift; # Optional argument, if zero blocks indefinitely 354*6236dae4SAndroid Build Coastguard Worker my $FH = \*DREAD; 355*6236dae4SAndroid Build Coastguard Worker 356*6236dae4SAndroid Build Coastguard Worker if(not defined $timeout) { 357*6236dae4SAndroid Build Coastguard Worker $timeout = $sockfilt_timeout + ($nbytes >> 12); 358*6236dae4SAndroid Build Coastguard Worker } 359*6236dae4SAndroid Build Coastguard Worker if(eXsysread($FH, $scalar, $nbytes, $timeout) != $nbytes) { 360*6236dae4SAndroid Build Coastguard Worker my ($fcaller, $lcaller) = (caller)[1,2]; 361*6236dae4SAndroid Build Coastguard Worker logmsg "Error: read_datasockf() failure at $fcaller " . 362*6236dae4SAndroid Build Coastguard Worker "line $lcaller. Due to eXsysread() failure\n"; 363*6236dae4SAndroid Build Coastguard Worker return 0; 364*6236dae4SAndroid Build Coastguard Worker } 365*6236dae4SAndroid Build Coastguard Worker return 1; 366*6236dae4SAndroid Build Coastguard Worker} 367*6236dae4SAndroid Build Coastguard Worker 368*6236dae4SAndroid Build Coastguard Workersub sysread_or_die { 369*6236dae4SAndroid Build Coastguard Worker my $FH = shift; 370*6236dae4SAndroid Build Coastguard Worker my $scalar = shift; 371*6236dae4SAndroid Build Coastguard Worker my $length = shift; 372*6236dae4SAndroid Build Coastguard Worker my $fcaller; 373*6236dae4SAndroid Build Coastguard Worker my $lcaller; 374*6236dae4SAndroid Build Coastguard Worker my $result; 375*6236dae4SAndroid Build Coastguard Worker 376*6236dae4SAndroid Build Coastguard Worker $result = sysread($$FH, $$scalar, $length); 377*6236dae4SAndroid Build Coastguard Worker 378*6236dae4SAndroid Build Coastguard Worker if(not defined $result) { 379*6236dae4SAndroid Build Coastguard Worker ($fcaller, $lcaller) = (caller)[1,2]; 380*6236dae4SAndroid Build Coastguard Worker logmsg "Failed to read input\n"; 381*6236dae4SAndroid Build Coastguard Worker logmsg "Error: $srvrname server, sysread error: $!\n"; 382*6236dae4SAndroid Build Coastguard Worker logmsg "Exited from sysread_or_die() at $fcaller " . 383*6236dae4SAndroid Build Coastguard Worker "line $lcaller. $srvrname server, sysread error: $!\n"; 384*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose); 385*6236dae4SAndroid Build Coastguard Worker unlink($pidfile); 386*6236dae4SAndroid Build Coastguard Worker unlink($portfile); 387*6236dae4SAndroid Build Coastguard Worker if($serverlogslocked) { 388*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 389*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 390*6236dae4SAndroid Build Coastguard Worker } 391*6236dae4SAndroid Build Coastguard Worker exit; 392*6236dae4SAndroid Build Coastguard Worker } 393*6236dae4SAndroid Build Coastguard Worker elsif($result == 0) { 394*6236dae4SAndroid Build Coastguard Worker ($fcaller, $lcaller) = (caller)[1,2]; 395*6236dae4SAndroid Build Coastguard Worker logmsg "Failed to read input\n"; 396*6236dae4SAndroid Build Coastguard Worker logmsg "Error: $srvrname server, read zero\n"; 397*6236dae4SAndroid Build Coastguard Worker logmsg "Exited from sysread_or_die() at $fcaller " . 398*6236dae4SAndroid Build Coastguard Worker "line $lcaller. $srvrname server, read zero\n"; 399*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose); 400*6236dae4SAndroid Build Coastguard Worker unlink($pidfile); 401*6236dae4SAndroid Build Coastguard Worker unlink($portfile); 402*6236dae4SAndroid Build Coastguard Worker if($serverlogslocked) { 403*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 404*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 405*6236dae4SAndroid Build Coastguard Worker } 406*6236dae4SAndroid Build Coastguard Worker exit; 407*6236dae4SAndroid Build Coastguard Worker } 408*6236dae4SAndroid Build Coastguard Worker 409*6236dae4SAndroid Build Coastguard Worker return $result; 410*6236dae4SAndroid Build Coastguard Worker} 411*6236dae4SAndroid Build Coastguard Worker 412*6236dae4SAndroid Build Coastguard Workersub startsf { 413*6236dae4SAndroid Build Coastguard Worker my @mainsockfcmd = ("./server/sockfilt".exe_ext('SRV'), 414*6236dae4SAndroid Build Coastguard Worker "--ipv$ipvnum", 415*6236dae4SAndroid Build Coastguard Worker "--port", $port, 416*6236dae4SAndroid Build Coastguard Worker "--pidfile", $mainsockf_pidfile, 417*6236dae4SAndroid Build Coastguard Worker "--portfile", $portfile, 418*6236dae4SAndroid Build Coastguard Worker "--logfile", $mainsockf_logfile); 419*6236dae4SAndroid Build Coastguard Worker $sfpid = open2(*SFREAD, *SFWRITE, @mainsockfcmd); 420*6236dae4SAndroid Build Coastguard Worker 421*6236dae4SAndroid Build Coastguard Worker print STDERR "@mainsockfcmd\n" if($verbose); 422*6236dae4SAndroid Build Coastguard Worker 423*6236dae4SAndroid Build Coastguard Worker print SFWRITE "PING\n"; 424*6236dae4SAndroid Build Coastguard Worker my $pong; 425*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*SFREAD, \$pong, 5); 426*6236dae4SAndroid Build Coastguard Worker 427*6236dae4SAndroid Build Coastguard Worker if($pong !~ /^PONG/) { 428*6236dae4SAndroid Build Coastguard Worker logmsg "Failed sockfilt command: @mainsockfcmd\n"; 429*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose); 430*6236dae4SAndroid Build Coastguard Worker unlink($pidfile); 431*6236dae4SAndroid Build Coastguard Worker unlink($portfile); 432*6236dae4SAndroid Build Coastguard Worker if($serverlogslocked) { 433*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 434*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 435*6236dae4SAndroid Build Coastguard Worker } 436*6236dae4SAndroid Build Coastguard Worker die "Failed to start sockfilt!"; 437*6236dae4SAndroid Build Coastguard Worker } 438*6236dae4SAndroid Build Coastguard Worker} 439*6236dae4SAndroid Build Coastguard Worker 440*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 441*6236dae4SAndroid Build Coastguard Worker# Returns the given test's reply data 442*6236dae4SAndroid Build Coastguard Worker# 443*6236dae4SAndroid Build Coastguard Workersub getreplydata { 444*6236dae4SAndroid Build Coastguard Worker my ($num) = @_; 445*6236dae4SAndroid Build Coastguard Worker my $testpart = ""; 446*6236dae4SAndroid Build Coastguard Worker 447*6236dae4SAndroid Build Coastguard Worker $num =~ s/^([^0-9]*)//; 448*6236dae4SAndroid Build Coastguard Worker if($num > 10000) { 449*6236dae4SAndroid Build Coastguard Worker $testpart = $num % 10000; 450*6236dae4SAndroid Build Coastguard Worker } 451*6236dae4SAndroid Build Coastguard Worker 452*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "data$testpart"); 453*6236dae4SAndroid Build Coastguard Worker if((!@data) && ($testpart ne "")) { 454*6236dae4SAndroid Build Coastguard Worker @data = getpart("reply", "data"); 455*6236dae4SAndroid Build Coastguard Worker } 456*6236dae4SAndroid Build Coastguard Worker 457*6236dae4SAndroid Build Coastguard Worker return @data; 458*6236dae4SAndroid Build Coastguard Worker} 459*6236dae4SAndroid Build Coastguard Worker 460*6236dae4SAndroid Build Coastguard Workersub sockfilt { 461*6236dae4SAndroid Build Coastguard Worker my $l; 462*6236dae4SAndroid Build Coastguard Worker foreach $l (@_) { 463*6236dae4SAndroid Build Coastguard Worker printf SFWRITE "DATA\n%04x\n", length($l); 464*6236dae4SAndroid Build Coastguard Worker print SFWRITE $l; 465*6236dae4SAndroid Build Coastguard Worker } 466*6236dae4SAndroid Build Coastguard Worker} 467*6236dae4SAndroid Build Coastguard Worker 468*6236dae4SAndroid Build Coastguard Workersub sockfiltsecondary { 469*6236dae4SAndroid Build Coastguard Worker my $l; 470*6236dae4SAndroid Build Coastguard Worker foreach $l (@_) { 471*6236dae4SAndroid Build Coastguard Worker printf DWRITE "DATA\n%04x\n", length($l); 472*6236dae4SAndroid Build Coastguard Worker print DWRITE $l; 473*6236dae4SAndroid Build Coastguard Worker } 474*6236dae4SAndroid Build Coastguard Worker} 475*6236dae4SAndroid Build Coastguard Worker 476*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 477*6236dae4SAndroid Build Coastguard Worker# Send data to the client on the control stream, which happens to be plain 478*6236dae4SAndroid Build Coastguard Worker# stdout. 479*6236dae4SAndroid Build Coastguard Worker# 480*6236dae4SAndroid Build Coastguard Workersub sendcontrol { 481*6236dae4SAndroid Build Coastguard Worker if(!$ctrldelay) { 482*6236dae4SAndroid Build Coastguard Worker # spit it all out at once 483*6236dae4SAndroid Build Coastguard Worker sockfilt @_; 484*6236dae4SAndroid Build Coastguard Worker } 485*6236dae4SAndroid Build Coastguard Worker else { 486*6236dae4SAndroid Build Coastguard Worker my $a = join("", @_); 487*6236dae4SAndroid Build Coastguard Worker my @a = split("", $a); 488*6236dae4SAndroid Build Coastguard Worker 489*6236dae4SAndroid Build Coastguard Worker for(@a) { 490*6236dae4SAndroid Build Coastguard Worker sockfilt $_; 491*6236dae4SAndroid Build Coastguard Worker portable_sleep($ctrldelay); 492*6236dae4SAndroid Build Coastguard Worker } 493*6236dae4SAndroid Build Coastguard Worker } 494*6236dae4SAndroid Build Coastguard Worker my $log; 495*6236dae4SAndroid Build Coastguard Worker foreach $log (@_) { 496*6236dae4SAndroid Build Coastguard Worker my $l = $log; 497*6236dae4SAndroid Build Coastguard Worker $l =~ s/\r/[CR]/g; 498*6236dae4SAndroid Build Coastguard Worker $l =~ s/\n/[LF]/g; 499*6236dae4SAndroid Build Coastguard Worker logmsg "> \"$l\"\n"; 500*6236dae4SAndroid Build Coastguard Worker } 501*6236dae4SAndroid Build Coastguard Worker} 502*6236dae4SAndroid Build Coastguard Worker 503*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 504*6236dae4SAndroid Build Coastguard Worker# Send data to the FTP client on the data stream when data connection 505*6236dae4SAndroid Build Coastguard Worker# is actually established. Given that this sub should only be called 506*6236dae4SAndroid Build Coastguard Worker# when a data connection is supposed to be established, calling this 507*6236dae4SAndroid Build Coastguard Worker# without a data connection is an indication of weak logic somewhere. 508*6236dae4SAndroid Build Coastguard Worker# 509*6236dae4SAndroid Build Coastguard Workersub senddata { 510*6236dae4SAndroid Build Coastguard Worker my $l; 511*6236dae4SAndroid Build Coastguard Worker if($datasockf_conn eq 'no') { 512*6236dae4SAndroid Build Coastguard Worker logmsg "WARNING: Detected data sending attempt without DATA channel\n"; 513*6236dae4SAndroid Build Coastguard Worker foreach $l (@_) { 514*6236dae4SAndroid Build Coastguard Worker logmsg "WARNING: Data swallowed: $l\n" 515*6236dae4SAndroid Build Coastguard Worker } 516*6236dae4SAndroid Build Coastguard Worker return; 517*6236dae4SAndroid Build Coastguard Worker } 518*6236dae4SAndroid Build Coastguard Worker 519*6236dae4SAndroid Build Coastguard Worker foreach $l (@_) { 520*6236dae4SAndroid Build Coastguard Worker if(!$datadelay) { 521*6236dae4SAndroid Build Coastguard Worker # spit it all out at once 522*6236dae4SAndroid Build Coastguard Worker sockfiltsecondary $l; 523*6236dae4SAndroid Build Coastguard Worker } 524*6236dae4SAndroid Build Coastguard Worker else { 525*6236dae4SAndroid Build Coastguard Worker # pause between each byte 526*6236dae4SAndroid Build Coastguard Worker for (split(//,$l)) { 527*6236dae4SAndroid Build Coastguard Worker sockfiltsecondary $_; 528*6236dae4SAndroid Build Coastguard Worker portable_sleep($datadelay); 529*6236dae4SAndroid Build Coastguard Worker } 530*6236dae4SAndroid Build Coastguard Worker } 531*6236dae4SAndroid Build Coastguard Worker } 532*6236dae4SAndroid Build Coastguard Worker} 533*6236dae4SAndroid Build Coastguard Worker 534*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 535*6236dae4SAndroid Build Coastguard Worker# protocolsetup initializes the 'displaytext' and 'commandfunc' hashes 536*6236dae4SAndroid Build Coastguard Worker# for the given protocol. References to protocol command callbacks are 537*6236dae4SAndroid Build Coastguard Worker# stored in 'commandfunc' hash, and text which will be returned to the 538*6236dae4SAndroid Build Coastguard Worker# client before the command callback runs is stored in 'displaytext'. 539*6236dae4SAndroid Build Coastguard Worker# 540*6236dae4SAndroid Build Coastguard Workersub protocolsetup { 541*6236dae4SAndroid Build Coastguard Worker my $proto = $_[0]; 542*6236dae4SAndroid Build Coastguard Worker 543*6236dae4SAndroid Build Coastguard Worker if($proto eq 'ftp') { 544*6236dae4SAndroid Build Coastguard Worker %commandfunc = ( 545*6236dae4SAndroid Build Coastguard Worker 'PORT' => \&PORT_ftp, 546*6236dae4SAndroid Build Coastguard Worker 'EPRT' => \&PORT_ftp, 547*6236dae4SAndroid Build Coastguard Worker 'LIST' => \&LIST_ftp, 548*6236dae4SAndroid Build Coastguard Worker 'NLST' => \&NLST_ftp, 549*6236dae4SAndroid Build Coastguard Worker 'PASV' => \&PASV_ftp, 550*6236dae4SAndroid Build Coastguard Worker 'CWD' => \&CWD_ftp, 551*6236dae4SAndroid Build Coastguard Worker 'PWD' => \&PWD_ftp, 552*6236dae4SAndroid Build Coastguard Worker 'EPSV' => \&PASV_ftp, 553*6236dae4SAndroid Build Coastguard Worker 'RETR' => \&RETR_ftp, 554*6236dae4SAndroid Build Coastguard Worker 'SIZE' => \&SIZE_ftp, 555*6236dae4SAndroid Build Coastguard Worker 'REST' => \&REST_ftp, 556*6236dae4SAndroid Build Coastguard Worker 'STOR' => \&STOR_ftp, 557*6236dae4SAndroid Build Coastguard Worker 'APPE' => \&STOR_ftp, # append looks like upload 558*6236dae4SAndroid Build Coastguard Worker 'MDTM' => \&MDTM_ftp, 559*6236dae4SAndroid Build Coastguard Worker ); 560*6236dae4SAndroid Build Coastguard Worker %displaytext = ( 561*6236dae4SAndroid Build Coastguard Worker 'USER' => '331 We are happy you popped in!', 562*6236dae4SAndroid Build Coastguard Worker 'PASS' => '230 Welcome you silly person', 563*6236dae4SAndroid Build Coastguard Worker 'PORT' => '200 You said PORT - I say FINE', 564*6236dae4SAndroid Build Coastguard Worker 'TYPE' => '200 I modify TYPE as you wanted', 565*6236dae4SAndroid Build Coastguard Worker 'LIST' => '150 here comes a directory', 566*6236dae4SAndroid Build Coastguard Worker 'NLST' => '150 here comes a directory', 567*6236dae4SAndroid Build Coastguard Worker 'CWD' => '250 CWD command successful.', 568*6236dae4SAndroid Build Coastguard Worker 'SYST' => '215 UNIX Type: L8', # just fake something 569*6236dae4SAndroid Build Coastguard Worker 'QUIT' => '221 bye bye baby', # just reply something 570*6236dae4SAndroid Build Coastguard Worker 'MKD' => '257 Created your requested directory', 571*6236dae4SAndroid Build Coastguard Worker 'REST' => '350 Yeah yeah we set it there for you', 572*6236dae4SAndroid Build Coastguard Worker 'DELE' => '200 OK OK OK whatever you say', 573*6236dae4SAndroid Build Coastguard Worker 'RNFR' => '350 Received your order. Please provide more', 574*6236dae4SAndroid Build Coastguard Worker 'RNTO' => '250 Ok, thanks. File renaming completed.', 575*6236dae4SAndroid Build Coastguard Worker 'NOOP' => '200 Yes, I\'m very good at doing nothing.', 576*6236dae4SAndroid Build Coastguard Worker 'PBSZ' => '500 PBSZ not implemented', 577*6236dae4SAndroid Build Coastguard Worker 'PROT' => '500 PROT not implemented', 578*6236dae4SAndroid Build Coastguard Worker 'welcome' => join("", 579*6236dae4SAndroid Build Coastguard Worker '220- _ _ ____ _ '."\r\n", 580*6236dae4SAndroid Build Coastguard Worker '220- ___| | | | _ \| | '."\r\n", 581*6236dae4SAndroid Build Coastguard Worker '220- / __| | | | |_) | | '."\r\n", 582*6236dae4SAndroid Build Coastguard Worker '220- | (__| |_| | _ {| |___ '."\r\n", 583*6236dae4SAndroid Build Coastguard Worker '220 \___|\___/|_| \_\_____|'."\r\n") 584*6236dae4SAndroid Build Coastguard Worker ); 585*6236dae4SAndroid Build Coastguard Worker } 586*6236dae4SAndroid Build Coastguard Worker elsif($proto eq 'pop3') { 587*6236dae4SAndroid Build Coastguard Worker %commandfunc = ( 588*6236dae4SAndroid Build Coastguard Worker 'APOP' => \&APOP_pop3, 589*6236dae4SAndroid Build Coastguard Worker 'AUTH' => \&AUTH_pop3, 590*6236dae4SAndroid Build Coastguard Worker 'CAPA' => \&CAPA_pop3, 591*6236dae4SAndroid Build Coastguard Worker 'DELE' => \&DELE_pop3, 592*6236dae4SAndroid Build Coastguard Worker 'LIST' => \&LIST_pop3, 593*6236dae4SAndroid Build Coastguard Worker 'NOOP' => \&NOOP_pop3, 594*6236dae4SAndroid Build Coastguard Worker 'PASS' => \&PASS_pop3, 595*6236dae4SAndroid Build Coastguard Worker 'QUIT' => \&QUIT_pop3, 596*6236dae4SAndroid Build Coastguard Worker 'RETR' => \&RETR_pop3, 597*6236dae4SAndroid Build Coastguard Worker 'RSET' => \&RSET_pop3, 598*6236dae4SAndroid Build Coastguard Worker 'STAT' => \&STAT_pop3, 599*6236dae4SAndroid Build Coastguard Worker 'TOP' => \&TOP_pop3, 600*6236dae4SAndroid Build Coastguard Worker 'UIDL' => \&UIDL_pop3, 601*6236dae4SAndroid Build Coastguard Worker 'USER' => \&USER_pop3, 602*6236dae4SAndroid Build Coastguard Worker ); 603*6236dae4SAndroid Build Coastguard Worker %displaytext = ( 604*6236dae4SAndroid Build Coastguard Worker 'welcome' => join("", 605*6236dae4SAndroid Build Coastguard Worker ' _ _ ____ _ '."\r\n", 606*6236dae4SAndroid Build Coastguard Worker ' ___| | | | _ \| | '."\r\n", 607*6236dae4SAndroid Build Coastguard Worker ' / __| | | | |_) | | '."\r\n", 608*6236dae4SAndroid Build Coastguard Worker ' | (__| |_| | _ {| |___ '."\r\n", 609*6236dae4SAndroid Build Coastguard Worker ' \___|\___/|_| \_\_____|'."\r\n", 610*6236dae4SAndroid Build Coastguard Worker '+OK curl POP3 server ready to serve '."\r\n") 611*6236dae4SAndroid Build Coastguard Worker ); 612*6236dae4SAndroid Build Coastguard Worker } 613*6236dae4SAndroid Build Coastguard Worker elsif($proto eq 'imap') { 614*6236dae4SAndroid Build Coastguard Worker %commandfunc = ( 615*6236dae4SAndroid Build Coastguard Worker 'APPEND' => \&APPEND_imap, 616*6236dae4SAndroid Build Coastguard Worker 'CAPABILITY' => \&CAPABILITY_imap, 617*6236dae4SAndroid Build Coastguard Worker 'CHECK' => \&CHECK_imap, 618*6236dae4SAndroid Build Coastguard Worker 'CLOSE' => \&CLOSE_imap, 619*6236dae4SAndroid Build Coastguard Worker 'COPY' => \©_imap, 620*6236dae4SAndroid Build Coastguard Worker 'CREATE' => \&CREATE_imap, 621*6236dae4SAndroid Build Coastguard Worker 'DELETE' => \&DELETE_imap, 622*6236dae4SAndroid Build Coastguard Worker 'EXAMINE' => \&EXAMINE_imap, 623*6236dae4SAndroid Build Coastguard Worker 'EXPUNGE' => \&EXPUNGE_imap, 624*6236dae4SAndroid Build Coastguard Worker 'FETCH' => \&FETCH_imap, 625*6236dae4SAndroid Build Coastguard Worker 'LIST' => \&LIST_imap, 626*6236dae4SAndroid Build Coastguard Worker 'LSUB' => \&LSUB_imap, 627*6236dae4SAndroid Build Coastguard Worker 'LOGIN' => \&LOGIN_imap, 628*6236dae4SAndroid Build Coastguard Worker 'LOGOUT' => \&LOGOUT_imap, 629*6236dae4SAndroid Build Coastguard Worker 'NOOP' => \&NOOP_imap, 630*6236dae4SAndroid Build Coastguard Worker 'RENAME' => \&RENAME_imap, 631*6236dae4SAndroid Build Coastguard Worker 'SEARCH' => \&SEARCH_imap, 632*6236dae4SAndroid Build Coastguard Worker 'SELECT' => \&SELECT_imap, 633*6236dae4SAndroid Build Coastguard Worker 'STATUS' => \&STATUS_imap, 634*6236dae4SAndroid Build Coastguard Worker 'STORE' => \&STORE_imap, 635*6236dae4SAndroid Build Coastguard Worker 'UID' => \&UID_imap, 636*6236dae4SAndroid Build Coastguard Worker 'IDLE' => \&IDLE_imap, 637*6236dae4SAndroid Build Coastguard Worker ); 638*6236dae4SAndroid Build Coastguard Worker %displaytext = ( 639*6236dae4SAndroid Build Coastguard Worker 'welcome' => join("", 640*6236dae4SAndroid Build Coastguard Worker ' _ _ ____ _ '."\r\n", 641*6236dae4SAndroid Build Coastguard Worker ' ___| | | | _ \| | '."\r\n", 642*6236dae4SAndroid Build Coastguard Worker ' / __| | | | |_) | | '."\r\n", 643*6236dae4SAndroid Build Coastguard Worker ' | (__| |_| | _ {| |___ '."\r\n", 644*6236dae4SAndroid Build Coastguard Worker ' \___|\___/|_| \_\_____|'."\r\n", 645*6236dae4SAndroid Build Coastguard Worker '* OK curl IMAP server ready to serve'."\r\n") 646*6236dae4SAndroid Build Coastguard Worker ); 647*6236dae4SAndroid Build Coastguard Worker } 648*6236dae4SAndroid Build Coastguard Worker elsif($proto eq 'smtp') { 649*6236dae4SAndroid Build Coastguard Worker %commandfunc = ( 650*6236dae4SAndroid Build Coastguard Worker 'DATA' => \&DATA_smtp, 651*6236dae4SAndroid Build Coastguard Worker 'EHLO' => \&EHLO_smtp, 652*6236dae4SAndroid Build Coastguard Worker 'EXPN' => \&EXPN_smtp, 653*6236dae4SAndroid Build Coastguard Worker 'HELO' => \&HELO_smtp, 654*6236dae4SAndroid Build Coastguard Worker 'HELP' => \&HELP_smtp, 655*6236dae4SAndroid Build Coastguard Worker 'MAIL' => \&MAIL_smtp, 656*6236dae4SAndroid Build Coastguard Worker 'NOOP' => \&NOOP_smtp, 657*6236dae4SAndroid Build Coastguard Worker 'RSET' => \&RSET_smtp, 658*6236dae4SAndroid Build Coastguard Worker 'RCPT' => \&RCPT_smtp, 659*6236dae4SAndroid Build Coastguard Worker 'VRFY' => \&VRFY_smtp, 660*6236dae4SAndroid Build Coastguard Worker 'QUIT' => \&QUIT_smtp, 661*6236dae4SAndroid Build Coastguard Worker ); 662*6236dae4SAndroid Build Coastguard Worker %displaytext = ( 663*6236dae4SAndroid Build Coastguard Worker 'welcome' => join("", 664*6236dae4SAndroid Build Coastguard Worker '220- _ _ ____ _ '."\r\n", 665*6236dae4SAndroid Build Coastguard Worker '220- ___| | | | _ \| | '."\r\n", 666*6236dae4SAndroid Build Coastguard Worker '220- / __| | | | |_) | | '."\r\n", 667*6236dae4SAndroid Build Coastguard Worker '220- | (__| |_| | _ {| |___ '."\r\n", 668*6236dae4SAndroid Build Coastguard Worker '220 \___|\___/|_| \_\_____|'."\r\n") 669*6236dae4SAndroid Build Coastguard Worker ); 670*6236dae4SAndroid Build Coastguard Worker } 671*6236dae4SAndroid Build Coastguard Worker} 672*6236dae4SAndroid Build Coastguard Worker 673*6236dae4SAndroid Build Coastguard Worker# Perform the disconnect handshake with sockfilt on the secondary connection 674*6236dae4SAndroid Build Coastguard Worker# (the only connection we actively disconnect). 675*6236dae4SAndroid Build Coastguard Worker# This involves waiting for the disconnect acknowledgment after the DISC 676*6236dae4SAndroid Build Coastguard Worker# command, while throwing away anything else that might come in before 677*6236dae4SAndroid Build Coastguard Worker# that. 678*6236dae4SAndroid Build Coastguard Workersub disc_handshake { 679*6236dae4SAndroid Build Coastguard Worker print DWRITE "DISC\n"; 680*6236dae4SAndroid Build Coastguard Worker my $line; 681*6236dae4SAndroid Build Coastguard Worker my $nr; 682*6236dae4SAndroid Build Coastguard Worker while (5 == ($nr = sysread DREAD, $line, 5)) { 683*6236dae4SAndroid Build Coastguard Worker if($line eq "DATA\n") { 684*6236dae4SAndroid Build Coastguard Worker # Must read the data bytes to stay in sync 685*6236dae4SAndroid Build Coastguard Worker my $i; 686*6236dae4SAndroid Build Coastguard Worker sysread DREAD, $i, 5; 687*6236dae4SAndroid Build Coastguard Worker 688*6236dae4SAndroid Build Coastguard Worker my $size = 0; 689*6236dae4SAndroid Build Coastguard Worker if($i =~ /^([0-9a-fA-F]{4})\n/) { 690*6236dae4SAndroid Build Coastguard Worker $size = hex($1); 691*6236dae4SAndroid Build Coastguard Worker } 692*6236dae4SAndroid Build Coastguard Worker 693*6236dae4SAndroid Build Coastguard Worker logmsg "> Throwing away $size bytes on closed connection\n"; 694*6236dae4SAndroid Build Coastguard Worker read_datasockf(\$line, $size); 695*6236dae4SAndroid Build Coastguard Worker } 696*6236dae4SAndroid Build Coastguard Worker elsif($line eq "DISC\n") { 697*6236dae4SAndroid Build Coastguard Worker logmsg "Fancy that; client wants to DISC, too\n"; 698*6236dae4SAndroid Build Coastguard Worker printf DWRITE "ACKD\n"; 699*6236dae4SAndroid Build Coastguard Worker } 700*6236dae4SAndroid Build Coastguard Worker elsif($line eq "ACKD\n") { 701*6236dae4SAndroid Build Coastguard Worker # Got the ack we were waiting for 702*6236dae4SAndroid Build Coastguard Worker last; 703*6236dae4SAndroid Build Coastguard Worker } 704*6236dae4SAndroid Build Coastguard Worker else { 705*6236dae4SAndroid Build Coastguard Worker logmsg "Ignoring: $line"; 706*6236dae4SAndroid Build Coastguard Worker # sockfilt should not be sending us any other commands 707*6236dae4SAndroid Build Coastguard Worker } 708*6236dae4SAndroid Build Coastguard Worker } 709*6236dae4SAndroid Build Coastguard Worker if(!defined($nr)) { 710*6236dae4SAndroid Build Coastguard Worker logmsg "Error: pipe read error ($!) while waiting for ACKD"; 711*6236dae4SAndroid Build Coastguard Worker } 712*6236dae4SAndroid Build Coastguard Worker elsif($nr <= 0) { 713*6236dae4SAndroid Build Coastguard Worker logmsg "Error: pipe EOF while waiting for ACKD"; 714*6236dae4SAndroid Build Coastguard Worker } 715*6236dae4SAndroid Build Coastguard Worker} 716*6236dae4SAndroid Build Coastguard Worker 717*6236dae4SAndroid Build Coastguard Workersub close_dataconn { 718*6236dae4SAndroid Build Coastguard Worker my ($closed)=@_; # non-zero if already disconnected 719*6236dae4SAndroid Build Coastguard Worker 720*6236dae4SAndroid Build Coastguard Worker my $datapid = processexists($datasockf_pidfile); 721*6236dae4SAndroid Build Coastguard Worker 722*6236dae4SAndroid Build Coastguard Worker logmsg "=====> Closing $datasockf_mode DATA connection...\n"; 723*6236dae4SAndroid Build Coastguard Worker 724*6236dae4SAndroid Build Coastguard Worker if(!$closed) { 725*6236dae4SAndroid Build Coastguard Worker if($datapid > 0) { 726*6236dae4SAndroid Build Coastguard Worker logmsg "Server disconnects $datasockf_mode DATA connection\n"; 727*6236dae4SAndroid Build Coastguard Worker disc_handshake(); 728*6236dae4SAndroid Build Coastguard Worker logmsg "Server disconnected $datasockf_mode DATA connection\n"; 729*6236dae4SAndroid Build Coastguard Worker } 730*6236dae4SAndroid Build Coastguard Worker else { 731*6236dae4SAndroid Build Coastguard Worker logmsg "Server finds $datasockf_mode DATA connection already ". 732*6236dae4SAndroid Build Coastguard Worker "disconnected\n"; 733*6236dae4SAndroid Build Coastguard Worker } 734*6236dae4SAndroid Build Coastguard Worker } 735*6236dae4SAndroid Build Coastguard Worker else { 736*6236dae4SAndroid Build Coastguard Worker logmsg "Server knows $datasockf_mode DATA connection is already ". 737*6236dae4SAndroid Build Coastguard Worker "disconnected\n"; 738*6236dae4SAndroid Build Coastguard Worker } 739*6236dae4SAndroid Build Coastguard Worker 740*6236dae4SAndroid Build Coastguard Worker if($datapid > 0) { 741*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel quits ". 742*6236dae4SAndroid Build Coastguard Worker "(pid $datapid)\n"; 743*6236dae4SAndroid Build Coastguard Worker print DWRITE "QUIT\n"; 744*6236dae4SAndroid Build Coastguard Worker pidwait($datapid, 0); 745*6236dae4SAndroid Build Coastguard Worker unlink($datasockf_pidfile) if(-f $datasockf_pidfile); 746*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel quit ". 747*6236dae4SAndroid Build Coastguard Worker "(pid $datapid)\n"; 748*6236dae4SAndroid Build Coastguard Worker } 749*6236dae4SAndroid Build Coastguard Worker else { 750*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel already ". 751*6236dae4SAndroid Build Coastguard Worker "dead\n"; 752*6236dae4SAndroid Build Coastguard Worker } 753*6236dae4SAndroid Build Coastguard Worker 754*6236dae4SAndroid Build Coastguard Worker logmsg "=====> Closed $datasockf_mode DATA connection\n"; 755*6236dae4SAndroid Build Coastguard Worker 756*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 757*6236dae4SAndroid Build Coastguard Worker} 758*6236dae4SAndroid Build Coastguard Worker 759*6236dae4SAndroid Build Coastguard Worker################ 760*6236dae4SAndroid Build Coastguard Worker################ SMTP commands 761*6236dae4SAndroid Build Coastguard Worker################ 762*6236dae4SAndroid Build Coastguard Worker 763*6236dae4SAndroid Build Coastguard Worker# The type of server (SMTP or ESMTP) 764*6236dae4SAndroid Build Coastguard Workermy $smtp_type; 765*6236dae4SAndroid Build Coastguard Worker 766*6236dae4SAndroid Build Coastguard Worker# The client (which normally contains the test number) 767*6236dae4SAndroid Build Coastguard Workermy $smtp_client; 768*6236dae4SAndroid Build Coastguard Worker 769*6236dae4SAndroid Build Coastguard Workersub EHLO_smtp { 770*6236dae4SAndroid Build Coastguard Worker my ($client) = @_; 771*6236dae4SAndroid Build Coastguard Worker my @data; 772*6236dae4SAndroid Build Coastguard Worker 773*6236dae4SAndroid Build Coastguard Worker # TODO: Get the IP address of the client connection to use in the 774*6236dae4SAndroid Build Coastguard Worker # EHLO response when the client doesn't specify one but for now use 775*6236dae4SAndroid Build Coastguard Worker # 127.0.0.1 776*6236dae4SAndroid Build Coastguard Worker if(!$client) { 777*6236dae4SAndroid Build Coastguard Worker $client = "[127.0.0.1]"; 778*6236dae4SAndroid Build Coastguard Worker } 779*6236dae4SAndroid Build Coastguard Worker 780*6236dae4SAndroid Build Coastguard Worker # Set the server type to ESMTP 781*6236dae4SAndroid Build Coastguard Worker $smtp_type = "ESMTP"; 782*6236dae4SAndroid Build Coastguard Worker 783*6236dae4SAndroid Build Coastguard Worker # Calculate the EHLO response 784*6236dae4SAndroid Build Coastguard Worker push @data, "$smtp_type pingpong test server Hello $client"; 785*6236dae4SAndroid Build Coastguard Worker 786*6236dae4SAndroid Build Coastguard Worker if((@capabilities) || (@auth_mechs)) { 787*6236dae4SAndroid Build Coastguard Worker my $mechs; 788*6236dae4SAndroid Build Coastguard Worker 789*6236dae4SAndroid Build Coastguard Worker for my $c (@capabilities) { 790*6236dae4SAndroid Build Coastguard Worker push @data, $c; 791*6236dae4SAndroid Build Coastguard Worker } 792*6236dae4SAndroid Build Coastguard Worker 793*6236dae4SAndroid Build Coastguard Worker for my $am (@auth_mechs) { 794*6236dae4SAndroid Build Coastguard Worker if(!$mechs) { 795*6236dae4SAndroid Build Coastguard Worker $mechs = "$am"; 796*6236dae4SAndroid Build Coastguard Worker } 797*6236dae4SAndroid Build Coastguard Worker else { 798*6236dae4SAndroid Build Coastguard Worker $mechs .= " $am"; 799*6236dae4SAndroid Build Coastguard Worker } 800*6236dae4SAndroid Build Coastguard Worker } 801*6236dae4SAndroid Build Coastguard Worker 802*6236dae4SAndroid Build Coastguard Worker if($mechs) { 803*6236dae4SAndroid Build Coastguard Worker push @data, "AUTH $mechs"; 804*6236dae4SAndroid Build Coastguard Worker } 805*6236dae4SAndroid Build Coastguard Worker } 806*6236dae4SAndroid Build Coastguard Worker 807*6236dae4SAndroid Build Coastguard Worker # Send the EHLO response 808*6236dae4SAndroid Build Coastguard Worker for(my $i = 0; $i < @data; $i++) { 809*6236dae4SAndroid Build Coastguard Worker my $d = $data[$i]; 810*6236dae4SAndroid Build Coastguard Worker 811*6236dae4SAndroid Build Coastguard Worker if($i < @data - 1) { 812*6236dae4SAndroid Build Coastguard Worker sendcontrol "250-$d\r\n"; 813*6236dae4SAndroid Build Coastguard Worker } 814*6236dae4SAndroid Build Coastguard Worker else { 815*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 $d\r\n"; 816*6236dae4SAndroid Build Coastguard Worker } 817*6236dae4SAndroid Build Coastguard Worker } 818*6236dae4SAndroid Build Coastguard Worker 819*6236dae4SAndroid Build Coastguard Worker # Store the client (as it may contain the test number) 820*6236dae4SAndroid Build Coastguard Worker $smtp_client = $client; 821*6236dae4SAndroid Build Coastguard Worker 822*6236dae4SAndroid Build Coastguard Worker return 0; 823*6236dae4SAndroid Build Coastguard Worker} 824*6236dae4SAndroid Build Coastguard Worker 825*6236dae4SAndroid Build Coastguard Workersub HELO_smtp { 826*6236dae4SAndroid Build Coastguard Worker my ($client) = @_; 827*6236dae4SAndroid Build Coastguard Worker 828*6236dae4SAndroid Build Coastguard Worker # TODO: Get the IP address of the client connection to use in the HELO 829*6236dae4SAndroid Build Coastguard Worker # response when the client doesn't specify one but for now use 127.0.0.1 830*6236dae4SAndroid Build Coastguard Worker if(!$client) { 831*6236dae4SAndroid Build Coastguard Worker $client = "[127.0.0.1]"; 832*6236dae4SAndroid Build Coastguard Worker } 833*6236dae4SAndroid Build Coastguard Worker 834*6236dae4SAndroid Build Coastguard Worker # Set the server type to SMTP 835*6236dae4SAndroid Build Coastguard Worker $smtp_type = "SMTP"; 836*6236dae4SAndroid Build Coastguard Worker 837*6236dae4SAndroid Build Coastguard Worker # Send the HELO response 838*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 $smtp_type pingpong test server Hello $client\r\n"; 839*6236dae4SAndroid Build Coastguard Worker 840*6236dae4SAndroid Build Coastguard Worker # Store the client (as it may contain the test number) 841*6236dae4SAndroid Build Coastguard Worker $smtp_client = $client; 842*6236dae4SAndroid Build Coastguard Worker 843*6236dae4SAndroid Build Coastguard Worker return 0; 844*6236dae4SAndroid Build Coastguard Worker} 845*6236dae4SAndroid Build Coastguard Worker 846*6236dae4SAndroid Build Coastguard Workersub MAIL_smtp { 847*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 848*6236dae4SAndroid Build Coastguard Worker 849*6236dae4SAndroid Build Coastguard Worker logmsg "MAIL_smtp got $args\n"; 850*6236dae4SAndroid Build Coastguard Worker 851*6236dae4SAndroid Build Coastguard Worker if (!$args) { 852*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 853*6236dae4SAndroid Build Coastguard Worker } 854*6236dae4SAndroid Build Coastguard Worker else { 855*6236dae4SAndroid Build Coastguard Worker my $from; 856*6236dae4SAndroid Build Coastguard Worker my $size; 857*6236dae4SAndroid Build Coastguard Worker my $smtputf8 = grep /^SMTPUTF8$/, @capabilities; 858*6236dae4SAndroid Build Coastguard Worker my @elements = split(/ /, $args); 859*6236dae4SAndroid Build Coastguard Worker 860*6236dae4SAndroid Build Coastguard Worker # Get the FROM and SIZE parameters 861*6236dae4SAndroid Build Coastguard Worker for my $e (@elements) { 862*6236dae4SAndroid Build Coastguard Worker if($e =~ /^FROM:(.*)$/) { 863*6236dae4SAndroid Build Coastguard Worker $from = $1; 864*6236dae4SAndroid Build Coastguard Worker } 865*6236dae4SAndroid Build Coastguard Worker elsif($e =~ /^SIZE=(\d+)$/) { 866*6236dae4SAndroid Build Coastguard Worker $size = $1; 867*6236dae4SAndroid Build Coastguard Worker } 868*6236dae4SAndroid Build Coastguard Worker } 869*6236dae4SAndroid Build Coastguard Worker 870*6236dae4SAndroid Build Coastguard Worker # this server doesn't "validate" MAIL FROM addresses 871*6236dae4SAndroid Build Coastguard Worker if (length($from)) { 872*6236dae4SAndroid Build Coastguard Worker my @found; 873*6236dae4SAndroid Build Coastguard Worker my $valid = 1; 874*6236dae4SAndroid Build Coastguard Worker 875*6236dae4SAndroid Build Coastguard Worker # Check the capabilities for SIZE and if the specified size is 876*6236dae4SAndroid Build Coastguard Worker # greater than the message size then reject it 877*6236dae4SAndroid Build Coastguard Worker if (@found = grep /^SIZE (\d+)$/, @capabilities) { 878*6236dae4SAndroid Build Coastguard Worker if ($found[0] =~ /^SIZE (\d+)$/) { 879*6236dae4SAndroid Build Coastguard Worker if ($size > $1) { 880*6236dae4SAndroid Build Coastguard Worker $valid = 0; 881*6236dae4SAndroid Build Coastguard Worker } 882*6236dae4SAndroid Build Coastguard Worker } 883*6236dae4SAndroid Build Coastguard Worker } 884*6236dae4SAndroid Build Coastguard Worker 885*6236dae4SAndroid Build Coastguard Worker if(!$valid) { 886*6236dae4SAndroid Build Coastguard Worker sendcontrol "552 Message size too large\r\n"; 887*6236dae4SAndroid Build Coastguard Worker } 888*6236dae4SAndroid Build Coastguard Worker else { 889*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 Sender OK\r\n"; 890*6236dae4SAndroid Build Coastguard Worker } 891*6236dae4SAndroid Build Coastguard Worker } 892*6236dae4SAndroid Build Coastguard Worker else { 893*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Invalid address\r\n"; 894*6236dae4SAndroid Build Coastguard Worker } 895*6236dae4SAndroid Build Coastguard Worker } 896*6236dae4SAndroid Build Coastguard Worker 897*6236dae4SAndroid Build Coastguard Worker return 0; 898*6236dae4SAndroid Build Coastguard Worker} 899*6236dae4SAndroid Build Coastguard Worker 900*6236dae4SAndroid Build Coastguard Workersub RCPT_smtp { 901*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 902*6236dae4SAndroid Build Coastguard Worker 903*6236dae4SAndroid Build Coastguard Worker logmsg "RCPT_smtp got $args\n"; 904*6236dae4SAndroid Build Coastguard Worker 905*6236dae4SAndroid Build Coastguard Worker # Get the TO parameter 906*6236dae4SAndroid Build Coastguard Worker if($args !~ /^TO:(.*)/) { 907*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 908*6236dae4SAndroid Build Coastguard Worker } 909*6236dae4SAndroid Build Coastguard Worker else { 910*6236dae4SAndroid Build Coastguard Worker my $smtputf8 = grep /^SMTPUTF8$/, @capabilities; 911*6236dae4SAndroid Build Coastguard Worker my $to = $1; 912*6236dae4SAndroid Build Coastguard Worker 913*6236dae4SAndroid Build Coastguard Worker # Validate the to address (only a valid email address inside <> is 914*6236dae4SAndroid Build Coastguard Worker # allowed, such as <[email protected]>) 915*6236dae4SAndroid Build Coastguard Worker if ((!$smtputf8 && $to =~ 916*6236dae4SAndroid Build Coastguard Worker /^<([a-zA-Z0-9._%+-]+)\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4})>$/) || 917*6236dae4SAndroid Build Coastguard Worker ($smtputf8 && $to =~ 918*6236dae4SAndroid Build Coastguard Worker /^<([a-zA-Z0-9\x{80}-\x{ff}._%+-]+)\@(([a-zA-Z0-9\x{80}-\x{ff}-]+)\.)+([a-zA-Z]{2,4})>$/)) { 919*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 Recipient OK\r\n"; 920*6236dae4SAndroid Build Coastguard Worker } 921*6236dae4SAndroid Build Coastguard Worker else { 922*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Invalid address\r\n"; 923*6236dae4SAndroid Build Coastguard Worker } 924*6236dae4SAndroid Build Coastguard Worker } 925*6236dae4SAndroid Build Coastguard Worker 926*6236dae4SAndroid Build Coastguard Worker return 0; 927*6236dae4SAndroid Build Coastguard Worker} 928*6236dae4SAndroid Build Coastguard Worker 929*6236dae4SAndroid Build Coastguard Workersub DATA_smtp { 930*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 931*6236dae4SAndroid Build Coastguard Worker 932*6236dae4SAndroid Build Coastguard Worker if ($args) { 933*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 934*6236dae4SAndroid Build Coastguard Worker } 935*6236dae4SAndroid Build Coastguard Worker elsif ($smtp_client !~ /^(\d*)$/) { 936*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Invalid arguments\r\n"; 937*6236dae4SAndroid Build Coastguard Worker } 938*6236dae4SAndroid Build Coastguard Worker else { 939*6236dae4SAndroid Build Coastguard Worker sendcontrol "354 Show me the mail\r\n"; 940*6236dae4SAndroid Build Coastguard Worker 941*6236dae4SAndroid Build Coastguard Worker my $testno = $smtp_client; 942*6236dae4SAndroid Build Coastguard Worker my $filename = "$logdir/upload.$testno"; 943*6236dae4SAndroid Build Coastguard Worker 944*6236dae4SAndroid Build Coastguard Worker logmsg "Store test number $testno in $filename\n"; 945*6236dae4SAndroid Build Coastguard Worker 946*6236dae4SAndroid Build Coastguard Worker open(my $file, ">", "$filename") || 947*6236dae4SAndroid Build Coastguard Worker return 0; # failed to open output 948*6236dae4SAndroid Build Coastguard Worker 949*6236dae4SAndroid Build Coastguard Worker my $line; 950*6236dae4SAndroid Build Coastguard Worker my $ulsize=0; 951*6236dae4SAndroid Build Coastguard Worker my $disc=0; 952*6236dae4SAndroid Build Coastguard Worker my $raw; 953*6236dae4SAndroid Build Coastguard Worker while (5 == (sysread \*SFREAD, $line, 5)) { 954*6236dae4SAndroid Build Coastguard Worker if($line eq "DATA\n") { 955*6236dae4SAndroid Build Coastguard Worker my $i; 956*6236dae4SAndroid Build Coastguard Worker my $eob; 957*6236dae4SAndroid Build Coastguard Worker sysread \*SFREAD, $i, 5; 958*6236dae4SAndroid Build Coastguard Worker 959*6236dae4SAndroid Build Coastguard Worker my $size = 0; 960*6236dae4SAndroid Build Coastguard Worker if($i =~ /^([0-9a-fA-F]{4})\n/) { 961*6236dae4SAndroid Build Coastguard Worker $size = hex($1); 962*6236dae4SAndroid Build Coastguard Worker } 963*6236dae4SAndroid Build Coastguard Worker 964*6236dae4SAndroid Build Coastguard Worker read_mainsockf(\$line, $size); 965*6236dae4SAndroid Build Coastguard Worker 966*6236dae4SAndroid Build Coastguard Worker $ulsize += $size; 967*6236dae4SAndroid Build Coastguard Worker print $file $line if(!$nosave); 968*6236dae4SAndroid Build Coastguard Worker 969*6236dae4SAndroid Build Coastguard Worker $raw .= $line; 970*6236dae4SAndroid Build Coastguard Worker if($raw =~ /(?:^|\x0d\x0a)\x2e\x0d\x0a/) { 971*6236dae4SAndroid Build Coastguard Worker # end of data marker! 972*6236dae4SAndroid Build Coastguard Worker $eob = 1; 973*6236dae4SAndroid Build Coastguard Worker } 974*6236dae4SAndroid Build Coastguard Worker 975*6236dae4SAndroid Build Coastguard Worker logmsg "> Appending $size bytes to file\n"; 976*6236dae4SAndroid Build Coastguard Worker 977*6236dae4SAndroid Build Coastguard Worker if($eob) { 978*6236dae4SAndroid Build Coastguard Worker logmsg "Found SMTP EOB marker\n"; 979*6236dae4SAndroid Build Coastguard Worker last; 980*6236dae4SAndroid Build Coastguard Worker } 981*6236dae4SAndroid Build Coastguard Worker } 982*6236dae4SAndroid Build Coastguard Worker elsif($line eq "DISC\n") { 983*6236dae4SAndroid Build Coastguard Worker # disconnect! 984*6236dae4SAndroid Build Coastguard Worker $disc=1; 985*6236dae4SAndroid Build Coastguard Worker printf SFWRITE "ACKD\n"; 986*6236dae4SAndroid Build Coastguard Worker last; 987*6236dae4SAndroid Build Coastguard Worker } 988*6236dae4SAndroid Build Coastguard Worker else { 989*6236dae4SAndroid Build Coastguard Worker logmsg "No support for: $line"; 990*6236dae4SAndroid Build Coastguard Worker last; 991*6236dae4SAndroid Build Coastguard Worker } 992*6236dae4SAndroid Build Coastguard Worker } 993*6236dae4SAndroid Build Coastguard Worker 994*6236dae4SAndroid Build Coastguard Worker if($nosave) { 995*6236dae4SAndroid Build Coastguard Worker print $file "$ulsize bytes would've been stored here\n"; 996*6236dae4SAndroid Build Coastguard Worker } 997*6236dae4SAndroid Build Coastguard Worker 998*6236dae4SAndroid Build Coastguard Worker close($file); 999*6236dae4SAndroid Build Coastguard Worker 1000*6236dae4SAndroid Build Coastguard Worker logmsg "received $ulsize bytes upload\n"; 1001*6236dae4SAndroid Build Coastguard Worker 1002*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 OK, data received!\r\n"; 1003*6236dae4SAndroid Build Coastguard Worker } 1004*6236dae4SAndroid Build Coastguard Worker 1005*6236dae4SAndroid Build Coastguard Worker return 0; 1006*6236dae4SAndroid Build Coastguard Worker} 1007*6236dae4SAndroid Build Coastguard Worker 1008*6236dae4SAndroid Build Coastguard Workersub NOOP_smtp { 1009*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1010*6236dae4SAndroid Build Coastguard Worker 1011*6236dae4SAndroid Build Coastguard Worker if($args) { 1012*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 1013*6236dae4SAndroid Build Coastguard Worker } 1014*6236dae4SAndroid Build Coastguard Worker else { 1015*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 OK\r\n"; 1016*6236dae4SAndroid Build Coastguard Worker } 1017*6236dae4SAndroid Build Coastguard Worker 1018*6236dae4SAndroid Build Coastguard Worker return 0; 1019*6236dae4SAndroid Build Coastguard Worker} 1020*6236dae4SAndroid Build Coastguard Worker 1021*6236dae4SAndroid Build Coastguard Workersub RSET_smtp { 1022*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1023*6236dae4SAndroid Build Coastguard Worker 1024*6236dae4SAndroid Build Coastguard Worker if($args) { 1025*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 1026*6236dae4SAndroid Build Coastguard Worker } 1027*6236dae4SAndroid Build Coastguard Worker else { 1028*6236dae4SAndroid Build Coastguard Worker sendcontrol "250 Resetting\r\n"; 1029*6236dae4SAndroid Build Coastguard Worker } 1030*6236dae4SAndroid Build Coastguard Worker 1031*6236dae4SAndroid Build Coastguard Worker return 0; 1032*6236dae4SAndroid Build Coastguard Worker} 1033*6236dae4SAndroid Build Coastguard Worker 1034*6236dae4SAndroid Build Coastguard Workersub HELP_smtp { 1035*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1036*6236dae4SAndroid Build Coastguard Worker 1037*6236dae4SAndroid Build Coastguard Worker # One argument is optional 1038*6236dae4SAndroid Build Coastguard Worker if($args) { 1039*6236dae4SAndroid Build Coastguard Worker logmsg "HELP_smtp got $args\n"; 1040*6236dae4SAndroid Build Coastguard Worker } 1041*6236dae4SAndroid Build Coastguard Worker 1042*6236dae4SAndroid Build Coastguard Worker if($smtp_client eq "verifiedserver") { 1043*6236dae4SAndroid Build Coastguard Worker # This is the secret command that verifies that this actually is 1044*6236dae4SAndroid Build Coastguard Worker # the curl test server 1045*6236dae4SAndroid Build Coastguard Worker sendcontrol "214 WE ROOLZ: $$\r\n"; 1046*6236dae4SAndroid Build Coastguard Worker 1047*6236dae4SAndroid Build Coastguard Worker if($verbose) { 1048*6236dae4SAndroid Build Coastguard Worker print STDERR "FTPD: We returned proof we are the test server\n"; 1049*6236dae4SAndroid Build Coastguard Worker } 1050*6236dae4SAndroid Build Coastguard Worker 1051*6236dae4SAndroid Build Coastguard Worker logmsg "return proof we are we\n"; 1052*6236dae4SAndroid Build Coastguard Worker } 1053*6236dae4SAndroid Build Coastguard Worker else { 1054*6236dae4SAndroid Build Coastguard Worker sendcontrol "214-This server supports the following commands:\r\n"; 1055*6236dae4SAndroid Build Coastguard Worker 1056*6236dae4SAndroid Build Coastguard Worker if(@auth_mechs) { 1057*6236dae4SAndroid Build Coastguard Worker sendcontrol "214 HELO EHLO RCPT DATA RSET MAIL VRFY EXPN QUIT HELP AUTH\r\n"; 1058*6236dae4SAndroid Build Coastguard Worker } 1059*6236dae4SAndroid Build Coastguard Worker else { 1060*6236dae4SAndroid Build Coastguard Worker sendcontrol "214 HELO EHLO RCPT DATA RSET MAIL VRFY EXPN QUIT HELP\r\n"; 1061*6236dae4SAndroid Build Coastguard Worker } 1062*6236dae4SAndroid Build Coastguard Worker } 1063*6236dae4SAndroid Build Coastguard Worker 1064*6236dae4SAndroid Build Coastguard Worker return 0; 1065*6236dae4SAndroid Build Coastguard Worker} 1066*6236dae4SAndroid Build Coastguard Worker 1067*6236dae4SAndroid Build Coastguard Workersub VRFY_smtp { 1068*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1069*6236dae4SAndroid Build Coastguard Worker my ($username, $address) = split(/ /, $args, 2); 1070*6236dae4SAndroid Build Coastguard Worker 1071*6236dae4SAndroid Build Coastguard Worker logmsg "VRFY_smtp got $args\n"; 1072*6236dae4SAndroid Build Coastguard Worker 1073*6236dae4SAndroid Build Coastguard Worker if($username eq "") { 1074*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 1075*6236dae4SAndroid Build Coastguard Worker } 1076*6236dae4SAndroid Build Coastguard Worker else { 1077*6236dae4SAndroid Build Coastguard Worker my $smtputf8 = grep /^SMTPUTF8$/, @capabilities; 1078*6236dae4SAndroid Build Coastguard Worker 1079*6236dae4SAndroid Build Coastguard Worker # Validate the username (only a valid local or external username is 1080*6236dae4SAndroid Build Coastguard Worker # allowed, such as user or [email protected]) 1081*6236dae4SAndroid Build Coastguard Worker if ((!$smtputf8 && $username =~ 1082*6236dae4SAndroid Build Coastguard Worker /^([a-zA-Z0-9._%+-]+)(\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4}))?$/) || 1083*6236dae4SAndroid Build Coastguard Worker ($smtputf8 && $username =~ 1084*6236dae4SAndroid Build Coastguard Worker /^([a-zA-Z0-9\x{80}-\x{ff}._%+-]+)(\@(([a-zA-Z0-9\x{80}-\x{ff}-]+)\.)+([a-zA-Z]{2,4}))?$/)) { 1085*6236dae4SAndroid Build Coastguard Worker 1086*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($smtp_client); 1087*6236dae4SAndroid Build Coastguard Worker 1088*6236dae4SAndroid Build Coastguard Worker if(!@data) { 1089*6236dae4SAndroid Build Coastguard Worker if ($username !~ 1090*6236dae4SAndroid Build Coastguard Worker /^([a-zA-Z0-9._%+-]+)\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4})$/) { 1091*6236dae4SAndroid Build Coastguard Worker push @data, "250 <$username\@example.com>\r\n" 1092*6236dae4SAndroid Build Coastguard Worker } 1093*6236dae4SAndroid Build Coastguard Worker else { 1094*6236dae4SAndroid Build Coastguard Worker push @data, "250 <$username>\r\n" 1095*6236dae4SAndroid Build Coastguard Worker } 1096*6236dae4SAndroid Build Coastguard Worker } 1097*6236dae4SAndroid Build Coastguard Worker 1098*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1099*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1100*6236dae4SAndroid Build Coastguard Worker } 1101*6236dae4SAndroid Build Coastguard Worker } 1102*6236dae4SAndroid Build Coastguard Worker else { 1103*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Invalid address\r\n"; 1104*6236dae4SAndroid Build Coastguard Worker } 1105*6236dae4SAndroid Build Coastguard Worker } 1106*6236dae4SAndroid Build Coastguard Worker 1107*6236dae4SAndroid Build Coastguard Worker return 0; 1108*6236dae4SAndroid Build Coastguard Worker} 1109*6236dae4SAndroid Build Coastguard Worker 1110*6236dae4SAndroid Build Coastguard Workersub EXPN_smtp { 1111*6236dae4SAndroid Build Coastguard Worker my ($list_name) = @_; 1112*6236dae4SAndroid Build Coastguard Worker 1113*6236dae4SAndroid Build Coastguard Worker logmsg "EXPN_smtp got $list_name\n"; 1114*6236dae4SAndroid Build Coastguard Worker 1115*6236dae4SAndroid Build Coastguard Worker if(!$list_name) { 1116*6236dae4SAndroid Build Coastguard Worker sendcontrol "501 Unrecognized parameter\r\n"; 1117*6236dae4SAndroid Build Coastguard Worker } 1118*6236dae4SAndroid Build Coastguard Worker else { 1119*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($smtp_client); 1120*6236dae4SAndroid Build Coastguard Worker 1121*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1122*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1123*6236dae4SAndroid Build Coastguard Worker } 1124*6236dae4SAndroid Build Coastguard Worker } 1125*6236dae4SAndroid Build Coastguard Worker 1126*6236dae4SAndroid Build Coastguard Worker return 0; 1127*6236dae4SAndroid Build Coastguard Worker} 1128*6236dae4SAndroid Build Coastguard Worker 1129*6236dae4SAndroid Build Coastguard Workersub QUIT_smtp { 1130*6236dae4SAndroid Build Coastguard Worker sendcontrol "221 curl $smtp_type server signing off\r\n"; 1131*6236dae4SAndroid Build Coastguard Worker 1132*6236dae4SAndroid Build Coastguard Worker return 0; 1133*6236dae4SAndroid Build Coastguard Worker} 1134*6236dae4SAndroid Build Coastguard Worker 1135*6236dae4SAndroid Build Coastguard Worker# What was deleted by IMAP STORE / POP3 DELE commands 1136*6236dae4SAndroid Build Coastguard Workermy @deleted; 1137*6236dae4SAndroid Build Coastguard Worker 1138*6236dae4SAndroid Build Coastguard Worker################ 1139*6236dae4SAndroid Build Coastguard Worker################ IMAP commands 1140*6236dae4SAndroid Build Coastguard Worker################ 1141*6236dae4SAndroid Build Coastguard Worker 1142*6236dae4SAndroid Build Coastguard Worker# global to allow the command functions to read it 1143*6236dae4SAndroid Build Coastguard Workermy $cmdid; 1144*6236dae4SAndroid Build Coastguard Worker 1145*6236dae4SAndroid Build Coastguard Worker# what was picked by SELECT 1146*6236dae4SAndroid Build Coastguard Workermy $selected; 1147*6236dae4SAndroid Build Coastguard Worker 1148*6236dae4SAndroid Build Coastguard Worker# Any IMAP parameter can come in escaped and in double quotes. 1149*6236dae4SAndroid Build Coastguard Worker# This function is dumb (so far) and just removes the quotes if present. 1150*6236dae4SAndroid Build Coastguard Workersub fix_imap_params { 1151*6236dae4SAndroid Build Coastguard Worker foreach (@_) { 1152*6236dae4SAndroid Build Coastguard Worker $_ = $1 if /^"(.*)"$/; 1153*6236dae4SAndroid Build Coastguard Worker } 1154*6236dae4SAndroid Build Coastguard Worker} 1155*6236dae4SAndroid Build Coastguard Worker 1156*6236dae4SAndroid Build Coastguard Workersub CAPABILITY_imap { 1157*6236dae4SAndroid Build Coastguard Worker if((!@capabilities) && (!@auth_mechs)) { 1158*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command\r\n"; 1159*6236dae4SAndroid Build Coastguard Worker } 1160*6236dae4SAndroid Build Coastguard Worker else { 1161*6236dae4SAndroid Build Coastguard Worker my $data; 1162*6236dae4SAndroid Build Coastguard Worker 1163*6236dae4SAndroid Build Coastguard Worker # Calculate the CAPABILITY response 1164*6236dae4SAndroid Build Coastguard Worker $data = "* CAPABILITY IMAP4"; 1165*6236dae4SAndroid Build Coastguard Worker 1166*6236dae4SAndroid Build Coastguard Worker for my $c (@capabilities) { 1167*6236dae4SAndroid Build Coastguard Worker $data .= " $c"; 1168*6236dae4SAndroid Build Coastguard Worker } 1169*6236dae4SAndroid Build Coastguard Worker 1170*6236dae4SAndroid Build Coastguard Worker for my $am (@auth_mechs) { 1171*6236dae4SAndroid Build Coastguard Worker $data .= " AUTH=$am"; 1172*6236dae4SAndroid Build Coastguard Worker } 1173*6236dae4SAndroid Build Coastguard Worker 1174*6236dae4SAndroid Build Coastguard Worker $data .= " pingpong test server\r\n"; 1175*6236dae4SAndroid Build Coastguard Worker 1176*6236dae4SAndroid Build Coastguard Worker # Send the CAPABILITY response 1177*6236dae4SAndroid Build Coastguard Worker sendcontrol $data; 1178*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK CAPABILITY completed\r\n"; 1179*6236dae4SAndroid Build Coastguard Worker } 1180*6236dae4SAndroid Build Coastguard Worker 1181*6236dae4SAndroid Build Coastguard Worker return 0; 1182*6236dae4SAndroid Build Coastguard Worker} 1183*6236dae4SAndroid Build Coastguard Worker 1184*6236dae4SAndroid Build Coastguard Workersub LOGIN_imap { 1185*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1186*6236dae4SAndroid Build Coastguard Worker my ($user, $password) = split(/ /, $args, 2); 1187*6236dae4SAndroid Build Coastguard Worker fix_imap_params($user, $password); 1188*6236dae4SAndroid Build Coastguard Worker 1189*6236dae4SAndroid Build Coastguard Worker logmsg "LOGIN_imap got $args\n"; 1190*6236dae4SAndroid Build Coastguard Worker 1191*6236dae4SAndroid Build Coastguard Worker if ($user eq "") { 1192*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1193*6236dae4SAndroid Build Coastguard Worker } 1194*6236dae4SAndroid Build Coastguard Worker else { 1195*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK LOGIN completed\r\n"; 1196*6236dae4SAndroid Build Coastguard Worker } 1197*6236dae4SAndroid Build Coastguard Worker 1198*6236dae4SAndroid Build Coastguard Worker return 0; 1199*6236dae4SAndroid Build Coastguard Worker} 1200*6236dae4SAndroid Build Coastguard Worker 1201*6236dae4SAndroid Build Coastguard Workersub SELECT_imap { 1202*6236dae4SAndroid Build Coastguard Worker my ($mailbox) = @_; 1203*6236dae4SAndroid Build Coastguard Worker fix_imap_params($mailbox); 1204*6236dae4SAndroid Build Coastguard Worker 1205*6236dae4SAndroid Build Coastguard Worker logmsg "SELECT_imap got test $mailbox\n"; 1206*6236dae4SAndroid Build Coastguard Worker 1207*6236dae4SAndroid Build Coastguard Worker if($mailbox eq "") { 1208*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1209*6236dae4SAndroid Build Coastguard Worker } 1210*6236dae4SAndroid Build Coastguard Worker else { 1211*6236dae4SAndroid Build Coastguard Worker # Example from RFC 3501, 6.3.1. SELECT Command 1212*6236dae4SAndroid Build Coastguard Worker sendcontrol "* 172 EXISTS\r\n"; 1213*6236dae4SAndroid Build Coastguard Worker sendcontrol "* 1 RECENT\r\n"; 1214*6236dae4SAndroid Build Coastguard Worker sendcontrol "* OK [UNSEEN 12] Message 12 is first unseen\r\n"; 1215*6236dae4SAndroid Build Coastguard Worker sendcontrol "* OK [UIDVALIDITY 3857529045] UIDs valid\r\n"; 1216*6236dae4SAndroid Build Coastguard Worker sendcontrol "* OK [UIDNEXT 4392] Predicted next UID\r\n"; 1217*6236dae4SAndroid Build Coastguard Worker sendcontrol "* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n"; 1218*6236dae4SAndroid Build Coastguard Worker sendcontrol "* OK [PERMANENTFLAGS (\\Deleted \\Seen \\*)] Limited\r\n"; 1219*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK [READ-WRITE] SELECT completed\r\n"; 1220*6236dae4SAndroid Build Coastguard Worker 1221*6236dae4SAndroid Build Coastguard Worker $selected = $mailbox; 1222*6236dae4SAndroid Build Coastguard Worker } 1223*6236dae4SAndroid Build Coastguard Worker 1224*6236dae4SAndroid Build Coastguard Worker return 0; 1225*6236dae4SAndroid Build Coastguard Worker} 1226*6236dae4SAndroid Build Coastguard Worker 1227*6236dae4SAndroid Build Coastguard Workersub FETCH_imap { 1228*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1229*6236dae4SAndroid Build Coastguard Worker my ($uid, $how) = split(/ /, $args, 2); 1230*6236dae4SAndroid Build Coastguard Worker fix_imap_params($uid, $how); 1231*6236dae4SAndroid Build Coastguard Worker 1232*6236dae4SAndroid Build Coastguard Worker logmsg "FETCH_imap got $args\n"; 1233*6236dae4SAndroid Build Coastguard Worker 1234*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1235*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1236*6236dae4SAndroid Build Coastguard Worker } 1237*6236dae4SAndroid Build Coastguard Worker else { 1238*6236dae4SAndroid Build Coastguard Worker my @data; 1239*6236dae4SAndroid Build Coastguard Worker my $size; 1240*6236dae4SAndroid Build Coastguard Worker 1241*6236dae4SAndroid Build Coastguard Worker if($selected eq "verifiedserver") { 1242*6236dae4SAndroid Build Coastguard Worker # this is the secret command that verifies that this actually is 1243*6236dae4SAndroid Build Coastguard Worker # the curl test server 1244*6236dae4SAndroid Build Coastguard Worker my $response = "WE ROOLZ: $$\r\n"; 1245*6236dae4SAndroid Build Coastguard Worker if($verbose) { 1246*6236dae4SAndroid Build Coastguard Worker print STDERR "FTPD: We returned proof we are the test server\n"; 1247*6236dae4SAndroid Build Coastguard Worker } 1248*6236dae4SAndroid Build Coastguard Worker $data[0] = $response; 1249*6236dae4SAndroid Build Coastguard Worker logmsg "return proof we are we\n"; 1250*6236dae4SAndroid Build Coastguard Worker } 1251*6236dae4SAndroid Build Coastguard Worker else { 1252*6236dae4SAndroid Build Coastguard Worker # send mail content 1253*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve a mail\n"; 1254*6236dae4SAndroid Build Coastguard Worker 1255*6236dae4SAndroid Build Coastguard Worker @data = getreplydata($selected); 1256*6236dae4SAndroid Build Coastguard Worker } 1257*6236dae4SAndroid Build Coastguard Worker 1258*6236dae4SAndroid Build Coastguard Worker for (@data) { 1259*6236dae4SAndroid Build Coastguard Worker $size += length($_); 1260*6236dae4SAndroid Build Coastguard Worker } 1261*6236dae4SAndroid Build Coastguard Worker 1262*6236dae4SAndroid Build Coastguard Worker sendcontrol "* $uid FETCH ($how {$size}\r\n"; 1263*6236dae4SAndroid Build Coastguard Worker 1264*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1265*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1266*6236dae4SAndroid Build Coastguard Worker } 1267*6236dae4SAndroid Build Coastguard Worker 1268*6236dae4SAndroid Build Coastguard Worker # Set the custom extra header content with POSTFETCH 1269*6236dae4SAndroid Build Coastguard Worker sendcontrol "$postfetch)\r\n"; 1270*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK FETCH completed\r\n"; 1271*6236dae4SAndroid Build Coastguard Worker } 1272*6236dae4SAndroid Build Coastguard Worker 1273*6236dae4SAndroid Build Coastguard Worker return 0; 1274*6236dae4SAndroid Build Coastguard Worker} 1275*6236dae4SAndroid Build Coastguard Worker 1276*6236dae4SAndroid Build Coastguard Workersub APPEND_imap { 1277*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1278*6236dae4SAndroid Build Coastguard Worker 1279*6236dae4SAndroid Build Coastguard Worker logmsg "APPEND_imap got $args\r\n"; 1280*6236dae4SAndroid Build Coastguard Worker 1281*6236dae4SAndroid Build Coastguard Worker $args =~ /^([^ ]+) [^{]*\{(\d+)\}$/; 1282*6236dae4SAndroid Build Coastguard Worker my ($mailbox, $size) = ($1, $2); 1283*6236dae4SAndroid Build Coastguard Worker fix_imap_params($mailbox); 1284*6236dae4SAndroid Build Coastguard Worker 1285*6236dae4SAndroid Build Coastguard Worker if($mailbox eq "") { 1286*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1287*6236dae4SAndroid Build Coastguard Worker } 1288*6236dae4SAndroid Build Coastguard Worker else { 1289*6236dae4SAndroid Build Coastguard Worker sendcontrol "+ Ready for literal data\r\n"; 1290*6236dae4SAndroid Build Coastguard Worker 1291*6236dae4SAndroid Build Coastguard Worker my $testno = $mailbox; 1292*6236dae4SAndroid Build Coastguard Worker my $filename = "$logdir/upload.$testno"; 1293*6236dae4SAndroid Build Coastguard Worker 1294*6236dae4SAndroid Build Coastguard Worker logmsg "Store test number $testno in $filename\n"; 1295*6236dae4SAndroid Build Coastguard Worker 1296*6236dae4SAndroid Build Coastguard Worker open(my $file, ">", "$filename") || 1297*6236dae4SAndroid Build Coastguard Worker return 0; # failed to open output 1298*6236dae4SAndroid Build Coastguard Worker 1299*6236dae4SAndroid Build Coastguard Worker my $received = 0; 1300*6236dae4SAndroid Build Coastguard Worker my $line; 1301*6236dae4SAndroid Build Coastguard Worker while(5 == (sysread \*SFREAD, $line, 5)) { 1302*6236dae4SAndroid Build Coastguard Worker if($line eq "DATA\n") { 1303*6236dae4SAndroid Build Coastguard Worker sysread \*SFREAD, $line, 5; 1304*6236dae4SAndroid Build Coastguard Worker 1305*6236dae4SAndroid Build Coastguard Worker my $chunksize = 0; 1306*6236dae4SAndroid Build Coastguard Worker if($line =~ /^([0-9a-fA-F]{4})\n/) { 1307*6236dae4SAndroid Build Coastguard Worker $chunksize = hex($1); 1308*6236dae4SAndroid Build Coastguard Worker } 1309*6236dae4SAndroid Build Coastguard Worker 1310*6236dae4SAndroid Build Coastguard Worker read_mainsockf(\$line, $chunksize); 1311*6236dae4SAndroid Build Coastguard Worker 1312*6236dae4SAndroid Build Coastguard Worker my $left = $size - $received; 1313*6236dae4SAndroid Build Coastguard Worker my $datasize = ($left > $chunksize) ? $chunksize : $left; 1314*6236dae4SAndroid Build Coastguard Worker 1315*6236dae4SAndroid Build Coastguard Worker if($datasize > 0) { 1316*6236dae4SAndroid Build Coastguard Worker logmsg "> Appending $datasize bytes to file\n"; 1317*6236dae4SAndroid Build Coastguard Worker print $file substr($line, 0, $datasize) if(!$nosave); 1318*6236dae4SAndroid Build Coastguard Worker $line = substr($line, $datasize); 1319*6236dae4SAndroid Build Coastguard Worker 1320*6236dae4SAndroid Build Coastguard Worker $received += $datasize; 1321*6236dae4SAndroid Build Coastguard Worker if($received == $size) { 1322*6236dae4SAndroid Build Coastguard Worker logmsg "Received all data, waiting for final CRLF.\n"; 1323*6236dae4SAndroid Build Coastguard Worker } 1324*6236dae4SAndroid Build Coastguard Worker } 1325*6236dae4SAndroid Build Coastguard Worker 1326*6236dae4SAndroid Build Coastguard Worker if($received == $size && $line eq "\r\n") { 1327*6236dae4SAndroid Build Coastguard Worker last; 1328*6236dae4SAndroid Build Coastguard Worker } 1329*6236dae4SAndroid Build Coastguard Worker } 1330*6236dae4SAndroid Build Coastguard Worker elsif($line eq "DISC\n") { 1331*6236dae4SAndroid Build Coastguard Worker logmsg "Unexpected disconnect!\n"; 1332*6236dae4SAndroid Build Coastguard Worker printf SFWRITE "ACKD\n"; 1333*6236dae4SAndroid Build Coastguard Worker last; 1334*6236dae4SAndroid Build Coastguard Worker } 1335*6236dae4SAndroid Build Coastguard Worker else { 1336*6236dae4SAndroid Build Coastguard Worker logmsg "No support for: $line"; 1337*6236dae4SAndroid Build Coastguard Worker last; 1338*6236dae4SAndroid Build Coastguard Worker } 1339*6236dae4SAndroid Build Coastguard Worker } 1340*6236dae4SAndroid Build Coastguard Worker 1341*6236dae4SAndroid Build Coastguard Worker if($nosave) { 1342*6236dae4SAndroid Build Coastguard Worker print $file "$size bytes would've been stored here\n"; 1343*6236dae4SAndroid Build Coastguard Worker } 1344*6236dae4SAndroid Build Coastguard Worker 1345*6236dae4SAndroid Build Coastguard Worker close($file); 1346*6236dae4SAndroid Build Coastguard Worker 1347*6236dae4SAndroid Build Coastguard Worker logmsg "received $size bytes upload\n"; 1348*6236dae4SAndroid Build Coastguard Worker 1349*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK APPEND completed\r\n"; 1350*6236dae4SAndroid Build Coastguard Worker } 1351*6236dae4SAndroid Build Coastguard Worker 1352*6236dae4SAndroid Build Coastguard Worker return 0; 1353*6236dae4SAndroid Build Coastguard Worker} 1354*6236dae4SAndroid Build Coastguard Worker 1355*6236dae4SAndroid Build Coastguard Workersub STORE_imap { 1356*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1357*6236dae4SAndroid Build Coastguard Worker my ($uid, $what, $value) = split(/ /, $args, 3); 1358*6236dae4SAndroid Build Coastguard Worker fix_imap_params($uid); 1359*6236dae4SAndroid Build Coastguard Worker 1360*6236dae4SAndroid Build Coastguard Worker logmsg "STORE_imap got $args\n"; 1361*6236dae4SAndroid Build Coastguard Worker 1362*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1363*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1364*6236dae4SAndroid Build Coastguard Worker } 1365*6236dae4SAndroid Build Coastguard Worker elsif (($uid eq "") || ($what ne "+Flags") || ($value eq "")) { 1366*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1367*6236dae4SAndroid Build Coastguard Worker } 1368*6236dae4SAndroid Build Coastguard Worker else { 1369*6236dae4SAndroid Build Coastguard Worker if($value eq "\\Deleted") { 1370*6236dae4SAndroid Build Coastguard Worker push(@deleted, $uid); 1371*6236dae4SAndroid Build Coastguard Worker } 1372*6236dae4SAndroid Build Coastguard Worker 1373*6236dae4SAndroid Build Coastguard Worker sendcontrol "* $uid FETCH (FLAGS (\\Seen $value))\r\n"; 1374*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK STORE completed\r\n"; 1375*6236dae4SAndroid Build Coastguard Worker } 1376*6236dae4SAndroid Build Coastguard Worker 1377*6236dae4SAndroid Build Coastguard Worker return 0; 1378*6236dae4SAndroid Build Coastguard Worker} 1379*6236dae4SAndroid Build Coastguard Worker 1380*6236dae4SAndroid Build Coastguard Workersub LIST_imap { 1381*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1382*6236dae4SAndroid Build Coastguard Worker my ($reference, $mailbox) = split(/ /, $args, 2); 1383*6236dae4SAndroid Build Coastguard Worker fix_imap_params($reference, $mailbox); 1384*6236dae4SAndroid Build Coastguard Worker 1385*6236dae4SAndroid Build Coastguard Worker logmsg "LIST_imap got $args\n"; 1386*6236dae4SAndroid Build Coastguard Worker 1387*6236dae4SAndroid Build Coastguard Worker if ($reference eq "") { 1388*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1389*6236dae4SAndroid Build Coastguard Worker } 1390*6236dae4SAndroid Build Coastguard Worker elsif ($reference eq "verifiedserver") { 1391*6236dae4SAndroid Build Coastguard Worker # this is the secret command that verifies that this actually is 1392*6236dae4SAndroid Build Coastguard Worker # the curl test server 1393*6236dae4SAndroid Build Coastguard Worker sendcontrol "* LIST () \"/\" \"WE ROOLZ: $$\"\r\n"; 1394*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK LIST Completed\r\n"; 1395*6236dae4SAndroid Build Coastguard Worker 1396*6236dae4SAndroid Build Coastguard Worker if($verbose) { 1397*6236dae4SAndroid Build Coastguard Worker print STDERR "FTPD: We returned proof we are the test server\n"; 1398*6236dae4SAndroid Build Coastguard Worker } 1399*6236dae4SAndroid Build Coastguard Worker 1400*6236dae4SAndroid Build Coastguard Worker logmsg "return proof we are we\n"; 1401*6236dae4SAndroid Build Coastguard Worker } 1402*6236dae4SAndroid Build Coastguard Worker else { 1403*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($reference); 1404*6236dae4SAndroid Build Coastguard Worker 1405*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1406*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1407*6236dae4SAndroid Build Coastguard Worker } 1408*6236dae4SAndroid Build Coastguard Worker 1409*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK LIST Completed\r\n"; 1410*6236dae4SAndroid Build Coastguard Worker } 1411*6236dae4SAndroid Build Coastguard Worker 1412*6236dae4SAndroid Build Coastguard Worker return 0; 1413*6236dae4SAndroid Build Coastguard Worker} 1414*6236dae4SAndroid Build Coastguard Worker 1415*6236dae4SAndroid Build Coastguard Workersub LSUB_imap { 1416*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1417*6236dae4SAndroid Build Coastguard Worker my ($reference, $mailbox) = split(/ /, $args, 2); 1418*6236dae4SAndroid Build Coastguard Worker fix_imap_params($reference, $mailbox); 1419*6236dae4SAndroid Build Coastguard Worker 1420*6236dae4SAndroid Build Coastguard Worker logmsg "LSUB_imap got $args\n"; 1421*6236dae4SAndroid Build Coastguard Worker 1422*6236dae4SAndroid Build Coastguard Worker if ($reference eq "") { 1423*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1424*6236dae4SAndroid Build Coastguard Worker } 1425*6236dae4SAndroid Build Coastguard Worker else { 1426*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($reference); 1427*6236dae4SAndroid Build Coastguard Worker 1428*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1429*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1430*6236dae4SAndroid Build Coastguard Worker } 1431*6236dae4SAndroid Build Coastguard Worker 1432*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK LSUB Completed\r\n"; 1433*6236dae4SAndroid Build Coastguard Worker } 1434*6236dae4SAndroid Build Coastguard Worker 1435*6236dae4SAndroid Build Coastguard Worker return 0; 1436*6236dae4SAndroid Build Coastguard Worker} 1437*6236dae4SAndroid Build Coastguard Worker 1438*6236dae4SAndroid Build Coastguard Workersub EXAMINE_imap { 1439*6236dae4SAndroid Build Coastguard Worker my ($mailbox) = @_; 1440*6236dae4SAndroid Build Coastguard Worker fix_imap_params($mailbox); 1441*6236dae4SAndroid Build Coastguard Worker 1442*6236dae4SAndroid Build Coastguard Worker logmsg "EXAMINE_imap got $mailbox\n"; 1443*6236dae4SAndroid Build Coastguard Worker 1444*6236dae4SAndroid Build Coastguard Worker if ($mailbox eq "") { 1445*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1446*6236dae4SAndroid Build Coastguard Worker } 1447*6236dae4SAndroid Build Coastguard Worker else { 1448*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($mailbox); 1449*6236dae4SAndroid Build Coastguard Worker 1450*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1451*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1452*6236dae4SAndroid Build Coastguard Worker } 1453*6236dae4SAndroid Build Coastguard Worker 1454*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK [READ-ONLY] EXAMINE completed\r\n"; 1455*6236dae4SAndroid Build Coastguard Worker } 1456*6236dae4SAndroid Build Coastguard Worker 1457*6236dae4SAndroid Build Coastguard Worker return 0; 1458*6236dae4SAndroid Build Coastguard Worker} 1459*6236dae4SAndroid Build Coastguard Worker 1460*6236dae4SAndroid Build Coastguard Workersub STATUS_imap { 1461*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1462*6236dae4SAndroid Build Coastguard Worker my ($mailbox, $what) = split(/ /, $args, 2); 1463*6236dae4SAndroid Build Coastguard Worker fix_imap_params($mailbox); 1464*6236dae4SAndroid Build Coastguard Worker 1465*6236dae4SAndroid Build Coastguard Worker logmsg "STATUS_imap got $args\n"; 1466*6236dae4SAndroid Build Coastguard Worker 1467*6236dae4SAndroid Build Coastguard Worker if ($mailbox eq "") { 1468*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1469*6236dae4SAndroid Build Coastguard Worker } 1470*6236dae4SAndroid Build Coastguard Worker else { 1471*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($mailbox); 1472*6236dae4SAndroid Build Coastguard Worker 1473*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1474*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1475*6236dae4SAndroid Build Coastguard Worker } 1476*6236dae4SAndroid Build Coastguard Worker 1477*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK STATUS completed\r\n"; 1478*6236dae4SAndroid Build Coastguard Worker } 1479*6236dae4SAndroid Build Coastguard Worker 1480*6236dae4SAndroid Build Coastguard Worker return 0; 1481*6236dae4SAndroid Build Coastguard Worker} 1482*6236dae4SAndroid Build Coastguard Worker 1483*6236dae4SAndroid Build Coastguard Workersub SEARCH_imap { 1484*6236dae4SAndroid Build Coastguard Worker my ($what) = @_; 1485*6236dae4SAndroid Build Coastguard Worker fix_imap_params($what); 1486*6236dae4SAndroid Build Coastguard Worker 1487*6236dae4SAndroid Build Coastguard Worker logmsg "SEARCH_imap got $what\n"; 1488*6236dae4SAndroid Build Coastguard Worker 1489*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1490*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1491*6236dae4SAndroid Build Coastguard Worker } 1492*6236dae4SAndroid Build Coastguard Worker elsif ($what eq "") { 1493*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1494*6236dae4SAndroid Build Coastguard Worker } 1495*6236dae4SAndroid Build Coastguard Worker else { 1496*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($selected); 1497*6236dae4SAndroid Build Coastguard Worker 1498*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1499*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1500*6236dae4SAndroid Build Coastguard Worker } 1501*6236dae4SAndroid Build Coastguard Worker 1502*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK SEARCH completed\r\n"; 1503*6236dae4SAndroid Build Coastguard Worker } 1504*6236dae4SAndroid Build Coastguard Worker 1505*6236dae4SAndroid Build Coastguard Worker return 0; 1506*6236dae4SAndroid Build Coastguard Worker} 1507*6236dae4SAndroid Build Coastguard Worker 1508*6236dae4SAndroid Build Coastguard Workersub CREATE_imap { 1509*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1510*6236dae4SAndroid Build Coastguard Worker fix_imap_params($args); 1511*6236dae4SAndroid Build Coastguard Worker 1512*6236dae4SAndroid Build Coastguard Worker logmsg "CREATE_imap got $args\n"; 1513*6236dae4SAndroid Build Coastguard Worker 1514*6236dae4SAndroid Build Coastguard Worker if ($args eq "") { 1515*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1516*6236dae4SAndroid Build Coastguard Worker } 1517*6236dae4SAndroid Build Coastguard Worker else { 1518*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK CREATE completed\r\n"; 1519*6236dae4SAndroid Build Coastguard Worker } 1520*6236dae4SAndroid Build Coastguard Worker 1521*6236dae4SAndroid Build Coastguard Worker return 0; 1522*6236dae4SAndroid Build Coastguard Worker} 1523*6236dae4SAndroid Build Coastguard Worker 1524*6236dae4SAndroid Build Coastguard Workersub DELETE_imap { 1525*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1526*6236dae4SAndroid Build Coastguard Worker fix_imap_params($args); 1527*6236dae4SAndroid Build Coastguard Worker 1528*6236dae4SAndroid Build Coastguard Worker logmsg "DELETE_imap got $args\n"; 1529*6236dae4SAndroid Build Coastguard Worker 1530*6236dae4SAndroid Build Coastguard Worker if ($args eq "") { 1531*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1532*6236dae4SAndroid Build Coastguard Worker } 1533*6236dae4SAndroid Build Coastguard Worker else { 1534*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK DELETE completed\r\n"; 1535*6236dae4SAndroid Build Coastguard Worker } 1536*6236dae4SAndroid Build Coastguard Worker 1537*6236dae4SAndroid Build Coastguard Worker return 0; 1538*6236dae4SAndroid Build Coastguard Worker} 1539*6236dae4SAndroid Build Coastguard Worker 1540*6236dae4SAndroid Build Coastguard Workersub RENAME_imap { 1541*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1542*6236dae4SAndroid Build Coastguard Worker my ($from_mailbox, $to_mailbox) = split(/ /, $args, 2); 1543*6236dae4SAndroid Build Coastguard Worker fix_imap_params($from_mailbox, $to_mailbox); 1544*6236dae4SAndroid Build Coastguard Worker 1545*6236dae4SAndroid Build Coastguard Worker logmsg "RENAME_imap got $args\n"; 1546*6236dae4SAndroid Build Coastguard Worker 1547*6236dae4SAndroid Build Coastguard Worker if (($from_mailbox eq "") || ($to_mailbox eq "")) { 1548*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1549*6236dae4SAndroid Build Coastguard Worker } 1550*6236dae4SAndroid Build Coastguard Worker else { 1551*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK RENAME completed\r\n"; 1552*6236dae4SAndroid Build Coastguard Worker } 1553*6236dae4SAndroid Build Coastguard Worker 1554*6236dae4SAndroid Build Coastguard Worker return 0; 1555*6236dae4SAndroid Build Coastguard Worker} 1556*6236dae4SAndroid Build Coastguard Worker 1557*6236dae4SAndroid Build Coastguard Workersub CHECK_imap { 1558*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1559*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1560*6236dae4SAndroid Build Coastguard Worker } 1561*6236dae4SAndroid Build Coastguard Worker else { 1562*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK CHECK completed\r\n"; 1563*6236dae4SAndroid Build Coastguard Worker } 1564*6236dae4SAndroid Build Coastguard Worker 1565*6236dae4SAndroid Build Coastguard Worker return 0; 1566*6236dae4SAndroid Build Coastguard Worker} 1567*6236dae4SAndroid Build Coastguard Worker 1568*6236dae4SAndroid Build Coastguard Workersub CLOSE_imap { 1569*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1570*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1571*6236dae4SAndroid Build Coastguard Worker } 1572*6236dae4SAndroid Build Coastguard Worker elsif (!@deleted) { 1573*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1574*6236dae4SAndroid Build Coastguard Worker } 1575*6236dae4SAndroid Build Coastguard Worker else { 1576*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK CLOSE completed\r\n"; 1577*6236dae4SAndroid Build Coastguard Worker 1578*6236dae4SAndroid Build Coastguard Worker @deleted = (); 1579*6236dae4SAndroid Build Coastguard Worker } 1580*6236dae4SAndroid Build Coastguard Worker 1581*6236dae4SAndroid Build Coastguard Worker return 0; 1582*6236dae4SAndroid Build Coastguard Worker} 1583*6236dae4SAndroid Build Coastguard Worker 1584*6236dae4SAndroid Build Coastguard Workersub EXPUNGE_imap { 1585*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1586*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1587*6236dae4SAndroid Build Coastguard Worker } 1588*6236dae4SAndroid Build Coastguard Worker else { 1589*6236dae4SAndroid Build Coastguard Worker if (!@deleted) { 1590*6236dae4SAndroid Build Coastguard Worker # Report the number of existing messages as per the SELECT 1591*6236dae4SAndroid Build Coastguard Worker # command 1592*6236dae4SAndroid Build Coastguard Worker sendcontrol "* 172 EXISTS\r\n"; 1593*6236dae4SAndroid Build Coastguard Worker } 1594*6236dae4SAndroid Build Coastguard Worker else { 1595*6236dae4SAndroid Build Coastguard Worker # Report the message UIDs being deleted 1596*6236dae4SAndroid Build Coastguard Worker for my $d (@deleted) { 1597*6236dae4SAndroid Build Coastguard Worker sendcontrol "* $d EXPUNGE\r\n"; 1598*6236dae4SAndroid Build Coastguard Worker } 1599*6236dae4SAndroid Build Coastguard Worker 1600*6236dae4SAndroid Build Coastguard Worker @deleted = (); 1601*6236dae4SAndroid Build Coastguard Worker } 1602*6236dae4SAndroid Build Coastguard Worker 1603*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK EXPUNGE completed\r\n"; 1604*6236dae4SAndroid Build Coastguard Worker } 1605*6236dae4SAndroid Build Coastguard Worker 1606*6236dae4SAndroid Build Coastguard Worker return 0; 1607*6236dae4SAndroid Build Coastguard Worker} 1608*6236dae4SAndroid Build Coastguard Worker 1609*6236dae4SAndroid Build Coastguard Workersub COPY_imap { 1610*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1611*6236dae4SAndroid Build Coastguard Worker my ($uid, $mailbox) = split(/ /, $args, 2); 1612*6236dae4SAndroid Build Coastguard Worker fix_imap_params($uid, $mailbox); 1613*6236dae4SAndroid Build Coastguard Worker 1614*6236dae4SAndroid Build Coastguard Worker logmsg "COPY_imap got $args\n"; 1615*6236dae4SAndroid Build Coastguard Worker 1616*6236dae4SAndroid Build Coastguard Worker if (($uid eq "") || ($mailbox eq "")) { 1617*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1618*6236dae4SAndroid Build Coastguard Worker } 1619*6236dae4SAndroid Build Coastguard Worker else { 1620*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK COPY completed\r\n"; 1621*6236dae4SAndroid Build Coastguard Worker } 1622*6236dae4SAndroid Build Coastguard Worker 1623*6236dae4SAndroid Build Coastguard Worker return 0; 1624*6236dae4SAndroid Build Coastguard Worker} 1625*6236dae4SAndroid Build Coastguard Worker 1626*6236dae4SAndroid Build Coastguard Workersub IDLE_imap { 1627*6236dae4SAndroid Build Coastguard Worker logmsg "IDLE received\n"; 1628*6236dae4SAndroid Build Coastguard Worker 1629*6236dae4SAndroid Build Coastguard Worker sendcontrol "+ entering idle mode\r\n"; 1630*6236dae4SAndroid Build Coastguard Worker return 0; 1631*6236dae4SAndroid Build Coastguard Worker} 1632*6236dae4SAndroid Build Coastguard Worker 1633*6236dae4SAndroid Build Coastguard Workersub UID_imap { 1634*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1635*6236dae4SAndroid Build Coastguard Worker my ($command) = split(/ /, $args, 1); 1636*6236dae4SAndroid Build Coastguard Worker fix_imap_params($command); 1637*6236dae4SAndroid Build Coastguard Worker 1638*6236dae4SAndroid Build Coastguard Worker logmsg "UID_imap got $args\n"; 1639*6236dae4SAndroid Build Coastguard Worker 1640*6236dae4SAndroid Build Coastguard Worker if ($selected eq "") { 1641*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command received in Invalid state\r\n"; 1642*6236dae4SAndroid Build Coastguard Worker } 1643*6236dae4SAndroid Build Coastguard Worker elsif (substr($command, 0, 5) eq "FETCH"){ 1644*6236dae4SAndroid Build Coastguard Worker my $func = $commandfunc{"FETCH"}; 1645*6236dae4SAndroid Build Coastguard Worker if($func) { 1646*6236dae4SAndroid Build Coastguard Worker &$func($args, $command); 1647*6236dae4SAndroid Build Coastguard Worker } 1648*6236dae4SAndroid Build Coastguard Worker } 1649*6236dae4SAndroid Build Coastguard Worker elsif (($command ne "COPY") && 1650*6236dae4SAndroid Build Coastguard Worker ($command ne "STORE") && ($command ne "SEARCH")) { 1651*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1652*6236dae4SAndroid Build Coastguard Worker } 1653*6236dae4SAndroid Build Coastguard Worker else { 1654*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($selected); 1655*6236dae4SAndroid Build Coastguard Worker 1656*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1657*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1658*6236dae4SAndroid Build Coastguard Worker } 1659*6236dae4SAndroid Build Coastguard Worker 1660*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK $command completed\r\n"; 1661*6236dae4SAndroid Build Coastguard Worker } 1662*6236dae4SAndroid Build Coastguard Worker 1663*6236dae4SAndroid Build Coastguard Worker return 0; 1664*6236dae4SAndroid Build Coastguard Worker} 1665*6236dae4SAndroid Build Coastguard Worker 1666*6236dae4SAndroid Build Coastguard Workersub NOOP_imap { 1667*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1668*6236dae4SAndroid Build Coastguard Worker my @data = ( 1669*6236dae4SAndroid Build Coastguard Worker "* 22 EXPUNGE\r\n", 1670*6236dae4SAndroid Build Coastguard Worker "* 23 EXISTS\r\n", 1671*6236dae4SAndroid Build Coastguard Worker "* 3 RECENT\r\n", 1672*6236dae4SAndroid Build Coastguard Worker "* 14 FETCH (FLAGS (\\Seen \\Deleted))\r\n", 1673*6236dae4SAndroid Build Coastguard Worker ); 1674*6236dae4SAndroid Build Coastguard Worker 1675*6236dae4SAndroid Build Coastguard Worker if ($args) { 1676*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD Command Argument\r\n"; 1677*6236dae4SAndroid Build Coastguard Worker } 1678*6236dae4SAndroid Build Coastguard Worker else { 1679*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1680*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1681*6236dae4SAndroid Build Coastguard Worker } 1682*6236dae4SAndroid Build Coastguard Worker 1683*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK NOOP completed\r\n"; 1684*6236dae4SAndroid Build Coastguard Worker } 1685*6236dae4SAndroid Build Coastguard Worker 1686*6236dae4SAndroid Build Coastguard Worker return 0; 1687*6236dae4SAndroid Build Coastguard Worker} 1688*6236dae4SAndroid Build Coastguard Worker 1689*6236dae4SAndroid Build Coastguard Workersub LOGOUT_imap { 1690*6236dae4SAndroid Build Coastguard Worker sendcontrol "* BYE curl IMAP server signing off\r\n"; 1691*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid OK LOGOUT completed\r\n"; 1692*6236dae4SAndroid Build Coastguard Worker 1693*6236dae4SAndroid Build Coastguard Worker return 0; 1694*6236dae4SAndroid Build Coastguard Worker} 1695*6236dae4SAndroid Build Coastguard Worker 1696*6236dae4SAndroid Build Coastguard Worker################ 1697*6236dae4SAndroid Build Coastguard Worker################ POP3 commands 1698*6236dae4SAndroid Build Coastguard Worker################ 1699*6236dae4SAndroid Build Coastguard Worker 1700*6236dae4SAndroid Build Coastguard Worker# Who is attempting to log in 1701*6236dae4SAndroid Build Coastguard Workermy $username; 1702*6236dae4SAndroid Build Coastguard Worker 1703*6236dae4SAndroid Build Coastguard Workersub CAPA_pop3 { 1704*6236dae4SAndroid Build Coastguard Worker my @list = (); 1705*6236dae4SAndroid Build Coastguard Worker my $mechs; 1706*6236dae4SAndroid Build Coastguard Worker 1707*6236dae4SAndroid Build Coastguard Worker # Calculate the capability list based on the specified capabilities 1708*6236dae4SAndroid Build Coastguard Worker # (except APOP) and any authentication mechanisms 1709*6236dae4SAndroid Build Coastguard Worker for my $c (@capabilities) { 1710*6236dae4SAndroid Build Coastguard Worker push @list, "$c\r\n" unless $c eq "APOP"; 1711*6236dae4SAndroid Build Coastguard Worker } 1712*6236dae4SAndroid Build Coastguard Worker 1713*6236dae4SAndroid Build Coastguard Worker for my $am (@auth_mechs) { 1714*6236dae4SAndroid Build Coastguard Worker if(!$mechs) { 1715*6236dae4SAndroid Build Coastguard Worker $mechs = "$am"; 1716*6236dae4SAndroid Build Coastguard Worker } 1717*6236dae4SAndroid Build Coastguard Worker else { 1718*6236dae4SAndroid Build Coastguard Worker $mechs .= " $am"; 1719*6236dae4SAndroid Build Coastguard Worker } 1720*6236dae4SAndroid Build Coastguard Worker } 1721*6236dae4SAndroid Build Coastguard Worker 1722*6236dae4SAndroid Build Coastguard Worker if($mechs) { 1723*6236dae4SAndroid Build Coastguard Worker push @list, "SASL $mechs\r\n"; 1724*6236dae4SAndroid Build Coastguard Worker } 1725*6236dae4SAndroid Build Coastguard Worker 1726*6236dae4SAndroid Build Coastguard Worker if(!@list) { 1727*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 1728*6236dae4SAndroid Build Coastguard Worker } 1729*6236dae4SAndroid Build Coastguard Worker else { 1730*6236dae4SAndroid Build Coastguard Worker my @data = (); 1731*6236dae4SAndroid Build Coastguard Worker 1732*6236dae4SAndroid Build Coastguard Worker # Calculate the CAPA response 1733*6236dae4SAndroid Build Coastguard Worker push @data, "+OK List of capabilities follows\r\n"; 1734*6236dae4SAndroid Build Coastguard Worker 1735*6236dae4SAndroid Build Coastguard Worker for my $l (@list) { 1736*6236dae4SAndroid Build Coastguard Worker push @data, "$l\r\n"; 1737*6236dae4SAndroid Build Coastguard Worker } 1738*6236dae4SAndroid Build Coastguard Worker 1739*6236dae4SAndroid Build Coastguard Worker push @data, "IMPLEMENTATION POP3 pingpong test server\r\n"; 1740*6236dae4SAndroid Build Coastguard Worker 1741*6236dae4SAndroid Build Coastguard Worker # Send the CAPA response 1742*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1743*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1744*6236dae4SAndroid Build Coastguard Worker } 1745*6236dae4SAndroid Build Coastguard Worker 1746*6236dae4SAndroid Build Coastguard Worker # End with the magic 3-byte end of listing marker 1747*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1748*6236dae4SAndroid Build Coastguard Worker } 1749*6236dae4SAndroid Build Coastguard Worker 1750*6236dae4SAndroid Build Coastguard Worker return 0; 1751*6236dae4SAndroid Build Coastguard Worker} 1752*6236dae4SAndroid Build Coastguard Worker 1753*6236dae4SAndroid Build Coastguard Workersub APOP_pop3 { 1754*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1755*6236dae4SAndroid Build Coastguard Worker my ($user, $secret) = split(/ /, $args, 2); 1756*6236dae4SAndroid Build Coastguard Worker 1757*6236dae4SAndroid Build Coastguard Worker if (!grep /^APOP$/, @capabilities) { 1758*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 1759*6236dae4SAndroid Build Coastguard Worker } 1760*6236dae4SAndroid Build Coastguard Worker elsif (($user eq "") || ($secret eq "")) { 1761*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1762*6236dae4SAndroid Build Coastguard Worker } 1763*6236dae4SAndroid Build Coastguard Worker else { 1764*6236dae4SAndroid Build Coastguard Worker my $digest = Digest::MD5::md5_hex($POP3_TIMESTAMP, $TEXT_PASSWORD); 1765*6236dae4SAndroid Build Coastguard Worker 1766*6236dae4SAndroid Build Coastguard Worker if ($secret ne $digest) { 1767*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Login failure\r\n"; 1768*6236dae4SAndroid Build Coastguard Worker } 1769*6236dae4SAndroid Build Coastguard Worker else { 1770*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Login successful\r\n"; 1771*6236dae4SAndroid Build Coastguard Worker } 1772*6236dae4SAndroid Build Coastguard Worker } 1773*6236dae4SAndroid Build Coastguard Worker 1774*6236dae4SAndroid Build Coastguard Worker return 0; 1775*6236dae4SAndroid Build Coastguard Worker} 1776*6236dae4SAndroid Build Coastguard Worker 1777*6236dae4SAndroid Build Coastguard Workersub AUTH_pop3 { 1778*6236dae4SAndroid Build Coastguard Worker if(!@auth_mechs) { 1779*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 1780*6236dae4SAndroid Build Coastguard Worker } 1781*6236dae4SAndroid Build Coastguard Worker else { 1782*6236dae4SAndroid Build Coastguard Worker my @data = (); 1783*6236dae4SAndroid Build Coastguard Worker 1784*6236dae4SAndroid Build Coastguard Worker # Calculate the AUTH response 1785*6236dae4SAndroid Build Coastguard Worker push @data, "+OK List of supported mechanisms follows\r\n"; 1786*6236dae4SAndroid Build Coastguard Worker 1787*6236dae4SAndroid Build Coastguard Worker for my $am (@auth_mechs) { 1788*6236dae4SAndroid Build Coastguard Worker push @data, "$am\r\n"; 1789*6236dae4SAndroid Build Coastguard Worker } 1790*6236dae4SAndroid Build Coastguard Worker 1791*6236dae4SAndroid Build Coastguard Worker # Send the AUTH response 1792*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1793*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1794*6236dae4SAndroid Build Coastguard Worker } 1795*6236dae4SAndroid Build Coastguard Worker 1796*6236dae4SAndroid Build Coastguard Worker # End with the magic 3-byte end of listing marker 1797*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1798*6236dae4SAndroid Build Coastguard Worker } 1799*6236dae4SAndroid Build Coastguard Worker 1800*6236dae4SAndroid Build Coastguard Worker return 0; 1801*6236dae4SAndroid Build Coastguard Worker} 1802*6236dae4SAndroid Build Coastguard Worker 1803*6236dae4SAndroid Build Coastguard Workersub USER_pop3 { 1804*6236dae4SAndroid Build Coastguard Worker my ($user) = @_; 1805*6236dae4SAndroid Build Coastguard Worker 1806*6236dae4SAndroid Build Coastguard Worker logmsg "USER_pop3 got $user\n"; 1807*6236dae4SAndroid Build Coastguard Worker 1808*6236dae4SAndroid Build Coastguard Worker if (!$user) { 1809*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1810*6236dae4SAndroid Build Coastguard Worker } 1811*6236dae4SAndroid Build Coastguard Worker else { 1812*6236dae4SAndroid Build Coastguard Worker $username = $user; 1813*6236dae4SAndroid Build Coastguard Worker 1814*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK\r\n"; 1815*6236dae4SAndroid Build Coastguard Worker } 1816*6236dae4SAndroid Build Coastguard Worker 1817*6236dae4SAndroid Build Coastguard Worker return 0; 1818*6236dae4SAndroid Build Coastguard Worker} 1819*6236dae4SAndroid Build Coastguard Worker 1820*6236dae4SAndroid Build Coastguard Workersub PASS_pop3 { 1821*6236dae4SAndroid Build Coastguard Worker my ($password) = @_; 1822*6236dae4SAndroid Build Coastguard Worker 1823*6236dae4SAndroid Build Coastguard Worker logmsg "PASS_pop3 got $password\n"; 1824*6236dae4SAndroid Build Coastguard Worker 1825*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Login successful\r\n"; 1826*6236dae4SAndroid Build Coastguard Worker 1827*6236dae4SAndroid Build Coastguard Worker return 0; 1828*6236dae4SAndroid Build Coastguard Worker} 1829*6236dae4SAndroid Build Coastguard Worker 1830*6236dae4SAndroid Build Coastguard Workersub RETR_pop3 { 1831*6236dae4SAndroid Build Coastguard Worker my ($msgid) = @_; 1832*6236dae4SAndroid Build Coastguard Worker my @data; 1833*6236dae4SAndroid Build Coastguard Worker 1834*6236dae4SAndroid Build Coastguard Worker if($msgid =~ /^verifiedserver$/) { 1835*6236dae4SAndroid Build Coastguard Worker # this is the secret command that verifies that this actually is 1836*6236dae4SAndroid Build Coastguard Worker # the curl test server 1837*6236dae4SAndroid Build Coastguard Worker my $response = "WE ROOLZ: $$\r\n"; 1838*6236dae4SAndroid Build Coastguard Worker if($verbose) { 1839*6236dae4SAndroid Build Coastguard Worker print STDERR "FTPD: We returned proof we are the test server\n"; 1840*6236dae4SAndroid Build Coastguard Worker } 1841*6236dae4SAndroid Build Coastguard Worker $data[0] = $response; 1842*6236dae4SAndroid Build Coastguard Worker logmsg "return proof we are we\n"; 1843*6236dae4SAndroid Build Coastguard Worker } 1844*6236dae4SAndroid Build Coastguard Worker else { 1845*6236dae4SAndroid Build Coastguard Worker # send mail content 1846*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve a mail\n"; 1847*6236dae4SAndroid Build Coastguard Worker 1848*6236dae4SAndroid Build Coastguard Worker @data = getreplydata($msgid); 1849*6236dae4SAndroid Build Coastguard Worker } 1850*6236dae4SAndroid Build Coastguard Worker 1851*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Mail transfer starts\r\n"; 1852*6236dae4SAndroid Build Coastguard Worker 1853*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1854*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1855*6236dae4SAndroid Build Coastguard Worker } 1856*6236dae4SAndroid Build Coastguard Worker 1857*6236dae4SAndroid Build Coastguard Worker # end with the magic 3-byte end of mail marker, assumes that the 1858*6236dae4SAndroid Build Coastguard Worker # mail body ends with a CRLF! 1859*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1860*6236dae4SAndroid Build Coastguard Worker 1861*6236dae4SAndroid Build Coastguard Worker return 0; 1862*6236dae4SAndroid Build Coastguard Worker} 1863*6236dae4SAndroid Build Coastguard Worker 1864*6236dae4SAndroid Build Coastguard Workersub LIST_pop3 { 1865*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "data"); 1866*6236dae4SAndroid Build Coastguard Worker 1867*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve a message list\n"; 1868*6236dae4SAndroid Build Coastguard Worker 1869*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Listing starts\r\n"; 1870*6236dae4SAndroid Build Coastguard Worker 1871*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1872*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1873*6236dae4SAndroid Build Coastguard Worker } 1874*6236dae4SAndroid Build Coastguard Worker 1875*6236dae4SAndroid Build Coastguard Worker # End with the magic 3-byte end of listing marker 1876*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1877*6236dae4SAndroid Build Coastguard Worker 1878*6236dae4SAndroid Build Coastguard Worker return 0; 1879*6236dae4SAndroid Build Coastguard Worker} 1880*6236dae4SAndroid Build Coastguard Worker 1881*6236dae4SAndroid Build Coastguard Workersub DELE_pop3 { 1882*6236dae4SAndroid Build Coastguard Worker my ($msgid) = @_; 1883*6236dae4SAndroid Build Coastguard Worker 1884*6236dae4SAndroid Build Coastguard Worker logmsg "DELE_pop3 got $msgid\n"; 1885*6236dae4SAndroid Build Coastguard Worker 1886*6236dae4SAndroid Build Coastguard Worker if (!$msgid) { 1887*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1888*6236dae4SAndroid Build Coastguard Worker } 1889*6236dae4SAndroid Build Coastguard Worker else { 1890*6236dae4SAndroid Build Coastguard Worker push (@deleted, $msgid); 1891*6236dae4SAndroid Build Coastguard Worker 1892*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK\r\n"; 1893*6236dae4SAndroid Build Coastguard Worker } 1894*6236dae4SAndroid Build Coastguard Worker 1895*6236dae4SAndroid Build Coastguard Worker return 0; 1896*6236dae4SAndroid Build Coastguard Worker} 1897*6236dae4SAndroid Build Coastguard Worker 1898*6236dae4SAndroid Build Coastguard Workersub STAT_pop3 { 1899*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1900*6236dae4SAndroid Build Coastguard Worker 1901*6236dae4SAndroid Build Coastguard Worker if ($args) { 1902*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1903*6236dae4SAndroid Build Coastguard Worker } 1904*6236dae4SAndroid Build Coastguard Worker else { 1905*6236dae4SAndroid Build Coastguard Worker # Send statistics for the built-in fake message list as 1906*6236dae4SAndroid Build Coastguard Worker # detailed in the LIST_pop3 function above 1907*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK 3 4294967800\r\n"; 1908*6236dae4SAndroid Build Coastguard Worker } 1909*6236dae4SAndroid Build Coastguard Worker 1910*6236dae4SAndroid Build Coastguard Worker return 0; 1911*6236dae4SAndroid Build Coastguard Worker} 1912*6236dae4SAndroid Build Coastguard Worker 1913*6236dae4SAndroid Build Coastguard Workersub NOOP_pop3 { 1914*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1915*6236dae4SAndroid Build Coastguard Worker 1916*6236dae4SAndroid Build Coastguard Worker if ($args) { 1917*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1918*6236dae4SAndroid Build Coastguard Worker } 1919*6236dae4SAndroid Build Coastguard Worker else { 1920*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK\r\n"; 1921*6236dae4SAndroid Build Coastguard Worker } 1922*6236dae4SAndroid Build Coastguard Worker 1923*6236dae4SAndroid Build Coastguard Worker return 0; 1924*6236dae4SAndroid Build Coastguard Worker} 1925*6236dae4SAndroid Build Coastguard Worker 1926*6236dae4SAndroid Build Coastguard Workersub UIDL_pop3 { 1927*6236dae4SAndroid Build Coastguard Worker # This is a built-in fake-message UID list 1928*6236dae4SAndroid Build Coastguard Worker my @data = ( 1929*6236dae4SAndroid Build Coastguard Worker "1 1\r\n", 1930*6236dae4SAndroid Build Coastguard Worker "2 2\r\n", 1931*6236dae4SAndroid Build Coastguard Worker "3 4\r\n", # Note that UID 3 is a simulated "deleted" message 1932*6236dae4SAndroid Build Coastguard Worker ); 1933*6236dae4SAndroid Build Coastguard Worker 1934*6236dae4SAndroid Build Coastguard Worker if (!grep /^UIDL$/, @capabilities) { 1935*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 1936*6236dae4SAndroid Build Coastguard Worker } 1937*6236dae4SAndroid Build Coastguard Worker else { 1938*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve a message UID list\n"; 1939*6236dae4SAndroid Build Coastguard Worker 1940*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Listing starts\r\n"; 1941*6236dae4SAndroid Build Coastguard Worker 1942*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1943*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1944*6236dae4SAndroid Build Coastguard Worker } 1945*6236dae4SAndroid Build Coastguard Worker 1946*6236dae4SAndroid Build Coastguard Worker # End with the magic 3-byte end of listing marker 1947*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1948*6236dae4SAndroid Build Coastguard Worker } 1949*6236dae4SAndroid Build Coastguard Worker 1950*6236dae4SAndroid Build Coastguard Worker return 0; 1951*6236dae4SAndroid Build Coastguard Worker} 1952*6236dae4SAndroid Build Coastguard Worker 1953*6236dae4SAndroid Build Coastguard Workersub TOP_pop3 { 1954*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1955*6236dae4SAndroid Build Coastguard Worker my ($msgid, $lines) = split(/ /, $args, 2); 1956*6236dae4SAndroid Build Coastguard Worker 1957*6236dae4SAndroid Build Coastguard Worker logmsg "TOP_pop3 got $args\n"; 1958*6236dae4SAndroid Build Coastguard Worker 1959*6236dae4SAndroid Build Coastguard Worker if (!grep /^TOP$/, @capabilities) { 1960*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 1961*6236dae4SAndroid Build Coastguard Worker } 1962*6236dae4SAndroid Build Coastguard Worker elsif (($msgid eq "") || ($lines eq "")) { 1963*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1964*6236dae4SAndroid Build Coastguard Worker } 1965*6236dae4SAndroid Build Coastguard Worker else { 1966*6236dae4SAndroid Build Coastguard Worker if ($lines == "0") { 1967*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve header of mail\n"; 1968*6236dae4SAndroid Build Coastguard Worker } 1969*6236dae4SAndroid Build Coastguard Worker else { 1970*6236dae4SAndroid Build Coastguard Worker logmsg "retrieve top $lines lines of mail\n"; 1971*6236dae4SAndroid Build Coastguard Worker } 1972*6236dae4SAndroid Build Coastguard Worker 1973*6236dae4SAndroid Build Coastguard Worker my @data = getreplydata($msgid); 1974*6236dae4SAndroid Build Coastguard Worker 1975*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK Mail transfer starts\r\n"; 1976*6236dae4SAndroid Build Coastguard Worker 1977*6236dae4SAndroid Build Coastguard Worker # Send mail content 1978*6236dae4SAndroid Build Coastguard Worker for my $d (@data) { 1979*6236dae4SAndroid Build Coastguard Worker sendcontrol $d; 1980*6236dae4SAndroid Build Coastguard Worker } 1981*6236dae4SAndroid Build Coastguard Worker 1982*6236dae4SAndroid Build Coastguard Worker # End with the magic 3-byte end of mail marker, assumes that the 1983*6236dae4SAndroid Build Coastguard Worker # mail body ends with a CRLF! 1984*6236dae4SAndroid Build Coastguard Worker sendcontrol ".\r\n"; 1985*6236dae4SAndroid Build Coastguard Worker } 1986*6236dae4SAndroid Build Coastguard Worker 1987*6236dae4SAndroid Build Coastguard Worker return 0; 1988*6236dae4SAndroid Build Coastguard Worker} 1989*6236dae4SAndroid Build Coastguard Worker 1990*6236dae4SAndroid Build Coastguard Workersub RSET_pop3 { 1991*6236dae4SAndroid Build Coastguard Worker my ($args) = @_; 1992*6236dae4SAndroid Build Coastguard Worker 1993*6236dae4SAndroid Build Coastguard Worker if ($args) { 1994*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Protocol error\r\n"; 1995*6236dae4SAndroid Build Coastguard Worker } 1996*6236dae4SAndroid Build Coastguard Worker else { 1997*6236dae4SAndroid Build Coastguard Worker if (@deleted) { 1998*6236dae4SAndroid Build Coastguard Worker logmsg "resetting @deleted message(s)\n"; 1999*6236dae4SAndroid Build Coastguard Worker 2000*6236dae4SAndroid Build Coastguard Worker @deleted = (); 2001*6236dae4SAndroid Build Coastguard Worker } 2002*6236dae4SAndroid Build Coastguard Worker 2003*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK\r\n"; 2004*6236dae4SAndroid Build Coastguard Worker } 2005*6236dae4SAndroid Build Coastguard Worker 2006*6236dae4SAndroid Build Coastguard Worker return 0; 2007*6236dae4SAndroid Build Coastguard Worker} 2008*6236dae4SAndroid Build Coastguard Worker 2009*6236dae4SAndroid Build Coastguard Workersub QUIT_pop3 { 2010*6236dae4SAndroid Build Coastguard Worker if(@deleted) { 2011*6236dae4SAndroid Build Coastguard Worker logmsg "deleting @deleted message(s)\n"; 2012*6236dae4SAndroid Build Coastguard Worker 2013*6236dae4SAndroid Build Coastguard Worker @deleted = (); 2014*6236dae4SAndroid Build Coastguard Worker } 2015*6236dae4SAndroid Build Coastguard Worker 2016*6236dae4SAndroid Build Coastguard Worker sendcontrol "+OK curl POP3 server signing off\r\n"; 2017*6236dae4SAndroid Build Coastguard Worker 2018*6236dae4SAndroid Build Coastguard Worker return 0; 2019*6236dae4SAndroid Build Coastguard Worker} 2020*6236dae4SAndroid Build Coastguard Worker 2021*6236dae4SAndroid Build Coastguard Worker################ 2022*6236dae4SAndroid Build Coastguard Worker################ FTP commands 2023*6236dae4SAndroid Build Coastguard Worker################ 2024*6236dae4SAndroid Build Coastguard Workermy $rest=0; 2025*6236dae4SAndroid Build Coastguard Workersub REST_ftp { 2026*6236dae4SAndroid Build Coastguard Worker $rest = $_[0]; 2027*6236dae4SAndroid Build Coastguard Worker logmsg "Set REST position to $rest\n" 2028*6236dae4SAndroid Build Coastguard Worker} 2029*6236dae4SAndroid Build Coastguard Worker 2030*6236dae4SAndroid Build Coastguard Workersub switch_directory_goto { 2031*6236dae4SAndroid Build Coastguard Worker my $target_dir = $_; 2032*6236dae4SAndroid Build Coastguard Worker 2033*6236dae4SAndroid Build Coastguard Worker if(!$ftptargetdir) { 2034*6236dae4SAndroid Build Coastguard Worker $ftptargetdir = "/"; 2035*6236dae4SAndroid Build Coastguard Worker } 2036*6236dae4SAndroid Build Coastguard Worker 2037*6236dae4SAndroid Build Coastguard Worker if($target_dir eq "") { 2038*6236dae4SAndroid Build Coastguard Worker $ftptargetdir = "/"; 2039*6236dae4SAndroid Build Coastguard Worker } 2040*6236dae4SAndroid Build Coastguard Worker elsif($target_dir eq "..") { 2041*6236dae4SAndroid Build Coastguard Worker if($ftptargetdir eq "/") { 2042*6236dae4SAndroid Build Coastguard Worker $ftptargetdir = "/"; 2043*6236dae4SAndroid Build Coastguard Worker } 2044*6236dae4SAndroid Build Coastguard Worker else { 2045*6236dae4SAndroid Build Coastguard Worker $ftptargetdir =~ s/[[:alnum:]]+\/$//; 2046*6236dae4SAndroid Build Coastguard Worker } 2047*6236dae4SAndroid Build Coastguard Worker } 2048*6236dae4SAndroid Build Coastguard Worker else { 2049*6236dae4SAndroid Build Coastguard Worker $ftptargetdir .= $target_dir . "/"; 2050*6236dae4SAndroid Build Coastguard Worker } 2051*6236dae4SAndroid Build Coastguard Worker} 2052*6236dae4SAndroid Build Coastguard Worker 2053*6236dae4SAndroid Build Coastguard Workersub switch_directory { 2054*6236dae4SAndroid Build Coastguard Worker my $target_dir = $_[0]; 2055*6236dae4SAndroid Build Coastguard Worker 2056*6236dae4SAndroid Build Coastguard Worker if($target_dir =~ /^test-(\d+)/) { 2057*6236dae4SAndroid Build Coastguard Worker $cwd_testno = $1; 2058*6236dae4SAndroid Build Coastguard Worker } 2059*6236dae4SAndroid Build Coastguard Worker elsif($target_dir eq "/") { 2060*6236dae4SAndroid Build Coastguard Worker $ftptargetdir = "/"; 2061*6236dae4SAndroid Build Coastguard Worker } 2062*6236dae4SAndroid Build Coastguard Worker else { 2063*6236dae4SAndroid Build Coastguard Worker my @dirs = split("/", $target_dir); 2064*6236dae4SAndroid Build Coastguard Worker for(@dirs) { 2065*6236dae4SAndroid Build Coastguard Worker switch_directory_goto($_); 2066*6236dae4SAndroid Build Coastguard Worker } 2067*6236dae4SAndroid Build Coastguard Worker } 2068*6236dae4SAndroid Build Coastguard Worker} 2069*6236dae4SAndroid Build Coastguard Worker 2070*6236dae4SAndroid Build Coastguard Workersub CWD_ftp { 2071*6236dae4SAndroid Build Coastguard Worker my ($folder, $fullcommand) = $_[0]; 2072*6236dae4SAndroid Build Coastguard Worker switch_directory($folder); 2073*6236dae4SAndroid Build Coastguard Worker if($ftptargetdir =~ /^\/fully_simulated/) { 2074*6236dae4SAndroid Build Coastguard Worker $ftplistparserstate = "enabled"; 2075*6236dae4SAndroid Build Coastguard Worker logmsg "enabled FTP list parser mode\n"; 2076*6236dae4SAndroid Build Coastguard Worker } 2077*6236dae4SAndroid Build Coastguard Worker else { 2078*6236dae4SAndroid Build Coastguard Worker undef $ftplistparserstate; 2079*6236dae4SAndroid Build Coastguard Worker } 2080*6236dae4SAndroid Build Coastguard Worker} 2081*6236dae4SAndroid Build Coastguard Worker 2082*6236dae4SAndroid Build Coastguard Workersub PWD_ftp { 2083*6236dae4SAndroid Build Coastguard Worker my $mydir; 2084*6236dae4SAndroid Build Coastguard Worker $mydir = $ftptargetdir ? $ftptargetdir : "/"; 2085*6236dae4SAndroid Build Coastguard Worker 2086*6236dae4SAndroid Build Coastguard Worker if($mydir ne "/") { 2087*6236dae4SAndroid Build Coastguard Worker $mydir =~ s/\/$//; 2088*6236dae4SAndroid Build Coastguard Worker } 2089*6236dae4SAndroid Build Coastguard Worker sendcontrol "257 \"$mydir\" is current directory\r\n"; 2090*6236dae4SAndroid Build Coastguard Worker} 2091*6236dae4SAndroid Build Coastguard Worker 2092*6236dae4SAndroid Build Coastguard Workersub LIST_ftp { 2093*6236dae4SAndroid Build Coastguard Worker # print "150 ASCII data connection for /bin/ls (193.15.23.1,59196) (0 bytes)\r\n"; 2094*6236dae4SAndroid Build Coastguard Worker 2095*6236dae4SAndroid Build Coastguard Worker if($datasockf_conn eq 'no') { 2096*6236dae4SAndroid Build Coastguard Worker if($nodataconn425) { 2097*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2098*6236dae4SAndroid Build Coastguard Worker sendcontrol "425 Can't open data connection\r\n"; 2099*6236dae4SAndroid Build Coastguard Worker } 2100*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn421) { 2101*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2102*6236dae4SAndroid Build Coastguard Worker sendcontrol "421 Connection timed out\r\n"; 2103*6236dae4SAndroid Build Coastguard Worker } 2104*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn150) { 2105*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2106*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2107*6236dae4SAndroid Build Coastguard Worker } 2108*6236dae4SAndroid Build Coastguard Worker else { 2109*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2110*6236dae4SAndroid Build Coastguard Worker } 2111*6236dae4SAndroid Build Coastguard Worker return 0; 2112*6236dae4SAndroid Build Coastguard Worker } 2113*6236dae4SAndroid Build Coastguard Worker 2114*6236dae4SAndroid Build Coastguard Worker logmsg "pass LIST data on data connection\n"; 2115*6236dae4SAndroid Build Coastguard Worker 2116*6236dae4SAndroid Build Coastguard Worker if($ftplistparserstate) { 2117*6236dae4SAndroid Build Coastguard Worker # provide a synthetic response 2118*6236dae4SAndroid Build Coastguard Worker my @ftpdir = ftp_contentlist($ftptargetdir); 2119*6236dae4SAndroid Build Coastguard Worker # old hard-coded style 2120*6236dae4SAndroid Build Coastguard Worker for(@ftpdir) { 2121*6236dae4SAndroid Build Coastguard Worker senddata $_; 2122*6236dae4SAndroid Build Coastguard Worker } 2123*6236dae4SAndroid Build Coastguard Worker } 2124*6236dae4SAndroid Build Coastguard Worker else { 2125*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "data"); 2126*6236dae4SAndroid Build Coastguard Worker for(@data) { 2127*6236dae4SAndroid Build Coastguard Worker my $send = $_; 2128*6236dae4SAndroid Build Coastguard Worker # convert all \n to \r\n for ASCII transfer 2129*6236dae4SAndroid Build Coastguard Worker $send =~ s/\r\n/\n/g; 2130*6236dae4SAndroid Build Coastguard Worker $send =~ s/\n/\r\n/g; 2131*6236dae4SAndroid Build Coastguard Worker logmsg "send $send as data\n"; 2132*6236dae4SAndroid Build Coastguard Worker senddata $send; 2133*6236dae4SAndroid Build Coastguard Worker } 2134*6236dae4SAndroid Build Coastguard Worker } 2135*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2136*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 ASCII transfer complete\r\n"; 2137*6236dae4SAndroid Build Coastguard Worker return 0; 2138*6236dae4SAndroid Build Coastguard Worker} 2139*6236dae4SAndroid Build Coastguard Worker 2140*6236dae4SAndroid Build Coastguard Workersub NLST_ftp { 2141*6236dae4SAndroid Build Coastguard Worker my @ftpdir=("file", "with space", "fake", "..", " ..", "funny", "README"); 2142*6236dae4SAndroid Build Coastguard Worker 2143*6236dae4SAndroid Build Coastguard Worker if($datasockf_conn eq 'no') { 2144*6236dae4SAndroid Build Coastguard Worker if($nodataconn425) { 2145*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2146*6236dae4SAndroid Build Coastguard Worker sendcontrol "425 Can't open data connection\r\n"; 2147*6236dae4SAndroid Build Coastguard Worker } 2148*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn421) { 2149*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2150*6236dae4SAndroid Build Coastguard Worker sendcontrol "421 Connection timed out\r\n"; 2151*6236dae4SAndroid Build Coastguard Worker } 2152*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn150) { 2153*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2154*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2155*6236dae4SAndroid Build Coastguard Worker } 2156*6236dae4SAndroid Build Coastguard Worker else { 2157*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2158*6236dae4SAndroid Build Coastguard Worker } 2159*6236dae4SAndroid Build Coastguard Worker return 0; 2160*6236dae4SAndroid Build Coastguard Worker } 2161*6236dae4SAndroid Build Coastguard Worker 2162*6236dae4SAndroid Build Coastguard Worker logmsg "pass NLST data on data connection\n"; 2163*6236dae4SAndroid Build Coastguard Worker for(@ftpdir) { 2164*6236dae4SAndroid Build Coastguard Worker senddata "$_\r\n"; 2165*6236dae4SAndroid Build Coastguard Worker } 2166*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2167*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 ASCII transfer complete\r\n"; 2168*6236dae4SAndroid Build Coastguard Worker return 0; 2169*6236dae4SAndroid Build Coastguard Worker} 2170*6236dae4SAndroid Build Coastguard Worker 2171*6236dae4SAndroid Build Coastguard Workersub MDTM_ftp { 2172*6236dae4SAndroid Build Coastguard Worker my $testno = $_[0]; 2173*6236dae4SAndroid Build Coastguard Worker my $testpart = ""; 2174*6236dae4SAndroid Build Coastguard Worker if ($testno > 10000) { 2175*6236dae4SAndroid Build Coastguard Worker $testpart = $testno % 10000; 2176*6236dae4SAndroid Build Coastguard Worker $testno = int($testno / 10000); 2177*6236dae4SAndroid Build Coastguard Worker } 2178*6236dae4SAndroid Build Coastguard Worker 2179*6236dae4SAndroid Build Coastguard Worker loadtest("$logdir/test$testno"); 2180*6236dae4SAndroid Build Coastguard Worker 2181*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "mdtm"); 2182*6236dae4SAndroid Build Coastguard Worker 2183*6236dae4SAndroid Build Coastguard Worker my $reply = $data[0]; 2184*6236dae4SAndroid Build Coastguard Worker chomp $reply if($reply); 2185*6236dae4SAndroid Build Coastguard Worker 2186*6236dae4SAndroid Build Coastguard Worker if($reply && ($reply =~ /^[+-]?\d+$/) && ($reply < 0)) { 2187*6236dae4SAndroid Build Coastguard Worker sendcontrol "550 $testno: no such file.\r\n"; 2188*6236dae4SAndroid Build Coastguard Worker } 2189*6236dae4SAndroid Build Coastguard Worker elsif($reply) { 2190*6236dae4SAndroid Build Coastguard Worker sendcontrol "$reply\r\n"; 2191*6236dae4SAndroid Build Coastguard Worker } 2192*6236dae4SAndroid Build Coastguard Worker else { 2193*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 MDTM: no such command.\r\n"; 2194*6236dae4SAndroid Build Coastguard Worker } 2195*6236dae4SAndroid Build Coastguard Worker return 0; 2196*6236dae4SAndroid Build Coastguard Worker} 2197*6236dae4SAndroid Build Coastguard Worker 2198*6236dae4SAndroid Build Coastguard Workersub SIZE_ftp { 2199*6236dae4SAndroid Build Coastguard Worker my $testno = $_[0]; 2200*6236dae4SAndroid Build Coastguard Worker 2201*6236dae4SAndroid Build Coastguard Worker if($ftplistparserstate) { 2202*6236dae4SAndroid Build Coastguard Worker my $size = wildcard_filesize($ftptargetdir, $testno); 2203*6236dae4SAndroid Build Coastguard Worker if($size == -1) { 2204*6236dae4SAndroid Build Coastguard Worker sendcontrol "550 $testno: No such file or directory.\r\n"; 2205*6236dae4SAndroid Build Coastguard Worker } 2206*6236dae4SAndroid Build Coastguard Worker else { 2207*6236dae4SAndroid Build Coastguard Worker sendcontrol "213 $size\r\n"; 2208*6236dae4SAndroid Build Coastguard Worker } 2209*6236dae4SAndroid Build Coastguard Worker return 0; 2210*6236dae4SAndroid Build Coastguard Worker } 2211*6236dae4SAndroid Build Coastguard Worker 2212*6236dae4SAndroid Build Coastguard Worker if($testno =~ /^verifiedserver$/) { 2213*6236dae4SAndroid Build Coastguard Worker my $response = "WE ROOLZ: $$\r\n"; 2214*6236dae4SAndroid Build Coastguard Worker my $size = length($response); 2215*6236dae4SAndroid Build Coastguard Worker sendcontrol "213 $size\r\n"; 2216*6236dae4SAndroid Build Coastguard Worker return 0; 2217*6236dae4SAndroid Build Coastguard Worker } 2218*6236dae4SAndroid Build Coastguard Worker 2219*6236dae4SAndroid Build Coastguard Worker if($testno =~ /(\d+)\/?$/) { 2220*6236dae4SAndroid Build Coastguard Worker $testno = $1; 2221*6236dae4SAndroid Build Coastguard Worker } 2222*6236dae4SAndroid Build Coastguard Worker else { 2223*6236dae4SAndroid Build Coastguard Worker print STDERR "SIZE_ftp: invalid test number: $testno\n"; 2224*6236dae4SAndroid Build Coastguard Worker return 1; 2225*6236dae4SAndroid Build Coastguard Worker } 2226*6236dae4SAndroid Build Coastguard Worker 2227*6236dae4SAndroid Build Coastguard Worker my $testpart = ""; 2228*6236dae4SAndroid Build Coastguard Worker if($testno > 10000) { 2229*6236dae4SAndroid Build Coastguard Worker $testpart = $testno % 10000; 2230*6236dae4SAndroid Build Coastguard Worker $testno = int($testno / 10000); 2231*6236dae4SAndroid Build Coastguard Worker } 2232*6236dae4SAndroid Build Coastguard Worker 2233*6236dae4SAndroid Build Coastguard Worker loadtest("$logdir/test$testno"); 2234*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "size"); 2235*6236dae4SAndroid Build Coastguard Worker 2236*6236dae4SAndroid Build Coastguard Worker my $size = $data[0]; 2237*6236dae4SAndroid Build Coastguard Worker 2238*6236dae4SAndroid Build Coastguard Worker if($size) { 2239*6236dae4SAndroid Build Coastguard Worker $size += 0; # make it a number 2240*6236dae4SAndroid Build Coastguard Worker if($size > -1) { 2241*6236dae4SAndroid Build Coastguard Worker sendcontrol "213 $size\r\n"; 2242*6236dae4SAndroid Build Coastguard Worker } 2243*6236dae4SAndroid Build Coastguard Worker else { 2244*6236dae4SAndroid Build Coastguard Worker sendcontrol "550 $testno: No such file or directory.\r\n"; 2245*6236dae4SAndroid Build Coastguard Worker } 2246*6236dae4SAndroid Build Coastguard Worker } 2247*6236dae4SAndroid Build Coastguard Worker else { 2248*6236dae4SAndroid Build Coastguard Worker $size=0; 2249*6236dae4SAndroid Build Coastguard Worker @data = getpart("reply", "data$testpart"); 2250*6236dae4SAndroid Build Coastguard Worker for(@data) { 2251*6236dae4SAndroid Build Coastguard Worker $size += length($_); 2252*6236dae4SAndroid Build Coastguard Worker } 2253*6236dae4SAndroid Build Coastguard Worker if($size) { 2254*6236dae4SAndroid Build Coastguard Worker sendcontrol "213 $size\r\n"; 2255*6236dae4SAndroid Build Coastguard Worker } 2256*6236dae4SAndroid Build Coastguard Worker else { 2257*6236dae4SAndroid Build Coastguard Worker sendcontrol "550 $testno: No such file or directory.\r\n"; 2258*6236dae4SAndroid Build Coastguard Worker } 2259*6236dae4SAndroid Build Coastguard Worker } 2260*6236dae4SAndroid Build Coastguard Worker return 0; 2261*6236dae4SAndroid Build Coastguard Worker} 2262*6236dae4SAndroid Build Coastguard Worker 2263*6236dae4SAndroid Build Coastguard Workersub RETR_ftp { 2264*6236dae4SAndroid Build Coastguard Worker my ($testno) = @_; 2265*6236dae4SAndroid Build Coastguard Worker 2266*6236dae4SAndroid Build Coastguard Worker if($datasockf_conn eq 'no') { 2267*6236dae4SAndroid Build Coastguard Worker if($nodataconn425) { 2268*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2269*6236dae4SAndroid Build Coastguard Worker sendcontrol "425 Can't open data connection\r\n"; 2270*6236dae4SAndroid Build Coastguard Worker } 2271*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn421) { 2272*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2273*6236dae4SAndroid Build Coastguard Worker sendcontrol "421 Connection timed out\r\n"; 2274*6236dae4SAndroid Build Coastguard Worker } 2275*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn150) { 2276*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2277*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2278*6236dae4SAndroid Build Coastguard Worker } 2279*6236dae4SAndroid Build Coastguard Worker else { 2280*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2281*6236dae4SAndroid Build Coastguard Worker } 2282*6236dae4SAndroid Build Coastguard Worker return 0; 2283*6236dae4SAndroid Build Coastguard Worker } 2284*6236dae4SAndroid Build Coastguard Worker 2285*6236dae4SAndroid Build Coastguard Worker if($ftplistparserstate) { 2286*6236dae4SAndroid Build Coastguard Worker my @content = wildcard_getfile($ftptargetdir, $testno); 2287*6236dae4SAndroid Build Coastguard Worker if($content[0] == -1) { 2288*6236dae4SAndroid Build Coastguard Worker #file not found 2289*6236dae4SAndroid Build Coastguard Worker } 2290*6236dae4SAndroid Build Coastguard Worker else { 2291*6236dae4SAndroid Build Coastguard Worker my $size = length $content[1]; 2292*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Binary data connection for $testno ($size bytes).\r\n", 2293*6236dae4SAndroid Build Coastguard Worker senddata $content[1]; 2294*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2295*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 File transfer complete\r\n"; 2296*6236dae4SAndroid Build Coastguard Worker } 2297*6236dae4SAndroid Build Coastguard Worker return 0; 2298*6236dae4SAndroid Build Coastguard Worker } 2299*6236dae4SAndroid Build Coastguard Worker 2300*6236dae4SAndroid Build Coastguard Worker if($testno =~ /^verifiedserver$/) { 2301*6236dae4SAndroid Build Coastguard Worker # this is the secret command that verifies that this actually is 2302*6236dae4SAndroid Build Coastguard Worker # the curl test server 2303*6236dae4SAndroid Build Coastguard Worker my $response = "WE ROOLZ: $$\r\n"; 2304*6236dae4SAndroid Build Coastguard Worker my $len = length($response); 2305*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Binary junk ($len bytes).\r\n"; 2306*6236dae4SAndroid Build Coastguard Worker senddata "WE ROOLZ: $$\r\n"; 2307*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2308*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 File transfer complete\r\n"; 2309*6236dae4SAndroid Build Coastguard Worker if($verbose) { 2310*6236dae4SAndroid Build Coastguard Worker print STDERR "FTPD: We returned proof we are the test server\n"; 2311*6236dae4SAndroid Build Coastguard Worker } 2312*6236dae4SAndroid Build Coastguard Worker return 0; 2313*6236dae4SAndroid Build Coastguard Worker } 2314*6236dae4SAndroid Build Coastguard Worker 2315*6236dae4SAndroid Build Coastguard Worker $testno =~ s/^([^0-9]*)//; 2316*6236dae4SAndroid Build Coastguard Worker my $testpart = ""; 2317*6236dae4SAndroid Build Coastguard Worker if ($testno > 10000) { 2318*6236dae4SAndroid Build Coastguard Worker $testpart = $testno % 10000; 2319*6236dae4SAndroid Build Coastguard Worker $testno = int($testno / 10000); 2320*6236dae4SAndroid Build Coastguard Worker } 2321*6236dae4SAndroid Build Coastguard Worker 2322*6236dae4SAndroid Build Coastguard Worker loadtest("$logdir/test$testno"); 2323*6236dae4SAndroid Build Coastguard Worker 2324*6236dae4SAndroid Build Coastguard Worker my @data = getpart("reply", "data$testpart"); 2325*6236dae4SAndroid Build Coastguard Worker 2326*6236dae4SAndroid Build Coastguard Worker my $size=0; 2327*6236dae4SAndroid Build Coastguard Worker for(@data) { 2328*6236dae4SAndroid Build Coastguard Worker $size += length($_); 2329*6236dae4SAndroid Build Coastguard Worker } 2330*6236dae4SAndroid Build Coastguard Worker 2331*6236dae4SAndroid Build Coastguard Worker my %hash = getpartattr("reply", "data$testpart"); 2332*6236dae4SAndroid Build Coastguard Worker 2333*6236dae4SAndroid Build Coastguard Worker if($size || $hash{'sendzero'}) { 2334*6236dae4SAndroid Build Coastguard Worker 2335*6236dae4SAndroid Build Coastguard Worker if($rest) { 2336*6236dae4SAndroid Build Coastguard Worker # move read pointer forward 2337*6236dae4SAndroid Build Coastguard Worker $size -= $rest; 2338*6236dae4SAndroid Build Coastguard Worker logmsg "REST $rest was removed from size, makes $size left\n"; 2339*6236dae4SAndroid Build Coastguard Worker $rest = 0; # reset REST offset again 2340*6236dae4SAndroid Build Coastguard Worker } 2341*6236dae4SAndroid Build Coastguard Worker if($retrweirdo) { 2342*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Binary data connection for $testno () ($size bytes).\r\n", 2343*6236dae4SAndroid Build Coastguard Worker "226 File transfer complete\r\n"; 2344*6236dae4SAndroid Build Coastguard Worker 2345*6236dae4SAndroid Build Coastguard Worker for(@data) { 2346*6236dae4SAndroid Build Coastguard Worker my $send = $_; 2347*6236dae4SAndroid Build Coastguard Worker senddata $send; 2348*6236dae4SAndroid Build Coastguard Worker } 2349*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2350*6236dae4SAndroid Build Coastguard Worker $retrweirdo=0; # switch off the weirdo again! 2351*6236dae4SAndroid Build Coastguard Worker } 2352*6236dae4SAndroid Build Coastguard Worker else { 2353*6236dae4SAndroid Build Coastguard Worker my $sz = "($size bytes)"; 2354*6236dae4SAndroid Build Coastguard Worker if($retrnosize) { 2355*6236dae4SAndroid Build Coastguard Worker $sz = "size?"; 2356*6236dae4SAndroid Build Coastguard Worker } 2357*6236dae4SAndroid Build Coastguard Worker elsif($retrsize > 0) { 2358*6236dae4SAndroid Build Coastguard Worker $sz = "($retrsize bytes)"; 2359*6236dae4SAndroid Build Coastguard Worker } 2360*6236dae4SAndroid Build Coastguard Worker 2361*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Binary data connection for $testno ($testpart) $sz.\r\n"; 2362*6236dae4SAndroid Build Coastguard Worker 2363*6236dae4SAndroid Build Coastguard Worker for(@data) { 2364*6236dae4SAndroid Build Coastguard Worker my $send = $_; 2365*6236dae4SAndroid Build Coastguard Worker senddata $send; 2366*6236dae4SAndroid Build Coastguard Worker } 2367*6236dae4SAndroid Build Coastguard Worker close_dataconn(0); 2368*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 File transfer complete\r\n"; 2369*6236dae4SAndroid Build Coastguard Worker } 2370*6236dae4SAndroid Build Coastguard Worker } 2371*6236dae4SAndroid Build Coastguard Worker else { 2372*6236dae4SAndroid Build Coastguard Worker sendcontrol "550 $testno: No such file or directory.\r\n"; 2373*6236dae4SAndroid Build Coastguard Worker } 2374*6236dae4SAndroid Build Coastguard Worker return 0; 2375*6236dae4SAndroid Build Coastguard Worker} 2376*6236dae4SAndroid Build Coastguard Worker 2377*6236dae4SAndroid Build Coastguard Workersub STOR_ftp { 2378*6236dae4SAndroid Build Coastguard Worker my $testno=$_[0]; 2379*6236dae4SAndroid Build Coastguard Worker 2380*6236dae4SAndroid Build Coastguard Worker my $filename = "$logdir/upload.$testno"; 2381*6236dae4SAndroid Build Coastguard Worker 2382*6236dae4SAndroid Build Coastguard Worker if($datasockf_conn eq 'no') { 2383*6236dae4SAndroid Build Coastguard Worker if($nodataconn425) { 2384*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2385*6236dae4SAndroid Build Coastguard Worker sendcontrol "425 Can't open data connection\r\n"; 2386*6236dae4SAndroid Build Coastguard Worker } 2387*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn421) { 2388*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2389*6236dae4SAndroid Build Coastguard Worker sendcontrol "421 Connection timed out\r\n"; 2390*6236dae4SAndroid Build Coastguard Worker } 2391*6236dae4SAndroid Build Coastguard Worker elsif($nodataconn150) { 2392*6236dae4SAndroid Build Coastguard Worker sendcontrol "150 Opening data connection\r\n"; 2393*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2394*6236dae4SAndroid Build Coastguard Worker } 2395*6236dae4SAndroid Build Coastguard Worker else { 2396*6236dae4SAndroid Build Coastguard Worker # client shall timeout 2397*6236dae4SAndroid Build Coastguard Worker } 2398*6236dae4SAndroid Build Coastguard Worker return 0; 2399*6236dae4SAndroid Build Coastguard Worker } 2400*6236dae4SAndroid Build Coastguard Worker 2401*6236dae4SAndroid Build Coastguard Worker logmsg "STOR test number $testno in $filename\n"; 2402*6236dae4SAndroid Build Coastguard Worker 2403*6236dae4SAndroid Build Coastguard Worker sendcontrol "125 Gimme gimme gimme!\r\n"; 2404*6236dae4SAndroid Build Coastguard Worker 2405*6236dae4SAndroid Build Coastguard Worker open(my $file, ">", "$filename") || 2406*6236dae4SAndroid Build Coastguard Worker return 0; # failed to open output 2407*6236dae4SAndroid Build Coastguard Worker 2408*6236dae4SAndroid Build Coastguard Worker my $line; 2409*6236dae4SAndroid Build Coastguard Worker my $ulsize=0; 2410*6236dae4SAndroid Build Coastguard Worker my $disc=0; 2411*6236dae4SAndroid Build Coastguard Worker while (5 == (sysread DREAD, $line, 5)) { 2412*6236dae4SAndroid Build Coastguard Worker if($line eq "DATA\n") { 2413*6236dae4SAndroid Build Coastguard Worker my $i; 2414*6236dae4SAndroid Build Coastguard Worker sysread DREAD, $i, 5; 2415*6236dae4SAndroid Build Coastguard Worker 2416*6236dae4SAndroid Build Coastguard Worker my $size = 0; 2417*6236dae4SAndroid Build Coastguard Worker if($i =~ /^([0-9a-fA-F]{4})\n/) { 2418*6236dae4SAndroid Build Coastguard Worker $size = hex($1); 2419*6236dae4SAndroid Build Coastguard Worker } 2420*6236dae4SAndroid Build Coastguard Worker 2421*6236dae4SAndroid Build Coastguard Worker read_datasockf(\$line, $size); 2422*6236dae4SAndroid Build Coastguard Worker 2423*6236dae4SAndroid Build Coastguard Worker #print STDERR " GOT: $size bytes\n"; 2424*6236dae4SAndroid Build Coastguard Worker 2425*6236dae4SAndroid Build Coastguard Worker $ulsize += $size; 2426*6236dae4SAndroid Build Coastguard Worker print $file $line if(!$nosave); 2427*6236dae4SAndroid Build Coastguard Worker logmsg "> Appending $size bytes to file\n"; 2428*6236dae4SAndroid Build Coastguard Worker } 2429*6236dae4SAndroid Build Coastguard Worker elsif($line eq "DISC\n") { 2430*6236dae4SAndroid Build Coastguard Worker # disconnect! 2431*6236dae4SAndroid Build Coastguard Worker $disc=1; 2432*6236dae4SAndroid Build Coastguard Worker printf DWRITE "ACKD\n"; 2433*6236dae4SAndroid Build Coastguard Worker last; 2434*6236dae4SAndroid Build Coastguard Worker } 2435*6236dae4SAndroid Build Coastguard Worker else { 2436*6236dae4SAndroid Build Coastguard Worker logmsg "No support for: $line"; 2437*6236dae4SAndroid Build Coastguard Worker last; 2438*6236dae4SAndroid Build Coastguard Worker } 2439*6236dae4SAndroid Build Coastguard Worker if($storeresp) { 2440*6236dae4SAndroid Build Coastguard Worker # abort early 2441*6236dae4SAndroid Build Coastguard Worker last; 2442*6236dae4SAndroid Build Coastguard Worker } 2443*6236dae4SAndroid Build Coastguard Worker } 2444*6236dae4SAndroid Build Coastguard Worker if($nosave) { 2445*6236dae4SAndroid Build Coastguard Worker print $file "$ulsize bytes would've been stored here\n"; 2446*6236dae4SAndroid Build Coastguard Worker } 2447*6236dae4SAndroid Build Coastguard Worker close($file); 2448*6236dae4SAndroid Build Coastguard Worker close_dataconn($disc); 2449*6236dae4SAndroid Build Coastguard Worker logmsg "received $ulsize bytes upload\n"; 2450*6236dae4SAndroid Build Coastguard Worker if($storeresp) { 2451*6236dae4SAndroid Build Coastguard Worker sendcontrol "$storeresp\r\n"; 2452*6236dae4SAndroid Build Coastguard Worker } 2453*6236dae4SAndroid Build Coastguard Worker else { 2454*6236dae4SAndroid Build Coastguard Worker sendcontrol "226 File transfer complete\r\n"; 2455*6236dae4SAndroid Build Coastguard Worker } 2456*6236dae4SAndroid Build Coastguard Worker return 0; 2457*6236dae4SAndroid Build Coastguard Worker} 2458*6236dae4SAndroid Build Coastguard Worker 2459*6236dae4SAndroid Build Coastguard Workersub PASV_ftp { 2460*6236dae4SAndroid Build Coastguard Worker my ($arg, $cmd)=@_; 2461*6236dae4SAndroid Build Coastguard Worker my $pasvport; 2462*6236dae4SAndroid Build Coastguard Worker 2463*6236dae4SAndroid Build Coastguard Worker # kill previous data connection sockfilt when alive 2464*6236dae4SAndroid Build Coastguard Worker if($datasockf_runs eq 'yes') { 2465*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2466*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel killed\n"; 2467*6236dae4SAndroid Build Coastguard Worker } 2468*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2469*6236dae4SAndroid Build Coastguard Worker 2470*6236dae4SAndroid Build Coastguard Worker logmsg "====> Passive DATA channel requested by client\n"; 2471*6236dae4SAndroid Build Coastguard Worker 2472*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel starting...\n"; 2473*6236dae4SAndroid Build Coastguard Worker 2474*6236dae4SAndroid Build Coastguard Worker # We fire up a new sockfilt to do the data transfer for us. 2475*6236dae4SAndroid Build Coastguard Worker my @datasockfcmd = ("./server/sockfilt".exe_ext('SRV'), 2476*6236dae4SAndroid Build Coastguard Worker "--ipv$ipvnum", "--port", 0, 2477*6236dae4SAndroid Build Coastguard Worker "--pidfile", $datasockf_pidfile, 2478*6236dae4SAndroid Build Coastguard Worker "--logfile", $datasockf_logfile); 2479*6236dae4SAndroid Build Coastguard Worker if($nodataconn) { 2480*6236dae4SAndroid Build Coastguard Worker push(@datasockfcmd, '--bindonly'); 2481*6236dae4SAndroid Build Coastguard Worker } 2482*6236dae4SAndroid Build Coastguard Worker $slavepid = open2(\*DREAD, \*DWRITE, @datasockfcmd); 2483*6236dae4SAndroid Build Coastguard Worker 2484*6236dae4SAndroid Build Coastguard Worker if($nodataconn) { 2485*6236dae4SAndroid Build Coastguard Worker datasockf_state('PASSIVE_NODATACONN'); 2486*6236dae4SAndroid Build Coastguard Worker } 2487*6236dae4SAndroid Build Coastguard Worker else { 2488*6236dae4SAndroid Build Coastguard Worker datasockf_state('PASSIVE'); 2489*6236dae4SAndroid Build Coastguard Worker } 2490*6236dae4SAndroid Build Coastguard Worker 2491*6236dae4SAndroid Build Coastguard Worker print STDERR "@datasockfcmd\n" if($verbose); 2492*6236dae4SAndroid Build Coastguard Worker 2493*6236dae4SAndroid Build Coastguard Worker print DWRITE "PING\n"; 2494*6236dae4SAndroid Build Coastguard Worker my $pong; 2495*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*DREAD, \$pong, 5); 2496*6236dae4SAndroid Build Coastguard Worker 2497*6236dae4SAndroid Build Coastguard Worker if($pong =~ /^FAIL/) { 2498*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt said: FAIL\n"; 2499*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel failed\n"; 2500*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2501*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2502*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 no free ports!\r\n"; 2503*6236dae4SAndroid Build Coastguard Worker return; 2504*6236dae4SAndroid Build Coastguard Worker } 2505*6236dae4SAndroid Build Coastguard Worker elsif($pong !~ /^PONG/) { 2506*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt unexpected response: $pong\n"; 2507*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel failed\n"; 2508*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt killed now\n"; 2509*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2510*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2511*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2512*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 no free ports!\r\n"; 2513*6236dae4SAndroid Build Coastguard Worker return; 2514*6236dae4SAndroid Build Coastguard Worker } 2515*6236dae4SAndroid Build Coastguard Worker 2516*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel started (pid $slavepid)\n"; 2517*6236dae4SAndroid Build Coastguard Worker 2518*6236dae4SAndroid Build Coastguard Worker # Find out on what port we listen on or have bound 2519*6236dae4SAndroid Build Coastguard Worker my $i; 2520*6236dae4SAndroid Build Coastguard Worker print DWRITE "PORT\n"; 2521*6236dae4SAndroid Build Coastguard Worker 2522*6236dae4SAndroid Build Coastguard Worker # READ the response code 2523*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*DREAD, \$i, 5); 2524*6236dae4SAndroid Build Coastguard Worker 2525*6236dae4SAndroid Build Coastguard Worker # READ the response size 2526*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*DREAD, \$i, 5); 2527*6236dae4SAndroid Build Coastguard Worker 2528*6236dae4SAndroid Build Coastguard Worker my $size = 0; 2529*6236dae4SAndroid Build Coastguard Worker if($i =~ /^([0-9a-fA-F]{4})\n/) { 2530*6236dae4SAndroid Build Coastguard Worker $size = hex($1); 2531*6236dae4SAndroid Build Coastguard Worker } 2532*6236dae4SAndroid Build Coastguard Worker 2533*6236dae4SAndroid Build Coastguard Worker # READ the response data 2534*6236dae4SAndroid Build Coastguard Worker read_datasockf(\$i, $size); 2535*6236dae4SAndroid Build Coastguard Worker 2536*6236dae4SAndroid Build Coastguard Worker # The data is in the format 2537*6236dae4SAndroid Build Coastguard Worker # IPvX/NNN 2538*6236dae4SAndroid Build Coastguard Worker 2539*6236dae4SAndroid Build Coastguard Worker if($i =~ /IPv(\d)\/(\d+)/) { 2540*6236dae4SAndroid Build Coastguard Worker # FIX: deal with IP protocol version 2541*6236dae4SAndroid Build Coastguard Worker $pasvport = $2; 2542*6236dae4SAndroid Build Coastguard Worker } 2543*6236dae4SAndroid Build Coastguard Worker 2544*6236dae4SAndroid Build Coastguard Worker if(!$pasvport) { 2545*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt unknown listener port\n"; 2546*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel failed\n"; 2547*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt killed now\n"; 2548*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2549*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2550*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2551*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 no free ports!\r\n"; 2552*6236dae4SAndroid Build Coastguard Worker return; 2553*6236dae4SAndroid Build Coastguard Worker } 2554*6236dae4SAndroid Build Coastguard Worker 2555*6236dae4SAndroid Build Coastguard Worker if($nodataconn) { 2556*6236dae4SAndroid Build Coastguard Worker my $str = nodataconn_str(); 2557*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel ($str) bound on port ". 2558*6236dae4SAndroid Build Coastguard Worker "$pasvport\n"; 2559*6236dae4SAndroid Build Coastguard Worker } 2560*6236dae4SAndroid Build Coastguard Worker else { 2561*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for passive data channel listens on port ". 2562*6236dae4SAndroid Build Coastguard Worker "$pasvport\n"; 2563*6236dae4SAndroid Build Coastguard Worker } 2564*6236dae4SAndroid Build Coastguard Worker 2565*6236dae4SAndroid Build Coastguard Worker if($cmd ne "EPSV") { 2566*6236dae4SAndroid Build Coastguard Worker # PASV reply 2567*6236dae4SAndroid Build Coastguard Worker my $p=$listenaddr; 2568*6236dae4SAndroid Build Coastguard Worker $p =~ s/\./,/g; 2569*6236dae4SAndroid Build Coastguard Worker if($pasvbadip) { 2570*6236dae4SAndroid Build Coastguard Worker $p="1,2,3,4"; 2571*6236dae4SAndroid Build Coastguard Worker } 2572*6236dae4SAndroid Build Coastguard Worker sendcontrol sprintf("227 Entering Passive Mode ($p,%d,%d)\n", 2573*6236dae4SAndroid Build Coastguard Worker int($pasvport/256), int($pasvport%256)); 2574*6236dae4SAndroid Build Coastguard Worker } 2575*6236dae4SAndroid Build Coastguard Worker else { 2576*6236dae4SAndroid Build Coastguard Worker # EPSV reply 2577*6236dae4SAndroid Build Coastguard Worker sendcontrol sprintf("229 Entering Passive Mode (|||%d|)\n", $pasvport); 2578*6236dae4SAndroid Build Coastguard Worker } 2579*6236dae4SAndroid Build Coastguard Worker 2580*6236dae4SAndroid Build Coastguard Worker logmsg "Client has been notified that DATA conn ". 2581*6236dae4SAndroid Build Coastguard Worker "will be accepted on port $pasvport\n"; 2582*6236dae4SAndroid Build Coastguard Worker 2583*6236dae4SAndroid Build Coastguard Worker if($nodataconn) { 2584*6236dae4SAndroid Build Coastguard Worker my $str = nodataconn_str(); 2585*6236dae4SAndroid Build Coastguard Worker logmsg "====> Client fooled ($str)\n"; 2586*6236dae4SAndroid Build Coastguard Worker return; 2587*6236dae4SAndroid Build Coastguard Worker } 2588*6236dae4SAndroid Build Coastguard Worker 2589*6236dae4SAndroid Build Coastguard Worker eval { 2590*6236dae4SAndroid Build Coastguard Worker local $SIG{ALRM} = sub { die "alarm\n" }; 2591*6236dae4SAndroid Build Coastguard Worker 2592*6236dae4SAndroid Build Coastguard Worker # assume swift operations unless explicitly slow 2593*6236dae4SAndroid Build Coastguard Worker alarm ($datadelay?20:2); 2594*6236dae4SAndroid Build Coastguard Worker 2595*6236dae4SAndroid Build Coastguard Worker # Wait for 'CNCT' 2596*6236dae4SAndroid Build Coastguard Worker my $input; 2597*6236dae4SAndroid Build Coastguard Worker 2598*6236dae4SAndroid Build Coastguard Worker # FIX: Monitor ctrl conn for disconnect 2599*6236dae4SAndroid Build Coastguard Worker 2600*6236dae4SAndroid Build Coastguard Worker while(sysread(DREAD, $input, 5)) { 2601*6236dae4SAndroid Build Coastguard Worker 2602*6236dae4SAndroid Build Coastguard Worker if($input !~ /^CNCT/) { 2603*6236dae4SAndroid Build Coastguard Worker # we wait for a connected client 2604*6236dae4SAndroid Build Coastguard Worker logmsg "Odd, we got $input from client\n"; 2605*6236dae4SAndroid Build Coastguard Worker next; 2606*6236dae4SAndroid Build Coastguard Worker } 2607*6236dae4SAndroid Build Coastguard Worker logmsg "Client connects to port $pasvport\n"; 2608*6236dae4SAndroid Build Coastguard Worker last; 2609*6236dae4SAndroid Build Coastguard Worker } 2610*6236dae4SAndroid Build Coastguard Worker alarm 0; 2611*6236dae4SAndroid Build Coastguard Worker }; 2612*6236dae4SAndroid Build Coastguard Worker if ($@) { 2613*6236dae4SAndroid Build Coastguard Worker # timed out 2614*6236dae4SAndroid Build Coastguard Worker logmsg "$srvrname server timed out awaiting data connection ". 2615*6236dae4SAndroid Build Coastguard Worker "on port $pasvport\n"; 2616*6236dae4SAndroid Build Coastguard Worker logmsg "accept failed or connection not even attempted\n"; 2617*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt killed now\n"; 2618*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2619*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2620*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2621*6236dae4SAndroid Build Coastguard Worker return; 2622*6236dae4SAndroid Build Coastguard Worker } 2623*6236dae4SAndroid Build Coastguard Worker else { 2624*6236dae4SAndroid Build Coastguard Worker logmsg "====> Client established passive DATA connection ". 2625*6236dae4SAndroid Build Coastguard Worker "on port $pasvport\n"; 2626*6236dae4SAndroid Build Coastguard Worker } 2627*6236dae4SAndroid Build Coastguard Worker 2628*6236dae4SAndroid Build Coastguard Worker return; 2629*6236dae4SAndroid Build Coastguard Worker} 2630*6236dae4SAndroid Build Coastguard Worker 2631*6236dae4SAndroid Build Coastguard Worker# 2632*6236dae4SAndroid Build Coastguard Worker# Support both PORT and EPRT here. 2633*6236dae4SAndroid Build Coastguard Worker# 2634*6236dae4SAndroid Build Coastguard Worker 2635*6236dae4SAndroid Build Coastguard Workersub PORT_ftp { 2636*6236dae4SAndroid Build Coastguard Worker my ($arg, $cmd) = @_; 2637*6236dae4SAndroid Build Coastguard Worker my $port; 2638*6236dae4SAndroid Build Coastguard Worker my $addr; 2639*6236dae4SAndroid Build Coastguard Worker 2640*6236dae4SAndroid Build Coastguard Worker # kill previous data connection sockfilt when alive 2641*6236dae4SAndroid Build Coastguard Worker if($datasockf_runs eq 'yes') { 2642*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2643*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel killed\n"; 2644*6236dae4SAndroid Build Coastguard Worker } 2645*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2646*6236dae4SAndroid Build Coastguard Worker 2647*6236dae4SAndroid Build Coastguard Worker logmsg "====> Active DATA channel requested by client\n"; 2648*6236dae4SAndroid Build Coastguard Worker 2649*6236dae4SAndroid Build Coastguard Worker # We always ignore the given IP and use localhost. 2650*6236dae4SAndroid Build Coastguard Worker 2651*6236dae4SAndroid Build Coastguard Worker if($cmd eq "PORT") { 2652*6236dae4SAndroid Build Coastguard Worker if($arg !~ /(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)/) { 2653*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel not started ". 2654*6236dae4SAndroid Build Coastguard Worker "(bad PORT-line: $arg)\n"; 2655*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 silly you, go away\r\n"; 2656*6236dae4SAndroid Build Coastguard Worker return; 2657*6236dae4SAndroid Build Coastguard Worker } 2658*6236dae4SAndroid Build Coastguard Worker $port = ($5<<8)+$6; 2659*6236dae4SAndroid Build Coastguard Worker $addr = "$1.$2.$3.$4"; 2660*6236dae4SAndroid Build Coastguard Worker } 2661*6236dae4SAndroid Build Coastguard Worker # EPRT |2|::1|49706| 2662*6236dae4SAndroid Build Coastguard Worker elsif($cmd eq "EPRT") { 2663*6236dae4SAndroid Build Coastguard Worker if($arg !~ /(\d+)\|([^\|]+)\|(\d+)/) { 2664*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel not started ". 2665*6236dae4SAndroid Build Coastguard Worker "(bad EPRT-line: $arg)\n"; 2666*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 silly you, go away\r\n"; 2667*6236dae4SAndroid Build Coastguard Worker return; 2668*6236dae4SAndroid Build Coastguard Worker } 2669*6236dae4SAndroid Build Coastguard Worker sendcontrol "200 Thanks for dropping by. We contact you later\r\n"; 2670*6236dae4SAndroid Build Coastguard Worker $port = $3; 2671*6236dae4SAndroid Build Coastguard Worker $addr = $2; 2672*6236dae4SAndroid Build Coastguard Worker } 2673*6236dae4SAndroid Build Coastguard Worker else { 2674*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel not started ". 2675*6236dae4SAndroid Build Coastguard Worker "(invalid command: $cmd)\n"; 2676*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 we don't like $cmd now\r\n"; 2677*6236dae4SAndroid Build Coastguard Worker return; 2678*6236dae4SAndroid Build Coastguard Worker } 2679*6236dae4SAndroid Build Coastguard Worker 2680*6236dae4SAndroid Build Coastguard Worker if(!$port || $port > 65535) { 2681*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel not started ". 2682*6236dae4SAndroid Build Coastguard Worker "(illegal PORT number: $port)\n"; 2683*6236dae4SAndroid Build Coastguard Worker return; 2684*6236dae4SAndroid Build Coastguard Worker } 2685*6236dae4SAndroid Build Coastguard Worker 2686*6236dae4SAndroid Build Coastguard Worker if($nodataconn) { 2687*6236dae4SAndroid Build Coastguard Worker my $str = nodataconn_str(); 2688*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel not started ($str)\n"; 2689*6236dae4SAndroid Build Coastguard Worker datasockf_state('ACTIVE_NODATACONN'); 2690*6236dae4SAndroid Build Coastguard Worker logmsg "====> Active DATA channel not established\n"; 2691*6236dae4SAndroid Build Coastguard Worker return; 2692*6236dae4SAndroid Build Coastguard Worker } 2693*6236dae4SAndroid Build Coastguard Worker 2694*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel starting...\n"; 2695*6236dae4SAndroid Build Coastguard Worker 2696*6236dae4SAndroid Build Coastguard Worker # We fire up a new sockfilt to do the data transfer for us. 2697*6236dae4SAndroid Build Coastguard Worker my @datasockfcmd = ("./server/sockfilt".exe_ext('SRV'), 2698*6236dae4SAndroid Build Coastguard Worker "--ipv$ipvnum", "--connect", $port, "--addr", $addr, 2699*6236dae4SAndroid Build Coastguard Worker "--pidfile", $datasockf_pidfile, 2700*6236dae4SAndroid Build Coastguard Worker "--logfile", $datasockf_logfile); 2701*6236dae4SAndroid Build Coastguard Worker $slavepid = open2(\*DREAD, \*DWRITE, @datasockfcmd); 2702*6236dae4SAndroid Build Coastguard Worker 2703*6236dae4SAndroid Build Coastguard Worker datasockf_state('ACTIVE'); 2704*6236dae4SAndroid Build Coastguard Worker 2705*6236dae4SAndroid Build Coastguard Worker print STDERR "@datasockfcmd\n" if($verbose); 2706*6236dae4SAndroid Build Coastguard Worker 2707*6236dae4SAndroid Build Coastguard Worker print DWRITE "PING\n"; 2708*6236dae4SAndroid Build Coastguard Worker my $pong; 2709*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*DREAD, \$pong, 5); 2710*6236dae4SAndroid Build Coastguard Worker 2711*6236dae4SAndroid Build Coastguard Worker if($pong =~ /^FAIL/) { 2712*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt said: FAIL\n"; 2713*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel failed\n"; 2714*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2715*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2716*6236dae4SAndroid Build Coastguard Worker # client shall timeout awaiting connection from server 2717*6236dae4SAndroid Build Coastguard Worker return; 2718*6236dae4SAndroid Build Coastguard Worker } 2719*6236dae4SAndroid Build Coastguard Worker elsif($pong !~ /^PONG/) { 2720*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt unexpected response: $pong\n"; 2721*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel failed\n"; 2722*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt killed now\n"; 2723*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 2724*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt not running\n"; 2725*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 2726*6236dae4SAndroid Build Coastguard Worker # client shall timeout awaiting connection from server 2727*6236dae4SAndroid Build Coastguard Worker return; 2728*6236dae4SAndroid Build Coastguard Worker } 2729*6236dae4SAndroid Build Coastguard Worker 2730*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for active data channel started (pid $slavepid)\n"; 2731*6236dae4SAndroid Build Coastguard Worker 2732*6236dae4SAndroid Build Coastguard Worker logmsg "====> Active DATA channel connected to client port $port\n"; 2733*6236dae4SAndroid Build Coastguard Worker 2734*6236dae4SAndroid Build Coastguard Worker return; 2735*6236dae4SAndroid Build Coastguard Worker} 2736*6236dae4SAndroid Build Coastguard Worker 2737*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 2738*6236dae4SAndroid Build Coastguard Worker# datasockf_state is used to change variables that keep state info 2739*6236dae4SAndroid Build Coastguard Worker# relative to the FTP secondary or data sockfilt process as soon as 2740*6236dae4SAndroid Build Coastguard Worker# one of the five possible stable states is reached. Variables that 2741*6236dae4SAndroid Build Coastguard Worker# are modified by this sub may be checked independently but should 2742*6236dae4SAndroid Build Coastguard Worker# not be changed except by calling this sub. 2743*6236dae4SAndroid Build Coastguard Worker# 2744*6236dae4SAndroid Build Coastguard Workersub datasockf_state { 2745*6236dae4SAndroid Build Coastguard Worker my $state = $_[0]; 2746*6236dae4SAndroid Build Coastguard Worker 2747*6236dae4SAndroid Build Coastguard Worker if($state eq 'STOPPED') { 2748*6236dae4SAndroid Build Coastguard Worker # Data sockfilter initial state, not running, 2749*6236dae4SAndroid Build Coastguard Worker # not connected and not used. 2750*6236dae4SAndroid Build Coastguard Worker $datasockf_state = $state; 2751*6236dae4SAndroid Build Coastguard Worker $datasockf_mode = 'none'; 2752*6236dae4SAndroid Build Coastguard Worker $datasockf_runs = 'no'; 2753*6236dae4SAndroid Build Coastguard Worker $datasockf_conn = 'no'; 2754*6236dae4SAndroid Build Coastguard Worker } 2755*6236dae4SAndroid Build Coastguard Worker elsif($state eq 'PASSIVE') { 2756*6236dae4SAndroid Build Coastguard Worker # Data sockfilter accepted connection from client. 2757*6236dae4SAndroid Build Coastguard Worker $datasockf_state = $state; 2758*6236dae4SAndroid Build Coastguard Worker $datasockf_mode = 'passive'; 2759*6236dae4SAndroid Build Coastguard Worker $datasockf_runs = 'yes'; 2760*6236dae4SAndroid Build Coastguard Worker $datasockf_conn = 'yes'; 2761*6236dae4SAndroid Build Coastguard Worker } 2762*6236dae4SAndroid Build Coastguard Worker elsif($state eq 'ACTIVE') { 2763*6236dae4SAndroid Build Coastguard Worker # Data sockfilter has connected to client. 2764*6236dae4SAndroid Build Coastguard Worker $datasockf_state = $state; 2765*6236dae4SAndroid Build Coastguard Worker $datasockf_mode = 'active'; 2766*6236dae4SAndroid Build Coastguard Worker $datasockf_runs = 'yes'; 2767*6236dae4SAndroid Build Coastguard Worker $datasockf_conn = 'yes'; 2768*6236dae4SAndroid Build Coastguard Worker } 2769*6236dae4SAndroid Build Coastguard Worker elsif($state eq 'PASSIVE_NODATACONN') { 2770*6236dae4SAndroid Build Coastguard Worker # Data sockfilter bound port without listening, 2771*6236dae4SAndroid Build Coastguard Worker # client won't be able to establish data connection. 2772*6236dae4SAndroid Build Coastguard Worker $datasockf_state = $state; 2773*6236dae4SAndroid Build Coastguard Worker $datasockf_mode = 'passive'; 2774*6236dae4SAndroid Build Coastguard Worker $datasockf_runs = 'yes'; 2775*6236dae4SAndroid Build Coastguard Worker $datasockf_conn = 'no'; 2776*6236dae4SAndroid Build Coastguard Worker } 2777*6236dae4SAndroid Build Coastguard Worker elsif($state eq 'ACTIVE_NODATACONN') { 2778*6236dae4SAndroid Build Coastguard Worker # Data sockfilter does not even run, 2779*6236dae4SAndroid Build Coastguard Worker # client awaits data connection from server in vain. 2780*6236dae4SAndroid Build Coastguard Worker $datasockf_state = $state; 2781*6236dae4SAndroid Build Coastguard Worker $datasockf_mode = 'active'; 2782*6236dae4SAndroid Build Coastguard Worker $datasockf_runs = 'no'; 2783*6236dae4SAndroid Build Coastguard Worker $datasockf_conn = 'no'; 2784*6236dae4SAndroid Build Coastguard Worker } 2785*6236dae4SAndroid Build Coastguard Worker else { 2786*6236dae4SAndroid Build Coastguard Worker die "Internal error. Unknown datasockf state: $state!"; 2787*6236dae4SAndroid Build Coastguard Worker } 2788*6236dae4SAndroid Build Coastguard Worker} 2789*6236dae4SAndroid Build Coastguard Worker 2790*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 2791*6236dae4SAndroid Build Coastguard Worker# nodataconn_str returns string of effective nodataconn command. Notice 2792*6236dae4SAndroid Build Coastguard Worker# that $nodataconn may be set alone or in addition to a $nodataconnXXX. 2793*6236dae4SAndroid Build Coastguard Worker# 2794*6236dae4SAndroid Build Coastguard Workersub nodataconn_str { 2795*6236dae4SAndroid Build Coastguard Worker my $str; 2796*6236dae4SAndroid Build Coastguard Worker # order matters 2797*6236dae4SAndroid Build Coastguard Worker $str = 'NODATACONN' if($nodataconn); 2798*6236dae4SAndroid Build Coastguard Worker $str = 'NODATACONN425' if($nodataconn425); 2799*6236dae4SAndroid Build Coastguard Worker $str = 'NODATACONN421' if($nodataconn421); 2800*6236dae4SAndroid Build Coastguard Worker $str = 'NODATACONN150' if($nodataconn150); 2801*6236dae4SAndroid Build Coastguard Worker return "$str"; 2802*6236dae4SAndroid Build Coastguard Worker} 2803*6236dae4SAndroid Build Coastguard Worker 2804*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 2805*6236dae4SAndroid Build Coastguard Worker# customize configures test server operation for each curl test, reading 2806*6236dae4SAndroid Build Coastguard Worker# configuration commands/parameters from server commands file each time 2807*6236dae4SAndroid Build Coastguard Worker# a new client control connection is established with the test server. 2808*6236dae4SAndroid Build Coastguard Worker# On success returns 1, otherwise zero. 2809*6236dae4SAndroid Build Coastguard Worker# 2810*6236dae4SAndroid Build Coastguard Workersub customize { 2811*6236dae4SAndroid Build Coastguard Worker my($cmdfile) = @_; 2812*6236dae4SAndroid Build Coastguard Worker $ctrldelay = 0; # default is no throttling of the ctrl stream 2813*6236dae4SAndroid Build Coastguard Worker $datadelay = 0; # default is no throttling of the data stream 2814*6236dae4SAndroid Build Coastguard Worker $retrweirdo = 0; # default is no use of RETRWEIRDO 2815*6236dae4SAndroid Build Coastguard Worker $retrnosize = 0; # default is no use of RETRNOSIZE 2816*6236dae4SAndroid Build Coastguard Worker $retrsize = 0; # default is no use of RETRSIZE 2817*6236dae4SAndroid Build Coastguard Worker $pasvbadip = 0; # default is no use of PASVBADIP 2818*6236dae4SAndroid Build Coastguard Worker $nosave = 0; # default is to actually save uploaded data to file 2819*6236dae4SAndroid Build Coastguard Worker $nodataconn = 0; # default is to establish or accept data channel 2820*6236dae4SAndroid Build Coastguard Worker $nodataconn425 = 0; # default is to not send 425 without data channel 2821*6236dae4SAndroid Build Coastguard Worker $nodataconn421 = 0; # default is to not send 421 without data channel 2822*6236dae4SAndroid Build Coastguard Worker $nodataconn150 = 0; # default is to not send 150 without data channel 2823*6236dae4SAndroid Build Coastguard Worker $storeresp = ""; # send as ultimate STOR response 2824*6236dae4SAndroid Build Coastguard Worker $postfetch = ""; # send as header after a FETCH response 2825*6236dae4SAndroid Build Coastguard Worker @capabilities = (); # default is to not support capability commands 2826*6236dae4SAndroid Build Coastguard Worker @auth_mechs = (); # default is to not support authentication commands 2827*6236dae4SAndroid Build Coastguard Worker %fulltextreply = ();# 2828*6236dae4SAndroid Build Coastguard Worker %commandreply = (); # 2829*6236dae4SAndroid Build Coastguard Worker %customcount = (); # 2830*6236dae4SAndroid Build Coastguard Worker %delayreply = (); # 2831*6236dae4SAndroid Build Coastguard Worker 2832*6236dae4SAndroid Build Coastguard Worker open(my $custom, "<", "$logdir/$SERVERCMD") || 2833*6236dae4SAndroid Build Coastguard Worker return 1; 2834*6236dae4SAndroid Build Coastguard Worker 2835*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: Getting commands from $logdir/$SERVERCMD\n"; 2836*6236dae4SAndroid Build Coastguard Worker 2837*6236dae4SAndroid Build Coastguard Worker while(<$custom>) { 2838*6236dae4SAndroid Build Coastguard Worker if($_ =~ /REPLY \"([A-Z]+ [A-Za-z0-9+-\/=\*. ]+)\" (.*)/) { 2839*6236dae4SAndroid Build Coastguard Worker $fulltextreply{$1}=eval "qq{$2}"; 2840*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: set custom reply for $1\n"; 2841*6236dae4SAndroid Build Coastguard Worker } 2842*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /REPLY(LF|) ([A-Za-z0-9+\/=\*]*) (.*)/) { 2843*6236dae4SAndroid Build Coastguard Worker $commandreply{$2}=eval "qq{$3}"; 2844*6236dae4SAndroid Build Coastguard Worker if($1 ne "LF") { 2845*6236dae4SAndroid Build Coastguard Worker $commandreply{$2}.="\r\n"; 2846*6236dae4SAndroid Build Coastguard Worker } 2847*6236dae4SAndroid Build Coastguard Worker else { 2848*6236dae4SAndroid Build Coastguard Worker $commandreply{$2}.="\n"; 2849*6236dae4SAndroid Build Coastguard Worker } 2850*6236dae4SAndroid Build Coastguard Worker if($2 eq "") { 2851*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: set custom reply for empty command\n"; 2852*6236dae4SAndroid Build Coastguard Worker } 2853*6236dae4SAndroid Build Coastguard Worker else { 2854*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: set custom reply for $2 command\n"; 2855*6236dae4SAndroid Build Coastguard Worker } 2856*6236dae4SAndroid Build Coastguard Worker } 2857*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /COUNT ([A-Z]+) (.*)/) { 2858*6236dae4SAndroid Build Coastguard Worker # we blank the custom reply for this command when having 2859*6236dae4SAndroid Build Coastguard Worker # been used this number of times 2860*6236dae4SAndroid Build Coastguard Worker $customcount{$1}=$2; 2861*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: blank custom reply for $1 command after $2 uses\n"; 2862*6236dae4SAndroid Build Coastguard Worker } 2863*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /DELAY ([A-Z]+) (\d*)/) { 2864*6236dae4SAndroid Build Coastguard Worker $delayreply{$1}=$2; 2865*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: delay reply for $1 with $2 seconds\n"; 2866*6236dae4SAndroid Build Coastguard Worker } 2867*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /POSTFETCH (.*)/) { 2868*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: read POSTFETCH header data\n"; 2869*6236dae4SAndroid Build Coastguard Worker $postfetch = $1; 2870*6236dae4SAndroid Build Coastguard Worker } 2871*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /SLOWDOWNDATA/) { 2872*6236dae4SAndroid Build Coastguard Worker $ctrldelay=0; 2873*6236dae4SAndroid Build Coastguard Worker $datadelay=0.005; 2874*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: send response data with 5ms delay per byte\n"; 2875*6236dae4SAndroid Build Coastguard Worker } 2876*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /SLOWDOWN/) { 2877*6236dae4SAndroid Build Coastguard Worker $ctrldelay=0.005; 2878*6236dae4SAndroid Build Coastguard Worker $datadelay=0.005; 2879*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: send response with 5ms delay between each byte\n"; 2880*6236dae4SAndroid Build Coastguard Worker } 2881*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /RETRWEIRDO/) { 2882*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use RETRWEIRDO\n"; 2883*6236dae4SAndroid Build Coastguard Worker $retrweirdo=1; 2884*6236dae4SAndroid Build Coastguard Worker } 2885*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /RETRNOSIZE/) { 2886*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use RETRNOSIZE\n"; 2887*6236dae4SAndroid Build Coastguard Worker $retrnosize=1; 2888*6236dae4SAndroid Build Coastguard Worker } 2889*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /RETRSIZE (\d+)/) { 2890*6236dae4SAndroid Build Coastguard Worker $retrsize= $1; 2891*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use RETRSIZE = $1\n"; 2892*6236dae4SAndroid Build Coastguard Worker } 2893*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /PASVBADIP/) { 2894*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use PASVBADIP\n"; 2895*6236dae4SAndroid Build Coastguard Worker $pasvbadip=1; 2896*6236dae4SAndroid Build Coastguard Worker } 2897*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /NODATACONN425/) { 2898*6236dae4SAndroid Build Coastguard Worker # applies to both active and passive FTP modes 2899*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use NODATACONN425\n"; 2900*6236dae4SAndroid Build Coastguard Worker $nodataconn425=1; 2901*6236dae4SAndroid Build Coastguard Worker $nodataconn=1; 2902*6236dae4SAndroid Build Coastguard Worker } 2903*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /NODATACONN421/) { 2904*6236dae4SAndroid Build Coastguard Worker # applies to both active and passive FTP modes 2905*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use NODATACONN421\n"; 2906*6236dae4SAndroid Build Coastguard Worker $nodataconn421=1; 2907*6236dae4SAndroid Build Coastguard Worker $nodataconn=1; 2908*6236dae4SAndroid Build Coastguard Worker } 2909*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /NODATACONN150/) { 2910*6236dae4SAndroid Build Coastguard Worker # applies to both active and passive FTP modes 2911*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use NODATACONN150\n"; 2912*6236dae4SAndroid Build Coastguard Worker $nodataconn150=1; 2913*6236dae4SAndroid Build Coastguard Worker $nodataconn=1; 2914*6236dae4SAndroid Build Coastguard Worker } 2915*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /NODATACONN/) { 2916*6236dae4SAndroid Build Coastguard Worker # applies to both active and passive FTP modes 2917*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use NODATACONN\n"; 2918*6236dae4SAndroid Build Coastguard Worker $nodataconn=1; 2919*6236dae4SAndroid Build Coastguard Worker } 2920*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /^STOR (.*)/) { 2921*6236dae4SAndroid Build Coastguard Worker $storeresp=$1; 2922*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to use respond to STOR with '$storeresp'\n"; 2923*6236dae4SAndroid Build Coastguard Worker } 2924*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /CAPA (.*)/) { 2925*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to support CAPABILITY command\n"; 2926*6236dae4SAndroid Build Coastguard Worker @capabilities = split(/ (?!(?:[^" ]|[^"] [^"])+")/, $1); 2927*6236dae4SAndroid Build Coastguard Worker foreach (@capabilities) { 2928*6236dae4SAndroid Build Coastguard Worker $_ = $1 if /^"(.*)"$/; 2929*6236dae4SAndroid Build Coastguard Worker } 2930*6236dae4SAndroid Build Coastguard Worker } 2931*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /AUTH (.*)/) { 2932*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: instructed to support AUTHENTICATION command\n"; 2933*6236dae4SAndroid Build Coastguard Worker @auth_mechs = split(/ /, $1); 2934*6236dae4SAndroid Build Coastguard Worker } 2935*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /NOSAVE/) { 2936*6236dae4SAndroid Build Coastguard Worker # don't actually store the file we upload - to be used when 2937*6236dae4SAndroid Build Coastguard Worker # uploading insanely huge amounts 2938*6236dae4SAndroid Build Coastguard Worker $nosave = 1; 2939*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: NOSAVE prevents saving of uploaded data\n"; 2940*6236dae4SAndroid Build Coastguard Worker } 2941*6236dae4SAndroid Build Coastguard Worker elsif($_ =~ /^Testnum (\d+)/){ 2942*6236dae4SAndroid Build Coastguard Worker $testno = $1; 2943*6236dae4SAndroid Build Coastguard Worker logmsg "FTPD: run test case number: $testno\n"; 2944*6236dae4SAndroid Build Coastguard Worker } 2945*6236dae4SAndroid Build Coastguard Worker } 2946*6236dae4SAndroid Build Coastguard Worker close($custom); 2947*6236dae4SAndroid Build Coastguard Worker} 2948*6236dae4SAndroid Build Coastguard Worker 2949*6236dae4SAndroid Build Coastguard Worker#---------------------------------------------------------------------- 2950*6236dae4SAndroid Build Coastguard Worker#---------------------------------------------------------------------- 2951*6236dae4SAndroid Build Coastguard Worker#--------------------------- END OF SUBS ---------------------------- 2952*6236dae4SAndroid Build Coastguard Worker#---------------------------------------------------------------------- 2953*6236dae4SAndroid Build Coastguard Worker#---------------------------------------------------------------------- 2954*6236dae4SAndroid Build Coastguard Worker 2955*6236dae4SAndroid Build Coastguard Worker#********************************************************************** 2956*6236dae4SAndroid Build Coastguard Worker# Parse command line options 2957*6236dae4SAndroid Build Coastguard Worker# 2958*6236dae4SAndroid Build Coastguard Worker# Options: 2959*6236dae4SAndroid Build Coastguard Worker# 2960*6236dae4SAndroid Build Coastguard Worker# --verbose # verbose 2961*6236dae4SAndroid Build Coastguard Worker# --srcdir # source directory 2962*6236dae4SAndroid Build Coastguard Worker# --id # server instance number 2963*6236dae4SAndroid Build Coastguard Worker# --proto # server protocol 2964*6236dae4SAndroid Build Coastguard Worker# --pidfile # server pid file 2965*6236dae4SAndroid Build Coastguard Worker# --portfile # server port file 2966*6236dae4SAndroid Build Coastguard Worker# --logfile # server log file 2967*6236dae4SAndroid Build Coastguard Worker# --logdir # server log directory 2968*6236dae4SAndroid Build Coastguard Worker# --ipv4 # server IP version 4 2969*6236dae4SAndroid Build Coastguard Worker# --ipv6 # server IP version 6 2970*6236dae4SAndroid Build Coastguard Worker# --port # server listener port 2971*6236dae4SAndroid Build Coastguard Worker# --addr # server address for listener port binding 2972*6236dae4SAndroid Build Coastguard Worker# 2973*6236dae4SAndroid Build Coastguard Workerwhile(@ARGV) { 2974*6236dae4SAndroid Build Coastguard Worker if($ARGV[0] eq '--verbose') { 2975*6236dae4SAndroid Build Coastguard Worker $verbose = 1; 2976*6236dae4SAndroid Build Coastguard Worker } 2977*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--srcdir') { 2978*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 2979*6236dae4SAndroid Build Coastguard Worker $srcdir = $ARGV[1]; 2980*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 2981*6236dae4SAndroid Build Coastguard Worker } 2982*6236dae4SAndroid Build Coastguard Worker } 2983*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--id') { 2984*6236dae4SAndroid Build Coastguard Worker if($ARGV[1] && ($ARGV[1] =~ /^(\d+)$/)) { 2985*6236dae4SAndroid Build Coastguard Worker $idnum = $1 if($1 > 0); 2986*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 2987*6236dae4SAndroid Build Coastguard Worker } 2988*6236dae4SAndroid Build Coastguard Worker } 2989*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--proto') { 2990*6236dae4SAndroid Build Coastguard Worker if($ARGV[1] && ($ARGV[1] =~ /^(ftp|imap|pop3|smtp)$/)) { 2991*6236dae4SAndroid Build Coastguard Worker $proto = $1; 2992*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 2993*6236dae4SAndroid Build Coastguard Worker } 2994*6236dae4SAndroid Build Coastguard Worker else { 2995*6236dae4SAndroid Build Coastguard Worker die "unsupported protocol $ARGV[1]"; 2996*6236dae4SAndroid Build Coastguard Worker } 2997*6236dae4SAndroid Build Coastguard Worker } 2998*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--pidfile') { 2999*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 3000*6236dae4SAndroid Build Coastguard Worker $pidfile = $ARGV[1]; 3001*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3002*6236dae4SAndroid Build Coastguard Worker } 3003*6236dae4SAndroid Build Coastguard Worker } 3004*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--portfile') { 3005*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 3006*6236dae4SAndroid Build Coastguard Worker $portfile = $ARGV[1]; 3007*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3008*6236dae4SAndroid Build Coastguard Worker } 3009*6236dae4SAndroid Build Coastguard Worker } 3010*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--logfile') { 3011*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 3012*6236dae4SAndroid Build Coastguard Worker $logfile = $ARGV[1]; 3013*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3014*6236dae4SAndroid Build Coastguard Worker } 3015*6236dae4SAndroid Build Coastguard Worker } 3016*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--logdir') { 3017*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 3018*6236dae4SAndroid Build Coastguard Worker $logdir = $ARGV[1]; 3019*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3020*6236dae4SAndroid Build Coastguard Worker } 3021*6236dae4SAndroid Build Coastguard Worker } 3022*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--ipv4') { 3023*6236dae4SAndroid Build Coastguard Worker $ipvnum = 4; 3024*6236dae4SAndroid Build Coastguard Worker $listenaddr = '127.0.0.1' if($listenaddr eq '::1'); 3025*6236dae4SAndroid Build Coastguard Worker } 3026*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--ipv6') { 3027*6236dae4SAndroid Build Coastguard Worker $ipvnum = 6; 3028*6236dae4SAndroid Build Coastguard Worker $listenaddr = '::1' if($listenaddr eq '127.0.0.1'); 3029*6236dae4SAndroid Build Coastguard Worker } 3030*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--port') { 3031*6236dae4SAndroid Build Coastguard Worker if($ARGV[1] =~ /^(\d+)$/) { 3032*6236dae4SAndroid Build Coastguard Worker $port = $1; 3033*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3034*6236dae4SAndroid Build Coastguard Worker } 3035*6236dae4SAndroid Build Coastguard Worker } 3036*6236dae4SAndroid Build Coastguard Worker elsif($ARGV[0] eq '--addr') { 3037*6236dae4SAndroid Build Coastguard Worker if($ARGV[1]) { 3038*6236dae4SAndroid Build Coastguard Worker my $tmpstr = $ARGV[1]; 3039*6236dae4SAndroid Build Coastguard Worker if($tmpstr =~ /^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)$/) { 3040*6236dae4SAndroid Build Coastguard Worker $listenaddr = "$1.$2.$3.$4" if($ipvnum == 4); 3041*6236dae4SAndroid Build Coastguard Worker } 3042*6236dae4SAndroid Build Coastguard Worker elsif($ipvnum == 6) { 3043*6236dae4SAndroid Build Coastguard Worker $listenaddr = $tmpstr; 3044*6236dae4SAndroid Build Coastguard Worker $listenaddr =~ s/^\[(.*)\]$/$1/; 3045*6236dae4SAndroid Build Coastguard Worker } 3046*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3047*6236dae4SAndroid Build Coastguard Worker } 3048*6236dae4SAndroid Build Coastguard Worker } 3049*6236dae4SAndroid Build Coastguard Worker else { 3050*6236dae4SAndroid Build Coastguard Worker print STDERR "\nWarning: ftpserver.pl unknown parameter: $ARGV[0]\n"; 3051*6236dae4SAndroid Build Coastguard Worker } 3052*6236dae4SAndroid Build Coastguard Worker shift @ARGV; 3053*6236dae4SAndroid Build Coastguard Worker} 3054*6236dae4SAndroid Build Coastguard Worker 3055*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 3056*6236dae4SAndroid Build Coastguard Worker# Initialize command line option dependent variables 3057*6236dae4SAndroid Build Coastguard Worker# 3058*6236dae4SAndroid Build Coastguard Worker 3059*6236dae4SAndroid Build Coastguard Workerif($pidfile) { 3060*6236dae4SAndroid Build Coastguard Worker # Use our pidfile directory to store the other pidfiles 3061*6236dae4SAndroid Build Coastguard Worker $piddir = dirname($pidfile); 3062*6236dae4SAndroid Build Coastguard Worker} 3063*6236dae4SAndroid Build Coastguard Workerelse { 3064*6236dae4SAndroid Build Coastguard Worker # Use the current directory to store all the pidfiles 3065*6236dae4SAndroid Build Coastguard Worker $piddir = $path; 3066*6236dae4SAndroid Build Coastguard Worker $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum); 3067*6236dae4SAndroid Build Coastguard Worker} 3068*6236dae4SAndroid Build Coastguard Workerif(!$portfile) { 3069*6236dae4SAndroid Build Coastguard Worker $portfile = $piddir . "/" . $PORTFILE; 3070*6236dae4SAndroid Build Coastguard Worker} 3071*6236dae4SAndroid Build Coastguard Workerif(!$srcdir) { 3072*6236dae4SAndroid Build Coastguard Worker $srcdir = $ENV{'srcdir'} || '.'; 3073*6236dae4SAndroid Build Coastguard Worker} 3074*6236dae4SAndroid Build Coastguard Workerif(!$logfile) { 3075*6236dae4SAndroid Build Coastguard Worker $logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum); 3076*6236dae4SAndroid Build Coastguard Worker} 3077*6236dae4SAndroid Build Coastguard Worker 3078*6236dae4SAndroid Build Coastguard Worker$mainsockf_pidfile = mainsockf_pidfilename($piddir, $proto, $ipvnum, $idnum); 3079*6236dae4SAndroid Build Coastguard Worker$mainsockf_logfile = 3080*6236dae4SAndroid Build Coastguard Worker mainsockf_logfilename($logdir, $proto, $ipvnum, $idnum); 3081*6236dae4SAndroid Build Coastguard Worker 3082*6236dae4SAndroid Build Coastguard Workerif($proto eq 'ftp') { 3083*6236dae4SAndroid Build Coastguard Worker $datasockf_pidfile = datasockf_pidfilename($piddir, $proto, $ipvnum, $idnum); 3084*6236dae4SAndroid Build Coastguard Worker $datasockf_logfile = 3085*6236dae4SAndroid Build Coastguard Worker datasockf_logfilename($logdir, $proto, $ipvnum, $idnum); 3086*6236dae4SAndroid Build Coastguard Worker} 3087*6236dae4SAndroid Build Coastguard Worker 3088*6236dae4SAndroid Build Coastguard Worker$srvrname = servername_str($proto, $ipvnum, $idnum); 3089*6236dae4SAndroid Build Coastguard Worker$serverlogs_lockfile = "$logdir/$LOCKDIR/${srvrname}.lock"; 3090*6236dae4SAndroid Build Coastguard Worker 3091*6236dae4SAndroid Build Coastguard Worker$idstr = "$idnum" if($idnum > 1); 3092*6236dae4SAndroid Build Coastguard Worker 3093*6236dae4SAndroid Build Coastguard Workerprotocolsetup($proto); 3094*6236dae4SAndroid Build Coastguard Worker 3095*6236dae4SAndroid Build Coastguard Worker$SIG{INT} = \&exit_signal_handler; 3096*6236dae4SAndroid Build Coastguard Worker$SIG{TERM} = \&exit_signal_handler; 3097*6236dae4SAndroid Build Coastguard Worker 3098*6236dae4SAndroid Build Coastguard Workerstartsf(); 3099*6236dae4SAndroid Build Coastguard Worker 3100*6236dae4SAndroid Build Coastguard Worker# actual port 3101*6236dae4SAndroid Build Coastguard Workerif($portfile && !$port) { 3102*6236dae4SAndroid Build Coastguard Worker my $aport; 3103*6236dae4SAndroid Build Coastguard Worker open(my $p, "<", "$portfile"); 3104*6236dae4SAndroid Build Coastguard Worker $aport = <$p>; 3105*6236dae4SAndroid Build Coastguard Worker close($p); 3106*6236dae4SAndroid Build Coastguard Worker $port = 0 + $aport; 3107*6236dae4SAndroid Build Coastguard Worker} 3108*6236dae4SAndroid Build Coastguard Worker 3109*6236dae4SAndroid Build Coastguard Workerlogmsg sprintf("%s server listens on port IPv${ipvnum}/${port}\n", uc($proto)); 3110*6236dae4SAndroid Build Coastguard Worker 3111*6236dae4SAndroid Build Coastguard Workeropen(my $pid, ">", "$pidfile"); 3112*6236dae4SAndroid Build Coastguard Workerprint $pid $$."\n"; 3113*6236dae4SAndroid Build Coastguard Workerclose($pid); 3114*6236dae4SAndroid Build Coastguard Worker 3115*6236dae4SAndroid Build Coastguard Workerlogmsg("logged pid $$ in $pidfile\n"); 3116*6236dae4SAndroid Build Coastguard Worker 3117*6236dae4SAndroid Build Coastguard Workerwhile(1) { 3118*6236dae4SAndroid Build Coastguard Worker 3119*6236dae4SAndroid Build Coastguard Worker # kill previous data connection sockfilt when alive 3120*6236dae4SAndroid Build Coastguard Worker if($datasockf_runs eq 'yes') { 3121*6236dae4SAndroid Build Coastguard Worker killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data'); 3122*6236dae4SAndroid Build Coastguard Worker logmsg "DATA sockfilt for $datasockf_mode data channel killed now\n"; 3123*6236dae4SAndroid Build Coastguard Worker } 3124*6236dae4SAndroid Build Coastguard Worker datasockf_state('STOPPED'); 3125*6236dae4SAndroid Build Coastguard Worker 3126*6236dae4SAndroid Build Coastguard Worker # 3127*6236dae4SAndroid Build Coastguard Worker # We read 'sockfilt' commands. 3128*6236dae4SAndroid Build Coastguard Worker # 3129*6236dae4SAndroid Build Coastguard Worker my $input; 3130*6236dae4SAndroid Build Coastguard Worker 3131*6236dae4SAndroid Build Coastguard Worker logmsg "Awaiting input\n"; 3132*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*SFREAD, \$input, 5); 3133*6236dae4SAndroid Build Coastguard Worker 3134*6236dae4SAndroid Build Coastguard Worker if($input !~ /^CNCT/) { 3135*6236dae4SAndroid Build Coastguard Worker # we wait for a connected client 3136*6236dae4SAndroid Build Coastguard Worker logmsg "MAIN sockfilt said: $input"; 3137*6236dae4SAndroid Build Coastguard Worker next; 3138*6236dae4SAndroid Build Coastguard Worker } 3139*6236dae4SAndroid Build Coastguard Worker logmsg "====> Client connect\n"; 3140*6236dae4SAndroid Build Coastguard Worker 3141*6236dae4SAndroid Build Coastguard Worker set_advisor_read_lock($serverlogs_lockfile); 3142*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 1; 3143*6236dae4SAndroid Build Coastguard Worker 3144*6236dae4SAndroid Build Coastguard Worker # flush data: 3145*6236dae4SAndroid Build Coastguard Worker $| = 1; 3146*6236dae4SAndroid Build Coastguard Worker 3147*6236dae4SAndroid Build Coastguard Worker &customize(); # read test control instructions 3148*6236dae4SAndroid Build Coastguard Worker loadtest("$logdir/test$testno"); 3149*6236dae4SAndroid Build Coastguard Worker 3150*6236dae4SAndroid Build Coastguard Worker my $welcome = $commandreply{"welcome"}; 3151*6236dae4SAndroid Build Coastguard Worker if(!$welcome) { 3152*6236dae4SAndroid Build Coastguard Worker $welcome = $displaytext{"welcome"}; 3153*6236dae4SAndroid Build Coastguard Worker } 3154*6236dae4SAndroid Build Coastguard Worker else { 3155*6236dae4SAndroid Build Coastguard Worker # clear it after use 3156*6236dae4SAndroid Build Coastguard Worker $commandreply{"welcome"}=""; 3157*6236dae4SAndroid Build Coastguard Worker if($welcome !~ /\r\n\z/) { 3158*6236dae4SAndroid Build Coastguard Worker $welcome .= "\r\n"; 3159*6236dae4SAndroid Build Coastguard Worker } 3160*6236dae4SAndroid Build Coastguard Worker } 3161*6236dae4SAndroid Build Coastguard Worker sendcontrol $welcome; 3162*6236dae4SAndroid Build Coastguard Worker 3163*6236dae4SAndroid Build Coastguard Worker #remove global variables from last connection 3164*6236dae4SAndroid Build Coastguard Worker if($ftplistparserstate) { 3165*6236dae4SAndroid Build Coastguard Worker undef $ftplistparserstate; 3166*6236dae4SAndroid Build Coastguard Worker } 3167*6236dae4SAndroid Build Coastguard Worker if($ftptargetdir) { 3168*6236dae4SAndroid Build Coastguard Worker $ftptargetdir = ""; 3169*6236dae4SAndroid Build Coastguard Worker } 3170*6236dae4SAndroid Build Coastguard Worker 3171*6236dae4SAndroid Build Coastguard Worker if($verbose) { 3172*6236dae4SAndroid Build Coastguard Worker print STDERR "OUT: $welcome"; 3173*6236dae4SAndroid Build Coastguard Worker } 3174*6236dae4SAndroid Build Coastguard Worker 3175*6236dae4SAndroid Build Coastguard Worker my $full = ""; 3176*6236dae4SAndroid Build Coastguard Worker 3177*6236dae4SAndroid Build Coastguard Worker while(1) { 3178*6236dae4SAndroid Build Coastguard Worker my $i; 3179*6236dae4SAndroid Build Coastguard Worker 3180*6236dae4SAndroid Build Coastguard Worker # Now we expect to read DATA\n[hex size]\n[prot], where the [prot] 3181*6236dae4SAndroid Build Coastguard Worker # part only is FTP lingo. 3182*6236dae4SAndroid Build Coastguard Worker 3183*6236dae4SAndroid Build Coastguard Worker # COMMAND 3184*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*SFREAD, \$i, 5); 3185*6236dae4SAndroid Build Coastguard Worker 3186*6236dae4SAndroid Build Coastguard Worker if($i !~ /^DATA/) { 3187*6236dae4SAndroid Build Coastguard Worker logmsg "MAIN sockfilt said $i"; 3188*6236dae4SAndroid Build Coastguard Worker if($i =~ /^DISC/) { 3189*6236dae4SAndroid Build Coastguard Worker # disconnect 3190*6236dae4SAndroid Build Coastguard Worker printf SFWRITE "ACKD\n"; 3191*6236dae4SAndroid Build Coastguard Worker last; 3192*6236dae4SAndroid Build Coastguard Worker } 3193*6236dae4SAndroid Build Coastguard Worker next; 3194*6236dae4SAndroid Build Coastguard Worker } 3195*6236dae4SAndroid Build Coastguard Worker 3196*6236dae4SAndroid Build Coastguard Worker # SIZE of data 3197*6236dae4SAndroid Build Coastguard Worker sysread_or_die(\*SFREAD, \$i, 5); 3198*6236dae4SAndroid Build Coastguard Worker 3199*6236dae4SAndroid Build Coastguard Worker my $size = 0; 3200*6236dae4SAndroid Build Coastguard Worker if($i =~ /^([0-9a-fA-F]{4})\n/) { 3201*6236dae4SAndroid Build Coastguard Worker $size = hex($1); 3202*6236dae4SAndroid Build Coastguard Worker } 3203*6236dae4SAndroid Build Coastguard Worker 3204*6236dae4SAndroid Build Coastguard Worker # data 3205*6236dae4SAndroid Build Coastguard Worker read_mainsockf(\$input, $size); 3206*6236dae4SAndroid Build Coastguard Worker 3207*6236dae4SAndroid Build Coastguard Worker ftpmsg $input; 3208*6236dae4SAndroid Build Coastguard Worker 3209*6236dae4SAndroid Build Coastguard Worker $full .= $input; 3210*6236dae4SAndroid Build Coastguard Worker 3211*6236dae4SAndroid Build Coastguard Worker # Loop until command completion 3212*6236dae4SAndroid Build Coastguard Worker next unless($full =~ /\r\n$/); 3213*6236dae4SAndroid Build Coastguard Worker 3214*6236dae4SAndroid Build Coastguard Worker # Remove trailing CRLF. 3215*6236dae4SAndroid Build Coastguard Worker $full =~ s/[\n\r]+$//; 3216*6236dae4SAndroid Build Coastguard Worker 3217*6236dae4SAndroid Build Coastguard Worker my $FTPCMD; 3218*6236dae4SAndroid Build Coastguard Worker my $FTPARG; 3219*6236dae4SAndroid Build Coastguard Worker if($proto eq "imap") { 3220*6236dae4SAndroid Build Coastguard Worker # IMAP is different with its identifier first on the command line 3221*6236dae4SAndroid Build Coastguard Worker if(($full =~ /^([^ ]+) ([^ ]+) (.*)/) || 3222*6236dae4SAndroid Build Coastguard Worker ($full =~ /^([^ ]+) ([^ ]+)/)) { 3223*6236dae4SAndroid Build Coastguard Worker $cmdid=$1; # set the global variable 3224*6236dae4SAndroid Build Coastguard Worker $FTPCMD=$2; 3225*6236dae4SAndroid Build Coastguard Worker $FTPARG=$3; 3226*6236dae4SAndroid Build Coastguard Worker } 3227*6236dae4SAndroid Build Coastguard Worker # IMAP authentication cancellation 3228*6236dae4SAndroid Build Coastguard Worker elsif($full =~ /^\*$/) { 3229*6236dae4SAndroid Build Coastguard Worker # Command id has already been set 3230*6236dae4SAndroid Build Coastguard Worker $FTPCMD="*"; 3231*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3232*6236dae4SAndroid Build Coastguard Worker } 3233*6236dae4SAndroid Build Coastguard Worker # IMAP long "commands" are base64 authentication data 3234*6236dae4SAndroid Build Coastguard Worker elsif($full =~ /^[A-Z0-9+\/]*={0,2}$/i) { 3235*6236dae4SAndroid Build Coastguard Worker # Command id has already been set 3236*6236dae4SAndroid Build Coastguard Worker $FTPCMD=$full; 3237*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3238*6236dae4SAndroid Build Coastguard Worker } 3239*6236dae4SAndroid Build Coastguard Worker else { 3240*6236dae4SAndroid Build Coastguard Worker sendcontrol "$full BAD Command\r\n"; 3241*6236dae4SAndroid Build Coastguard Worker last; 3242*6236dae4SAndroid Build Coastguard Worker } 3243*6236dae4SAndroid Build Coastguard Worker } 3244*6236dae4SAndroid Build Coastguard Worker elsif($full =~ /^([A-Z]{3,4})(\s(.*))?$/i) { 3245*6236dae4SAndroid Build Coastguard Worker $FTPCMD=$1; 3246*6236dae4SAndroid Build Coastguard Worker $FTPARG=$3; 3247*6236dae4SAndroid Build Coastguard Worker } 3248*6236dae4SAndroid Build Coastguard Worker elsif($proto eq "pop3") { 3249*6236dae4SAndroid Build Coastguard Worker # POP3 authentication cancellation 3250*6236dae4SAndroid Build Coastguard Worker if($full =~ /^\*$/) { 3251*6236dae4SAndroid Build Coastguard Worker $FTPCMD="*"; 3252*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3253*6236dae4SAndroid Build Coastguard Worker } 3254*6236dae4SAndroid Build Coastguard Worker # POP3 long "commands" are base64 authentication data 3255*6236dae4SAndroid Build Coastguard Worker elsif($full =~ /^[A-Z0-9+\/]*={0,2}$/i) { 3256*6236dae4SAndroid Build Coastguard Worker $FTPCMD=$full; 3257*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3258*6236dae4SAndroid Build Coastguard Worker } 3259*6236dae4SAndroid Build Coastguard Worker else { 3260*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR Unrecognized command\r\n"; 3261*6236dae4SAndroid Build Coastguard Worker last; 3262*6236dae4SAndroid Build Coastguard Worker } 3263*6236dae4SAndroid Build Coastguard Worker } 3264*6236dae4SAndroid Build Coastguard Worker elsif($proto eq "smtp") { 3265*6236dae4SAndroid Build Coastguard Worker # SMTP authentication cancellation 3266*6236dae4SAndroid Build Coastguard Worker if($full =~ /^\*$/) { 3267*6236dae4SAndroid Build Coastguard Worker $FTPCMD="*"; 3268*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3269*6236dae4SAndroid Build Coastguard Worker } 3270*6236dae4SAndroid Build Coastguard Worker # SMTP long "commands" are base64 authentication data 3271*6236dae4SAndroid Build Coastguard Worker elsif($full =~ /^[A-Z0-9+\/]{0,512}={0,2}$/i) { 3272*6236dae4SAndroid Build Coastguard Worker $FTPCMD=$full; 3273*6236dae4SAndroid Build Coastguard Worker $FTPARG=""; 3274*6236dae4SAndroid Build Coastguard Worker } 3275*6236dae4SAndroid Build Coastguard Worker else { 3276*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 Unrecognized command\r\n"; 3277*6236dae4SAndroid Build Coastguard Worker last; 3278*6236dae4SAndroid Build Coastguard Worker } 3279*6236dae4SAndroid Build Coastguard Worker } 3280*6236dae4SAndroid Build Coastguard Worker else { 3281*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 Unrecognized command\r\n"; 3282*6236dae4SAndroid Build Coastguard Worker last; 3283*6236dae4SAndroid Build Coastguard Worker } 3284*6236dae4SAndroid Build Coastguard Worker 3285*6236dae4SAndroid Build Coastguard Worker logmsg "< \"$full\"\n"; 3286*6236dae4SAndroid Build Coastguard Worker 3287*6236dae4SAndroid Build Coastguard Worker if($verbose) { 3288*6236dae4SAndroid Build Coastguard Worker print STDERR "IN: $full\n"; 3289*6236dae4SAndroid Build Coastguard Worker } 3290*6236dae4SAndroid Build Coastguard Worker 3291*6236dae4SAndroid Build Coastguard Worker $full = ""; 3292*6236dae4SAndroid Build Coastguard Worker 3293*6236dae4SAndroid Build Coastguard Worker my $delay = $delayreply{$FTPCMD}; 3294*6236dae4SAndroid Build Coastguard Worker if($delay) { 3295*6236dae4SAndroid Build Coastguard Worker # just go sleep this many seconds! 3296*6236dae4SAndroid Build Coastguard Worker logmsg("Sleep for $delay seconds\n"); 3297*6236dae4SAndroid Build Coastguard Worker my $twentieths = $delay * 20; 3298*6236dae4SAndroid Build Coastguard Worker while($twentieths--) { 3299*6236dae4SAndroid Build Coastguard Worker portable_sleep(0.05) unless($got_exit_signal); 3300*6236dae4SAndroid Build Coastguard Worker } 3301*6236dae4SAndroid Build Coastguard Worker } 3302*6236dae4SAndroid Build Coastguard Worker 3303*6236dae4SAndroid Build Coastguard Worker my $check = 1; # no response yet 3304*6236dae4SAndroid Build Coastguard Worker 3305*6236dae4SAndroid Build Coastguard Worker # See if there is a custom reply for the full text 3306*6236dae4SAndroid Build Coastguard Worker my $fulltext = $FTPARG ? $FTPCMD . " " . $FTPARG : $FTPCMD; 3307*6236dae4SAndroid Build Coastguard Worker my $text = $fulltextreply{$fulltext}; 3308*6236dae4SAndroid Build Coastguard Worker if($text && ($text ne "")) { 3309*6236dae4SAndroid Build Coastguard Worker sendcontrol "$text\r\n"; 3310*6236dae4SAndroid Build Coastguard Worker $check = 0; 3311*6236dae4SAndroid Build Coastguard Worker } 3312*6236dae4SAndroid Build Coastguard Worker else { 3313*6236dae4SAndroid Build Coastguard Worker # See if there is a custom reply for the command 3314*6236dae4SAndroid Build Coastguard Worker $text = $commandreply{$FTPCMD}; 3315*6236dae4SAndroid Build Coastguard Worker if($text && ($text ne "")) { 3316*6236dae4SAndroid Build Coastguard Worker if($customcount{$FTPCMD} && (!--$customcount{$FTPCMD})) { 3317*6236dae4SAndroid Build Coastguard Worker # used enough times so blank the custom command reply 3318*6236dae4SAndroid Build Coastguard Worker $commandreply{$FTPCMD}=""; 3319*6236dae4SAndroid Build Coastguard Worker } 3320*6236dae4SAndroid Build Coastguard Worker 3321*6236dae4SAndroid Build Coastguard Worker sendcontrol $text; 3322*6236dae4SAndroid Build Coastguard Worker $check = 0; 3323*6236dae4SAndroid Build Coastguard Worker } 3324*6236dae4SAndroid Build Coastguard Worker else { 3325*6236dae4SAndroid Build Coastguard Worker # See if there is any display text for the command 3326*6236dae4SAndroid Build Coastguard Worker $text = $displaytext{$FTPCMD}; 3327*6236dae4SAndroid Build Coastguard Worker if($text && ($text ne "")) { 3328*6236dae4SAndroid Build Coastguard Worker if($proto eq 'imap') { 3329*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid $text\r\n"; 3330*6236dae4SAndroid Build Coastguard Worker } 3331*6236dae4SAndroid Build Coastguard Worker else { 3332*6236dae4SAndroid Build Coastguard Worker sendcontrol "$text\r\n"; 3333*6236dae4SAndroid Build Coastguard Worker } 3334*6236dae4SAndroid Build Coastguard Worker 3335*6236dae4SAndroid Build Coastguard Worker $check = 0; 3336*6236dae4SAndroid Build Coastguard Worker } 3337*6236dae4SAndroid Build Coastguard Worker 3338*6236dae4SAndroid Build Coastguard Worker # only perform this if we're not faking a reply 3339*6236dae4SAndroid Build Coastguard Worker my $func = $commandfunc{uc($FTPCMD)}; 3340*6236dae4SAndroid Build Coastguard Worker if($func) { 3341*6236dae4SAndroid Build Coastguard Worker &$func($FTPARG, $FTPCMD); 3342*6236dae4SAndroid Build Coastguard Worker $check = 0; 3343*6236dae4SAndroid Build Coastguard Worker } 3344*6236dae4SAndroid Build Coastguard Worker } 3345*6236dae4SAndroid Build Coastguard Worker } 3346*6236dae4SAndroid Build Coastguard Worker 3347*6236dae4SAndroid Build Coastguard Worker if($check) { 3348*6236dae4SAndroid Build Coastguard Worker logmsg "$FTPCMD wasn't handled!\n"; 3349*6236dae4SAndroid Build Coastguard Worker if($proto eq 'pop3') { 3350*6236dae4SAndroid Build Coastguard Worker sendcontrol "-ERR $FTPCMD is not dealt with!\r\n"; 3351*6236dae4SAndroid Build Coastguard Worker } 3352*6236dae4SAndroid Build Coastguard Worker elsif($proto eq 'imap') { 3353*6236dae4SAndroid Build Coastguard Worker sendcontrol "$cmdid BAD $FTPCMD is not dealt with!\r\n"; 3354*6236dae4SAndroid Build Coastguard Worker } 3355*6236dae4SAndroid Build Coastguard Worker else { 3356*6236dae4SAndroid Build Coastguard Worker sendcontrol "500 $FTPCMD is not dealt with!\r\n"; 3357*6236dae4SAndroid Build Coastguard Worker } 3358*6236dae4SAndroid Build Coastguard Worker } 3359*6236dae4SAndroid Build Coastguard Worker 3360*6236dae4SAndroid Build Coastguard Worker } # while(1) 3361*6236dae4SAndroid Build Coastguard Worker logmsg "====> Client disconnected\n"; 3362*6236dae4SAndroid Build Coastguard Worker 3363*6236dae4SAndroid Build Coastguard Worker if($serverlogslocked) { 3364*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 3365*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 3366*6236dae4SAndroid Build Coastguard Worker } 3367*6236dae4SAndroid Build Coastguard Worker} 3368*6236dae4SAndroid Build Coastguard Worker 3369*6236dae4SAndroid Build Coastguard Workerkillsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose); 3370*6236dae4SAndroid Build Coastguard Workerunlink($pidfile); 3371*6236dae4SAndroid Build Coastguard Workerif($serverlogslocked) { 3372*6236dae4SAndroid Build Coastguard Worker $serverlogslocked = 0; 3373*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock($serverlogs_lockfile); 3374*6236dae4SAndroid Build Coastguard Worker} 3375*6236dae4SAndroid Build Coastguard Worker 3376*6236dae4SAndroid Build Coastguard Workerexit; 3377