check the sha1 checksum of the downloaded bootstrapfs tarball to protect ourselves...
authorS.Çağlar Onur <caglar@cs.princeton.edu>
Thu, 1 Jul 2010 04:09:33 +0000 (04:09 +0000)
committerS.Çağlar Onur <caglar@cs.princeton.edu>
Thu, 1 Jul 2010 04:09:33 +0000 (04:09 +0000)
source/steps/InstallBootstrapFS.py
source/utils.py

index 71ac9ab..1df89fb 100644 (file)
@@ -119,15 +119,27 @@ def Run( vars, log ):
         source_file= "/boot/%s" % (tarball)
         dest_file= "%s/%s" % (SYSIMG_PATH, tarball)
 
+        source_hash_file= "/boot/%s.sha1sum" % (tarball)
+        dest_hash_file= "%s/%s.sha1sum" % (SYSIMG_PATH, tarball)
+
         # 30 is the connect timeout, 14400 is the max transfer time in
         # seconds (4 hours)
         log.write( "downloading %s\n" % source_file )
-        result= bs_request.DownloadFile( source_file, None, None,
+        result = bs_request.DownloadFile( source_file, None, None,
                                          1, 1, dest_file,
                                          30, 14400)
+
         if result:
+            # Download SHA1 checksum file
+            result = bs_request.DownloadFile( source_hash_file, None, None,
+                                         1, 1, dest_hashfile,
+                                         30, 14400)
+            if not utils.check_file_hash(dest_file, dest_hash_file):
+                raise BootManagerException, "FATAL: SHA1 checksum does not match between %s and %s" % (source_file, source_hash_file)
+                
             log.write( "extracting %s in %s\n" % (dest_file,SYSIMG_PATH) )
-            result= utils.sysexec( "tar -C %s -xpf %s %s" % (SYSIMG_PATH,dest_file,uncompress_option), log )
+            result = utils.sysexec( "tar -C %s -xpf %s %s" % (SYSIMG_PATH,dest_file,uncompress_option), log )
             log.write( "Done\n")
             utils.removefile( dest_file )
         else:
index 7ac8e2f..6cd286a 100644 (file)
@@ -16,6 +16,7 @@ import socket
 import fcntl
 import string
 import exceptions
+import hashlib
 
 from Exceptions import *
 
@@ -247,3 +248,28 @@ def get_mac_from_interface(ifname):
         
     return ret
 
+def check_file_hash(filename, hash_filename):
+    """Check the file's integrity with a given hash."""
+    return sha1_file(filename) == open(hash_filename).read().split()[0].strip()
+
+def sha1_file(filename):
+    """Calculate sha1 hash of file."""
+    try:
+        m = hashlib.sha1()
+        f = file(filename, 'rb')
+        while True:
+            # 256 KB seems ideal for speed/memory tradeoff
+            # It wont get much faster with bigger blocks, but
+            # heap peak grows
+            block = f.read(256 * 1024)
+            if len(block) == 0:
+                # end of file
+                break
+            m.update(block)
+            # Simple trick to keep total heap even lower
+            # Delete the previous block, so while next one is read
+            # we wont have two allocated blocks with same size
+            del block
+        return m.hexdigest()
+    except IOError:
+        raise BootManagerException, "Cannot calculate SHA1 hash of %s" % filename