####################################
## SAMSUNG Security R&D Group	  ##
## Version 3.3 , 2012.03.08       ##
## Q&A: sign.server@samsung.com   ##
####################################
use Net::FTP; 
use File::Basename;
use Socket; 
use warnings;
use Sys::Hostname;
use File::Basename; 
use Cwd 'abs_path';

$retryCount = 7;
$PassiveTryStart = 4;
$sleepTime = 1;

$numArgs = $#ARGV + 1;
if ($numArgs < 3) {
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> prefix_\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>> -config <<config_filename>>\n";
	exit -1;
}

$runtype = $ARGV[0];
$modelname = $ARGV[1];
$inputfile = $ARGV[2];
###  version 3.1 add abs path 
$input_filename=basename($inputfile);
$prefix = "signed_";
$viewtype = "console";

###  version 3.1 add input file check
open(FP, "<$inputfile") || close (FP) || die "There is no input file: \"$inputfile\" Check input file";

###  version 3.1 add -out parameter 
if (!$ARGV[3]){
	$outputfile=$prefix.$input_filename;
}elsif ( $ARGV[3] eq '-out' ) {
	if(!$ARGV[4]){
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> prefix_\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>> -config <<config_filename>>\n";
	exit -1;
	}
	$outputfile = $ARGV[4];
	$output_file = basename($outputfile);
}elsif ($ARGV[3] ne NULL){
	$outputfile=$prefix.$ARGV[3].$input_filename;
}

###  version 3.1 add -config parameter 
if (!$ARGV[5]){
	$configfile="";
	$config_filename="";
}
elsif ( $ARGV[5] eq '-config' ) {
	if(!$ARGV[6]){
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> prefix_\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>>\n";
	print "perl SecureBootSign.pl secureboot SGH-T959_NA_XXX <<input_filename>> -out <<output_filename>> -config <<config_filename>>\n";
	exit -1;
	}
	$configfile= $ARGV[6];
	$config_filename=basename($configfile);
	open(FP, "<$configfile") || close (FP) || die "There is no config file: \"$configfile\" Check config file";
}


print "\n#########################################################################################################\n";
print "# (Version 3.3 , 2012.03.08)  SAMSUNG Security R&D Group                                                    #";
print "\n#########################################################################################################\n";
print "# perl SecureBootSign.pl $runtype $modelname $input_filename\n";
print "#########################################################################################################\n";
print "# Sign Type\t: $runtype \n";
print "# Model\t\t: $modelname";
print "\n# Input file\t: ".abs_path($inputfile);
print "\n# Output file\t: ".abs_path($outputfile);
if ($configfile ne ""){
print "\n# Config file\t: ".abs_path($configfile);
}

### create Log File
$debug_start_time = time();
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime;
my $start_time = sprintf("%04d-%02d-%02d-%02d-%02d-%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec);

#### check Client OS
	if ($^O eq 'MSWin32') {
		$BUILDENV = 'MSWin32';
	} elsif ($^O eq 'linux') {
		$BUILDENV = 'linux';
	} elsif ($^C eq 'cygwin') {
		$BUILDENV = 'MSWin32';
	} else {
		$BUILDENV = 'MSWin32';
	}
print "\n# CLIENT OS\t: $BUILDENV \n";


### Client SCM Build PC information
##linux
if ($BUILDENV eq 'linux'){
	$interface="eth0";
	$ifconfig = "/sbin/ifconfig";
	@lines=qx|$ifconfig $interface| ; 
	foreach(@lines){ 
		if(/inet addr:([\d.]+)/){ 
				$ipstamp = $1;
		} 
	} 
	$host = hostname;
	
} else {  
###windows
	$host = hostname();
	$ipstamp = inet_ntoa(scalar gethostbyname($host || 'localhost'));
}
$ftp_sub_path = "$runtype\@$debug_start_time\@$host\@$$";
### Connection Check
$RemoteServer1 = "10.254.124.52";
$RemoteServer2 = "10.90.13.36";

$ftp = Net::FTP->new($RemoteServer1) or $newerr=1;  
$RemoteServer = $RemoteServer1;
if ($newerr){
			$ftp = Net::FTP->new($RemoteServer2) or $newerr=1;  
			$RemoteServer = $RemoteServer2;
}
close $ftp;

$username = "scmbuild";
$password = "scmbuild";
$ftp_path = "/$modelname/$ftp_sub_path";

print "################################################\n";
print "# Create Working Folder to Signing Server \n";
print "# Signing Server IP: $RemoteServer \n";
print "################################################\n";
$count=0;
$newerr=0;
$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try $count $sleepTime\n";
			sleep($sleepTime);
		$newerr=0;
		
        if ( $count >= $PassiveTryStart ){
    		$ftp = Net::FTP->new($RemoteServer, Passive => 1) or $newerr=1;  
        } else {
    		$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
        }

		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
	push @ERRORS, "Error Can't connect to Certi-Server $RemoteServer" if $newerr;
	myerr() if $newerr;

### FTP login
$count=0;
$newerr=0;
$ftp->login($username,$password) or $newerr=1 ;  
if ($newerr==0) {
	print "# FTP login OK\n";
}

$ftp->binary(); 

### FTP path mkdir
$count=0;
$newerr=0;
$ftp->mkdir($ftp_path) or $newerr=1;
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try ftp mkdir $count $sleepTime\n";
			sleep($sleepTime);
		$newerr=0;
		$ftp->quit; 
        if ( $count >= $PassiveTryStart ){
    		$ftp = Net::FTP->new($RemoteServer, Passive => 1) or $newerr=1;  
        } else {
    		$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
        }
		$ftp->login($username,$password) or $newerr=1 ; 
		$ftp->binary() or $newerr=1; 
		
		$ftp->mkdir($ftp_path) or $newerr=1;
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
	push @ERRORS, "Error for server working folder" if $newerr;
	$ftp->quit if $newerr;
	myerr() if $newerr;
	print "  Model Working Folder: OK\n";

### FTP file upload
print "# FTP Sending \n";

$newerr=0;
$ftp->cwd($ftp_path) or $newerr=1;  
if ($newerr==0) {
	print "  FTP cwd OK\n";	
}
$count=0;
$newerr=0;
$ftp->put($inputfile,$ftp_path."/".$input_filename) or $newerr=1;  
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try ftp put $count $sleepTime\n";
			sleep($sleepTime);
		$newerr=0;
		
		$ftp->quit; 
        if ( $count >= $PassiveTryStart ){
    		$ftp = Net::FTP->new($RemoteServer, Passive => 1) or $newerr=1;  
        } else {
    		$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
        }
		$ftp->login($username,$password) or $newerr=1 ; 
		$ftp->binary() or $newerr=1; 
		$ftp->cwd($ftp_path) or $newerr=1;
		$ftp->put($inputfile,$ftp_path."/".$input_filename) or $newerr=1;  
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
	push @ERRORS, "Error Can't send the $input_filename file" if $newerr;
	$ftp->quit if $newerr;
	myerr() if $newerr;
	print "  $input_filename Transfer: OK\n";
	
## version 3.1 add config file upload
if($ARGV[5]){
$newerr=0;
$ftp->cwd($ftp_path) or $newerr=1;  
if ($newerr==0) {
	print "  FTP cwd OK\n";	
}
$count=0;
$newerr=0;
$ftp->put($configfile,$ftp_path."/".$config_filename) or $newerr=1;  
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try ftp put $count $sleepTime\n";
			sleep($sleepTime);
		$newerr=0;
		
		$ftp->quit; 
        if ( $count >= $PassiveTryStart ){
    		$ftp = Net::FTP->new($RemoteServer, Passive => 1) or $newerr=1;  
        } else {
    		$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
        }
		$ftp->login($username,$password) or $newerr=1 ; 
		$ftp->binary() or $newerr=1; 
		$ftp->cwd($ftp_path) or $newerr=1;
		$ftp->put($configfile,$ftp_path."/".$config_filename) or $newerr=1;  
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
	push @ERRORS, "Error Can't send the $config_filename file" if $newerr;
	$ftp->quit if $newerr;
	myerr() if $newerr;
	print "  $config_filename Transfer: OK\n";

}	
	
	
### Signing Binary 
print "# Signing Binary \n";
$count=0;
$newerr=0;

$handle = IO::Socket::INET->new("$RemoteServer:80") or $newerr=1;
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try http $count $sleepTime\n";
			sleep($sleepTime);
			$handle = IO::Socket::INET->new("$RemoteServer:80") or $newerr=1;
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
push @ERRORS, "Error from HTTP server $RemoteServer" if $newerr;
myerr() if $newerr;


$handle->send("GET http://$RemoteServer/SigningKey.php?model=$modelname&type=$runtype&filename=$input_filename&output=$output_file&filepath=$ftp_sub_path&prefix=$prefix&viewtype=$viewtype&ppa=$config_filename HTTP/1.0");
$handle->send("\n");
$handle->send("\n");
$handle->recv($line,1000);
close $handle;
#print $line;

if($line =~ /ERROR:/ ){
        	 			print "\n--SERVER ERRORS\n";
        	 			
                exit(-1);
}
if($line =~ /error/ ){
        	 			print "\n--SERVER ERRORS\n";
        	 			
                exit(-1);
}


### FTP Receiving
print "# FTP Receiving\n";
$count=0;
$newerr=0;
$ftp->get("$prefix$input_filename",$outputfile) or $newerr=1; 
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try ftp get $count $sleepTime\n";
			sleep($sleepTime);
		$newerr=0;
		
		$ftp->quit; 
        if ( $count >= $PassiveTryStart ){
    		$ftp = Net::FTP->new($RemoteServer, Passive => 1) or $newerr=1;  
        } else {
    		$ftp = Net::FTP->new($RemoteServer) or $newerr=1;  
        }
		$ftp->login($username,$password) or $newerr=1 ; 
		$ftp->binary() or $newerr=1; 
		$ftp->cwd($ftp_path) or $newerr=1;
		$ftp->get("$prefix$input_filename",$outputfile) or $newerr=1; 
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
	push @ERRORS, "Error Can't recv $outputfile file" if $newerr;
	$ftp->quit if $newerr;
	myerr() if $newerr;
	print "  $outputfile Transfer: OK\n";
	
$ftp->quit; 

print "# Signing Completed \n";
print "################################################\n";
print "# Remove Server Temp File ";
$count=0;
$newerr=0;

$handle = IO::Socket::INET->new("$RemoteServer:80") or $newerr=1;
if ($newerr){
	while ($count <= $retryCount ) {
			print "** re-try http $count $sleepTime\n";
			sleep($sleepTime);
			$handle = IO::Socket::INET->new("$RemoteServer:80") or $newerr=1;
		$count++;
		if ($newerr == 0 ) {
			last;
		}
	}
}
push @ERRORS, "Error from HTTP server $RemoteServer" if $newerr;
myerr() if $newerr;

$handle->send("GET http://$RemoteServer/DelConfirm.php?model=$modelname&type=$runtype&filepath=$ftp_sub_path&viewtype=$viewtype HTTP/1.0");
$handle->send("\n");
$handle->send("\n");
$handle->recv($line,1000);
close $handle;
#print $line;

if($line =~ /ERROR:/ ){
   	 			print "\n--SERVER ERRORS\n";
                exit(-1);
}
if($line =~ /error/ ){
   	 			print "\n--SERVER ERRORS\n";
                exit(-1);
}

$debug_end_time = time();
my $end_time = sprintf("%04d-%02d-%02d-%02d-%02d-%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec);
$debug_run_time =0;
$debug_run_time = $debug_end_time - $debug_start_time;

print "\n# Start Time\t\t: $start_time";
print "\n# End Time\t\t: $end_time";
print "\n# Running Time\t\t: $debug_run_time sec";
print "\n# Signing Server IP\t: $RemoteServer";
print "\n################################################\n\n";

sub myerr {
  print "** ERROR: ";
  print @ERRORS;
  print "\n";
  
  
  exit -1;
}

exit 0;
