#!/bin/bash scp_host_default="192.168.244.135" scp_user_default="user" scp_remote_path_default="./" strFileToUpload="" scp_host="" scp_user="" scp_remote_path="" bTestFailure=0 showUsage(){ if [ "$scp_host" = "" ]; then scp_host=$scp_host_default fi if [ "$scp_user" = "" ]; then scp_user=$scp_user_default fi if [ "$scp_remote_path" = "" ]; then scp_remote_path=$scp_remote_path_default fi strUsage="Usage:\r\n upload-file-with-hash [-t|--test-failure] file-to-upload [user@host:remote_path]\r\n\r\nDefaults:\r\n scp_host: $scp_host\r\n scp_user: $scp_user\r\n scp_remote_path: $scp_remote_path\r\n\r\n" printf "$strUsage" exit -1 } if [ $# -eq 0 ]; then showUsage fi for arg do for possibility in -h --help do if [ "$arg" == "$possibility" ]; then showUsage fi done for possibility in -t --test-failure do if [ "$arg" == "$possibility" ]; then bTestFailure=1 continue 2 fi done if [ "$strFileToUpload" == "" ]; then strFileToUpload=$arg continue else scp_host=$arg substring="@" if [[ $scp_host == *$substring* ]]; then re='(\S+)@(\S+)\:(.*)$' if [[ $scp_host =~ $re ]]; then scp_user=${BASH_REMATCH[1]} scp_host=${BASH_REMATCH[2]} scp_remote_path=${BASH_REMATCH[3]} else showUsage fi else showUsage fi fi done if [ "$strFileToUpload" == "" ]; then showUsage fi # Default arameters for the SFTP connection. # Public-key authentication is used to prevent # plain-text passwords from being embedded in this # file. if [ "$scp_host" == "" ]; then scp_host=$scp_host_default fi if [ "$scp_user" == "" ]; then scp_user=$scp_user_default fi if [ "$scp_remote_path" == "" ]; then scp_remote_path=$str_remote_path_default fi echo -ne " strFileToUpload: $strFileToUpload scp_host: $scp_host scp_user: $scp_user scp_remote_path: $scp_remote_path Test Failure: $bTestFailure " if [ ! -f $strFileToUpload ]; then echo " Source file not found: $strFileToUpload " exit 1 fi # A hash file path is composed strHashFile="$strFileToUpload#client_hash#.txt" # The hash file is generated strCmd="sha256sum --tag $strFileToUpload" echo "Creating hash file a la: $strCmd > $strHashFile" strHash=`$strCmd` if [ $bTestFailure -eq 0 ]; then echo $strHash > $strHashFile else # If --test-failure was present as an option, the last # character of the checksum file will be replaced with abc123 # in order to simulate a checksum value that is different # than expected, generating a failure condition. echo ${strHash%?}abc123 > $strHashFile fi if [ $bTestFailure -eq 0 ]; then # upload the File using the scp command strCmd="scp -oPasswordAuthentication=no $strFileToUpload $scp_user@$scp_host:$scp_remote_path" echo "Uploading '$strFileToUpload' a la \"$strCmd\" ..." $strCmd err=$? if [ "$err" != "0" ]; then echo "Failed to upload '$strFileToUpload' to remote host: $err" exit $err fi fi # upload the hash file strCmd="scp -oPasswordAuthentication=no $strHashFile $scp_user@$scp_host:$scp_remote_path" echo "Uploading hash file a la \"$strCmd\"..." $strCmd err=$? if [ "$err" != "0" ]; then echo "Failed to upload hash file '$strHashFile' to remote host: $err" exit $err fi # Now download the server's hash file that it generated # It may take some time for the hash file to exist, which is why # we do this in a loop, exiting with an error only if we exhaust # the retry_max server_hash_file="$strFileToUpload#server_hash#.txt" echo "Downloading server-generated hash file..." # Enter a retry loop that will make 10 attempts to download the # server-generated hash file. for i in {1..10} do # Give the server a few seconds to generate the hash file before # we try to download it... we'll retry if it's still not yet available, # but we'd like to increase the probability that the first time will # be a success! sleep 2 # Now, attempt to download it locally... scp $scp_user@$scp_host:$scp_remote_path$server_hash_file ./ err=$? if [ "$err" != "0" ]; then echo "Download of server hash-file failed: $err (attempt #$i)" echo " Waiting 2 seconds to try again..." sleep 2 else echo "Successfully downloaded server hash-file." # Now let's run a diff on the two files... a quick way to # see if the client and server hashes match: diff --strip-trailing-cr $server_hash_file $strHashFile 2>&1 > /dev/null diff=$? if [ "$diff" == "0" ]; then echo -e "\033[32;1mHashes match. Non-repudiation complete.\033[0m" exit 0 else echo -e "\033[31;1mWARNING: Hashes do not match.\033[0m" echo -e "\033[1mClient hash file:\033[0m" echo "------------------------------------------------------------" cat $strHashFile echo "" echo -e "\033[1mServer hash file:\033[0m" echo "------------------------------------------------------------" cat $server_hash_file echo "" exit 255 fi exit 0 fi done # if we ever get to this point, it indicates that none # of the retry attempts were successful in downloading # the server-generated hash file. Thus, we must exit # with the last error code returned from that attempt: exit $err