MOON
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4
System: Linux csr818.wilogic.com 2.6.18-419.el5xen #1 SMP Fri Feb 24 22:50:37 UTC 2017 x86_64
User: digitals (531)
PHP: 5.4.45
Disabled: NONE
Upload Files
File: //scripts.20110531.215904.25158/getremotecpmove
#!/usr/bin/perl
# cpanel - getremotecpmove                        Copyright(c) 2010 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

BEGIN {
    unshift @INC, '/usr/local/cpanel';
    $SIG{__WARN__} = sub {
        my $errlt = localtime( time() );
        my $safe_longmess = Carp::longmess(@_);
        $safe_longmess =~ s/('pass'\,?\s+\')[^\']+/$1__HIDDEN__/g;
        print "(internal error) $errlt [$$] warn: " . $safe_longmess;
    };
    $SIG{__DIE__} = sub {
        my $errlt = localtime( time() );
        my $safe_longmess = Carp::longmess(@_);
        $safe_longmess =~ s/('pass'\,?\s+\')[^\']+/$1__HIDDEN__/g;
        print "(internal error) $errlt [$$] error: " . $safe_longmess;
    };
}

use strict;
use Socket                ();
use Cpanel::HttpRequest   ();
use Cpanel::Encoder::URI  ();
use Cpanel::Encoder::Tiny ();
use Cpanel::MD5           ();
use Cpanel::Filesys       ();

$| = 1;

my $httpClient = Cpanel::HttpRequest->new( 'hideOutput' => 0 );
chdir("/scripts");

my $host        = $ARGV[0];
my $user        = $ARGV[1];
my $domain      = $ARGV[2];
my $usebestdisk = $ARGV[3];
my $permitfallb = $ARGV[4];

$host   =~ s/\///g;
$user   =~ s/\///g;
$domain =~ s/\///g;
$host   =~ s/\.\.//g;
$user   =~ s/\.\.//g;
$domain =~ s/\.\.//g;
$domain =~ s/[\s\n\t\r]*//g;
my $pass = <STDIN>;
$pass =~ s/\n//g;

my $extractdir;
my $md5sum;
my $part = '/home';
if ($usebestdisk) {
    $part = Cpanel::Filesys::getmntpoint();
}

my @PKGDEBUG;
my ( $fetch_ok, $archive_file, $extractdir, $md5sum, $pkgdebug ) = fetch_acct_by_cpanel( 'user' => $user, 'host' => $host, 'domain' => $domain, 'pass' => $pass, 'part' => $part );
push @PKGDEBUG, $pkgdebug;


if ( !$fetch_ok ) {
    print "Failed to fetch cpmove file via cPanel XML-API.\n";
    if ($permitfallb) {
        ( $fetch_ok, $archive_file, $extractdir, $md5sum, $pkgdebug ) = fetch_acct_by_ftp_and_http( 'user' => $user, 'host' => $host, 'domain' => $domain, 'pass' => $pass, 'part' => $part );
        push @PKGDEBUG, $pkgdebug;
    } else {
        print "Terminating because fallback to ftp+cgi was not enabled.\n";
        exit;
    }
}

if ($fetch_ok) {
    if ($md5sum) {
        my $newmd5 = Cpanel::MD5::getmd5sum($archive_file);
        if ( $newmd5 eq $md5sum ) {
            print "Checksum Matches!\n";
        }
        else {
            print "Checksum Failure [[$newmd5]] [[$md5sum]]...trace information follows...<table width=\"100%\" style=\"border: 1px #000 solid;\"><tr><td><pre>" . join( "\n\n\n", @PKGDEBUG ) . "</pre></td></tr></table>\n\n";
            exit;
        }
    }
    elsif ( -z $archive_file ) {
        print "Checksum Failure: Failed to download account file.\n";
        exit;
    }
    print "extract dir name is: $extractdir\n";
    print "pkgacctfile is: $archive_file\n";
    print "MOVE IS GOOD!\n";
}
else {
    print "Failed to fetch account via cpanel and ftp/web\n";
}

sub fetch_acct_by_cpanel {
    my %OPTS = @_;
    my $host = $OPTS{'host'};
    my $user = $OPTS{'user'};
    my $pass = $OPTS{'pass'};
    my $part = $OPTS{'part'};

    print "Trying to fetch cpmove file via cPanel XML-API!\n";

    require MIME::Base64;
    require Net::SSLeay;
    {
        local $SIG{'__DIE__'};
        require IO::Socket::SSL;
        IO::Socket::SSL->import('inet4'); # see case 16674
    }
    print "Fetching current backups from remote server....";
    my ($current_bck_page,$current_bck_response,$current_bck_ref) = get_current_backups( $host, $user, $pass );
    print ".." . (scalar keys %$current_bck_ref) . " backups found...";
    print "Done\n";

    foreach my $bck (keys %$current_bck_ref) {
        if ($current_bck_ref->{$bck}) {
            print "A backup to the file $bck is currently in progress on the remote server.\n";
            print "Please wait until it is complete and try again.\n"; 
            exit 1;
        }
    } 

    if ($current_bck_response =~ /401/) {
        return 0;
    }

    print "Starting the backup...";

    my $encoded_request = '/xml-api/cpanel?xmlin=%3Ccpanelaction%3E%3Capiversion%3E1%3C/apiversion%3E%3Cmodule%3EFileman%3C/module%3E%3Cfunc%3Efullbackup%3C/func%3E%3C/cpanelaction%3E';
    my $decoded_request = Cpanel::Encoder::URI::uri_decode_str($encoded_request);

    #start the backup
    my ( $page, $response, %reply_headers ) = Net::SSLeay::get_https( $host, 2083, 
        $encoded_request, 
        Net::SSLeay::make_headers( Authorization => 'Basic ' . MIME::Base64::encode( "$user:$pass", '' ) ) );
    print "Done\n";

    print "Waiting for backup to start...";
    sleep(10);
    print "Done\n";

    print "Checking remote server for backups...";  
    my ($new_bck_page,$new_bck_response,$new_bck_ref)  = get_current_backups( $host, $user, $pass );
    print ".." . (scalar keys %$new_bck_ref) . " backups found.\n";
    my $backup_file;
    foreach my $back ( keys %{$new_bck_ref} ) {
        if ( !exists $current_bck_ref->{$back} ) {
            $backup_file = $back;
            last;
        }
    }

    if ( !$backup_file ) {
        print "Failed to start the backup on the remote machine (if a previous backup is in progress you will need to wait until it is complete)!\n";
        print "(Trace information follows for backup start request)...<table width=\"100%\" style=\"border: 1px #000 solid;\"><tr><td><pre>" . Cpanel::Encoder::Tiny::safe_html_encode_str($decoded_request) . "</pre></td></tr><td><pre>" . Cpanel::Encoder::Tiny::safe_html_encode_str($page) . "</pre></td></tr></table>\n";
        print "(Trace information follows for initial backups)...<table width=\"100%\" style=\"border: 1px #000 solid;\"><tr><td><pre>" . Cpanel::Encoder::Tiny::safe_html_encode_str($current_bck_page) . "</pre></td></tr></table>\n";
        print "(Trace information follows for backups after request started)...<table width=\"100%\" style=\"border: 1px #000 solid;\"><tr><td><pre>" . Cpanel::Encoder::Tiny::safe_html_encode_str($new_bck_page) . "</pre></td></tr></table>\n";
        return (0);
    }

    print "Remote server is creating backup to $backup_file!\n";
    print "Starting wait cycle for remote backup.\n";
    my $bck_ref;
    my $bck_page;
    my $bck_response;
    for ( 0 .. 1500 ) {
        ($bck_page,$bck_response,$bck_ref) = get_current_backups( $host, $user, $pass );
        if ( exists $bck_ref->{$backup_file} ) {
            if ( !$bck_ref->{$backup_file} ) {
                last;
            }
            else {
                print "Backup into $backup_file is still in progress.\nChecking again in 60 seconds...\n";
                sleep(15);
                print "Checking again in 45 seconds...\n";
                sleep(15);
            }
        }
        else {
            print "Backup file $backup_file went away!\n";
            return (0);
        }
        print "Checking again in 30 seconds...\n";
        sleep(15);
        print "Checking again in 15 seconds...\n";
        sleep(15);
    }


    print "Downloading $backup_file....";
    chdir($part) || return (0);

    my $client = IO::Socket::SSL->new("$host:2083") || do {
        print "Could not connect to $host on port 2083\n";
        return (0);
    };

    my $now = time();
    my $dest = "cpmove-$user-$now.tmp";

    print {$client} "GET /download/$backup_file HTTP/1.0\r\n";
    print {$client} "Connection: close\r\n";
    print {$client} ( "Authorization: Basic " . MIME::Base64::encode_base64( $user . ':' . $pass ) . "\r\n\r\n" );
    my $cl      = 1;
    my $percent = 0;
    open( my $out_fh, '>', $dest );
    while ( readline($client) ) {
        alarm(20);
        if (/^content-length: (\d+)/i) {
            print;
            $cl = $1;
        }
        last if (/^[\r\n]*$/);
    }
    alarm(0);
    my $bytes;
    my $new_percent;
    my $cc = 0;
    my $buffer;
    my $bytesread = 0;
    while ( $bytes = read( $client, $buffer, 65536 ) ) {
        alarm(90);
        $bytesread += $bytes;
        $cc++;
        if ( $cc == 170 ) {
            $new_percent = int( ( $bytesread / $cl ) * ( $cl == 1 ? 1 : 100 ) );
            if ( $new_percent != $percent ) {
                $percent = $new_percent;
                print "..${percent}" . ( $cl == 1 ? '' : '%' ) . "..\n";
            }
            $cc = 0;
        }
        print {$out_fh} $buffer;
    }
    alarm(0);
    close($out_fh);
    close($client);
    print "Done\n";

    my $extractdir = $backup_file;
    $extractdir =~ s/(\.tar)?(\.gz)?$//g;

    system( '/bin/mv', '-f', $dest, "$part/cpmove-$user-$now.tar.gz" );
    return ( 1, "$part/cpmove-$user-$now.tar.gz", $extractdir, '', '' );
}

sub get_current_backups {
    my ( $host, $user, $pass ) = @_;

    #look for backups
    my %CURRENT_BACKUPS;

    my ( $page, $response, %reply_headers ) = Net::SSLeay::get_https( $host, 2083, '/xml-api/cpanel?xmlin=%3Ccpanelaction%3E%3Capiversion%3E1%3C/apiversion%3E%3Cmodule%3EFileman%3C/module%3E%3Cfunc%3Elistfullbackups%3C/func%3E%3C/cpanelaction%3E', Net::SSLeay::make_headers( Authorization => 'Basic ' . MIME::Base64::encode( "$user:$pass", '' ) ) );
    if ($response =~ /401/) {
        print "cPanel Login Failed\n";
        return ($page,$response,{});
    }

    my $stripped_page = $page;
    $stripped_page =~ s/\<[^\>]+\>/\n/g;    #strip xml
    $stripped_page = Cpanel::Encoder::Tiny::safe_html_decode_str($stripped_page);
    foreach my $req ( split( /\n/, $stripped_page ) ) {
        if ( $req =~ /(backup-[^\"\>]+)/ ) {
            my $file = $1;
            $file =~ s/\s*$//g;
            my ( $bckfile, $progress ) = split( /\s+/, $file, 2 );
            $CURRENT_BACKUPS{$bckfile} = ( $progress =~ /progress/i ? 1 : 0 );
        }
    }

    return ($page,$response,\%CURRENT_BACKUPS);
}

sub fetch_acct_by_ftp_and_http {
    my %OPTS   = @_;
    my $host   = $OPTS{'host'};
    my $domain = $OPTS{'domain'};
    my $user   = $OPTS{'user'};
    my $pass   = $OPTS{'pass'};
    my $part   = $OPTS{'part'};

    print "Trying to fetch cpmove file via ftp+cgi!\n";
    my $md5sum;
    my $archive_name;
    my $uid;

    $SIG{'ALRM'} = sub {
        print "Copy Session Timed out!\n";
        die;
    };

    alarm(7200);
    require Net::FTP;
    my $ftp = Net::FTP->new( "$host", Debug => 0 );
    print "Attempting to login as $user to $host via ftp\n";
    if ( $ftp->login( $user, $pass ) ) {
        print "Login ok\n";
    }
    else {
        print "FTP Login Failed\n";
        exit;
    }

    $ftp->mkdir( "public_html/cgi-bin/cpdownload", 1 );
    $ftp->site("chmod 755 public_html/cgi-bin/cpdownload");
    $ftp->cwd("public_html/cgi-bin/cpdownload");
    print "Uploading Htaccess\n";
    $ftp->put(".htaccess");
    print "Uploading Wrapper\n";
    $ftp->put("cpanelwrap.c");
    print "Uploading Dectector\n";
    $ftp->put("cpanelwrap.cgi");
    print "Uploading Packager\n";
    $ftp->put("cpaneldownload.cgi");
    print "Uploading Downloader\n";
    $ftp->put("cpaneldownacct.cgi");
    print "Uploading Killer\n";
    $ftp->put("cpanelkill.cgi");
    print "Chmoding scripts\n";
    $ftp->site("chmod 755 cpanelwrap.cgi");
    $ftp->site("chmod 755 cpaneldownacct.cgi");
    $ftp->site("chmod 755 cpaneldownload.cgi");
    $ftp->site("chmod 755 cpanelkill.cgi");

    my $odebug    = '';
    my $hassuexec = 0;
    my $script    = 'cpanelwrap.cgi';
    my @FOPTS     = ( [ $host, "/~${user}/cgi-bin/cpdownload/${script}?${user}" ], [ $host, "/cgi-bin/cpdownload/${script}?${user}" ] );
    my $req;
    foreach my $hoste (@FOPTS) {
        my ( $host, $url ) = @{$hoste};
        $req = $httpClient->request(
            'host'     => $host,
            'url'      => $url,
            'protocol' => 0,
        );
        next if ( $req !~ /UID/ );
        foreach ( split( /\n/, $req ) ) {
            $odebug .= $_;
            if (/MYUID: (\d+)/) {
                $uid = $1;
            }
            if (/REALUID: (\d+)/) {
                if ( $1 == $uid ) {
                    $hassuexec = 1;
                }
            }
        }
        last;
    }

    if ($uid) {
        print "Found uid to be: $uid\n";
    }
    else {
        print "Unable to get uid of remote account...(trace information follows)...<table width=\"100%\" style=\"border: 1px #000 solid;\"><tr><td><pre>$odebug</pre><br />" . Cpanel::Encoder::Tiny::safe_html_encode_str($req) . "</td></tr></table>\n";
        exit;
    }

    mkdir( "/root/cpmove",            0700 );
    mkdir( "/root/cpmove/$host-$uid", 0700 );
    chdir("/root/cpmove/$host-$uid");
    print "Compiling wrapper\n";
    system( "gcc", '-m32',"-DUID=$uid", "/scripts/cpanelwrap.c",  "-o", "cpanelwrapper.cgi" );
    system( "gcc", '-m32',"-DUID=$uid", "/scripts/cpanelwrap2.c", "-o", "cpanelkiller.cgi" );
    print "Uploading wrapper\n";
    $ftp->put("cpanelwrapper.cgi");
    $ftp->put("cpanelkiller.cgi");
    print "Chmodding wrapper\n";
    $ftp->site("chmod 4755 cpanelwrapper.cgi");
    $ftp->site("chmod 4755 cpanelkiller.cgi");
    unlink("cpanelwrapper.cgi");
    chdir("/scripts");
    system( "/bin/rm", "-rf", '--', "/root/cpmove/$host-$uid" );

    print "Closing FTP Control\n";
    $ftp->quit;

    my $proto = getprotobyname('tcp');
    socket( Socket_Handle, &Socket::AF_INET, &Socket::SOCK_STREAM, $proto );
    my $iaddr = gethostbyname($host);
    my $port  = getservbyname( 'http', 'tcp' );
    my $sin   = Socket::sockaddr_in( $port, $iaddr );
    connect( Socket_Handle, $sin );

    alarm(7200);
    if ( !$hassuexec ) {
        print "Packing Account using non-suexec method\n";
        send Socket_Handle, "POST /~${user}/cgi-bin/cpdownload/cpanelwrapper.cgi HTTP/1.0\n", 0;
    }
    else {
        print "Packing Account using suexec method\n";
        send Socket_Handle, "POST /~${user}/cgi-bin/cpdownload/cpaneldownload.cgi HTTP/1.0\n", 0;
    }
    if ( $domain ne "" ) {
        send Socket_Handle, "Host: ${domain}\n", 0;
    }
    my $ct = "user=${user}&pass=${pass}";
    my $cl = length($ct);

    send Socket_Handle, "Content-length: ${cl}\n", 0;
    send Socket_Handle, "Connection: close\n\n",   0;
    send Socket_Handle, $ct, 0;

    my $pkgdebug  = '';
    my $inheaders = 1;
    my $archive_name;
    my $md5sum;
    while (<Socket_Handle>) {
        $pkgdebug .= $_;
        s/\n//g;
        if ( !$inheaders ) {
            if (/^md5sum is: (\S+)/) {
                $md5sum = $1;
                print "FOUND MD5 to be : $md5sum\n";
            }
            if (/^\s*DOWNLOAD\s+READY\s+in\s+(\S+)/) {
                ($archive_name) = $1 =~ m/([^\/]+)$/;
                $archive_name =~ s/[.]tar[.]gz$//;
            }
            print;
            print "\n";
        }
        if ( /^$/ || /Content-Type/ ) { $inheaders = 0; }
    }
    shutdown( Socket_Handle, 2 );
    close(Socket_Handle);

    print "Downloading Tarball\n";
    chdir $part || return (0);
    mkdir( "cptmp", 0700 );
    chdir("$part/cptmp") || return (0);
    mkdir( $user, 0700 );
    chdir $user || return (0);
    alarm(7200);

    $httpClient->download( "http://$host/~${user}/cgi-bin/cpdownload/cpaneldownacct.cgi?${user}", "cpmove-${user}.tmp" );

    my $script = '';
    if ( !$hassuexec ) {
        $script = "cpanelkiller.cgi";
        print "Removing Scripts using non-suexec method\n";
    }
    else {
        $script = "cpanelkill.cgi";
        print "Removing Scripts using suexec method\n";
    }

    my @FOPTS = ( [ $host, "/~${user}/cgi-bin/cpdownload/${script}?${user}" ], [ $host, "/cgi-bin/cpdownload/${script}?${user}" ] );
    foreach my $hoste (@FOPTS) {
        my ( $host, $url ) = @{$hoste};
        my $req = $httpClient->request(
            'host'     => $host,
            'url'      => $url,
            'protocol' => 0,
        );
        if ( $req =~ /UNLINKED/i ) {
            print "Removed archive from remote server ok!\n";
            last;
        }
    }

    if ( !-e "cpmove-${user}.tmp" || -z _ ) {
        print "Failed to download account package!\n";
        unlink "cpmove-${user}.tmp";
        return ( 0, '', '', $pkgdebug );
    }
    my $now = time();
    system( '/bin/mv', '-f', '--', "cpmove-$user.tmp", "$part/cpmove-$user-$now.tar.gz" );

    alarm(0);

    return ( 1, "$part/cpmove-$user-$now.tar.gz", 'cpmove-' . $user, $md5sum, $pkgdebug );
}