Commit c761fcb0 authored by Yang Tse's avatar Yang Tse
Browse files

ftpserver.pl: three new custom FTP server commands to disable data channel

NODATACONN421: applies only to active FTP mode, instructs server to not
establish data connection back to client and reply with FTP 421.

NODATACONN425: applies only to active FTP mode, instructs server to not
establish data connection back to client and reply with FTP 425.

NODATACONN: applies to both active and passive FTP modes, instructs server
to not establish nor accept a data channel and fool client into believing
that the data channel connection is possible.

Some polishing probably required.
parent ddeab482
Loading
Loading
Loading
Loading
+77 −23
Original line number Diff line number Diff line
@@ -132,6 +132,9 @@ my $retrweirdo; # set if ftp server should use RETRWEIRDO
my $retrnosize;    # set if ftp server should use RETRNOSIZE
my $pasvbadip;     # set if ftp server should use PASVBADIP
my $nosave;        # set if ftp server should not save uploaded data
my $nodataconn;    # set if ftp srvr doesn't establish or accepts data channel
my $nodataconn425; # set if ftp srvr doesn't establish data ch and replies 425
my $nodataconn421; # set if ftp srvr doesn't establish data ch and replies 421
my %customreply;   #
my %customcount;   #
my %delayreply;    #
@@ -1071,7 +1074,7 @@ sub PASV_ftp {
        logmsg "failed to run sockfilt for data connection\n";
        killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
        sendcontrol "500 no free ports!\r\n";
        return 0;
        return;
    }

    logmsg "Run sockfilt for data on pid $slavepid\n";
@@ -1102,6 +1105,12 @@ sub PASV_ftp {
        $pasvport = $2;
    }

    if($nodataconn) {
        # kill data sockfilter and make believe the client
        # that it is possible to establish a data connection.
        killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
    }

    if($cmd ne "EPSV") {
        # PASV reply
        my $p=$listenaddr;
@@ -1117,6 +1126,11 @@ sub PASV_ftp {
        sendcontrol sprintf("229 Entering Passive Mode (|||%d|)\n", $pasvport);
    }

    if($nodataconn) {
        logmsg "client fooled, running without data connection\n";
        return;
    }

    eval {
        local $SIG{ALRM} = sub { die "alarm\n" };

@@ -1162,13 +1176,16 @@ sub PORT_ftp {
    my $port;
    my $addr;

    # kill previous data connection sockfilt when alive
    killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');

    # We always ignore the given IP and use localhost.

    if($cmd eq "PORT") {
        if($arg !~ /(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)/) {
            logmsg "bad PORT-line: $arg\n";
            sendcontrol "500 silly you, go away\r\n";
            return 0;
            return;
        }
        $port = ($5<<8)+$6;
        $addr = "$1.$2.$3.$4";
@@ -1178,7 +1195,7 @@ sub PORT_ftp {
        if($arg !~ /(\d+)\|([^\|]+)\|(\d+)/) {
            logmsg "bad EPRT-line: $arg\n";
            sendcontrol "500 silly you, go away\r\n";
            return 0;
            return;
        }
        sendcontrol "200 Thanks for dropping by. We contact you later\r\n";
        $port = $3;
@@ -1186,12 +1203,31 @@ sub PORT_ftp {
    }
    else {
        sendcontrol "500 we don't like $cmd now\r\n";
        return 0;
        return;
    }

    if(!$port || $port > 65535) {
        print STDERR "very illegal PORT number: $port\n";
        return 1;
        return;
    }

    if($nodataconn) {
        # don't establish data connection back to client,
        # and don't send anything over control connection.
        logmsg "client fooled, will not connect back to him\n";
        return;
    }
    elsif($nodataconn425) {
        # don't establish data connection back to client,
        # reply with 425 over control connection.
        sendcontrol "425 Can't open data connection\r\n";
        return;
    }
    elsif($nodataconn421) {
        # don't establish data connection back to client
        # reply with 421 over control connection.
        sendcontrol "421 Connection timed out\r\n";
        return;
    }

    # We fire up a new sockfilt to do the data transfer for us.
@@ -1230,6 +1266,9 @@ sub customize {
    $retrnosize = 0;    # default is no use of RETRNOSIZE
    $pasvbadip = 0;     # default is no use of PASVBADIP
    $nosave = 0;        # default is to actually save uploaded data to file
    $nodataconn = 0;    # default is to establish or accept data channel
    $nodataconn425 = 0; # default is to not send 425 without data channel
    $nodataconn421 = 0; # default is to not send 421 without data channel
    %customreply = ();  #
    %customcount = ();  #
    %delayreply = ();   #
@@ -1271,6 +1310,21 @@ sub customize {
            logmsg "FTPD: instructed to use PASVBADIP\n";
            $pasvbadip=1;
        }
        elsif($_ =~ /NODATACONN425/) {
            # applies only to active FTP mode
            logmsg "FTPD: instructed to use NODATACONN425\n";
            $nodataconn425=1;
        }
        elsif($_ =~ /NODATACONN421/) {
            # applies only to active FTP mode
            logmsg "FTPD: instructed to use NODATACONN421\n";
            $nodataconn421=1;
        }
        elsif($_ =~ /NODATACONN/) {
            # applies to both active and passive FTP modes
            logmsg "FTPD: instructed to use NODATACONN\n";
            $nodataconn=1;
        }
        elsif($_ =~ /NOSAVE/) {
            # don't actually store the file we upload - to be used when
            # uploading insanely huge amounts