1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
#!/usr/local/bin/python
import sys ; sys.path = ['../../../'] + sys.path
import imp, os
from sys import modules
# Secure import:
def secimport(name, globals=None, locals=None, fromlist=None):
# Fast path: let's see if it's already in sys.modules.
# Two speed optimizations are worth mentioning:
# - We use 'modules' instead of 'sys.modules'; this saves a
# dictionary look-up per call.
# - It's also faster to use a try-except statement than
# to use modules.has_key(name) to check if it's there.
try:
return modules[name]
except KeyError:
pass
# See if it's a built-in module
m = imp.init_builtin(name)
if m:
return m
# See if it's a frozen module
m = imp.init_frozen(name)
if m:
return m
# Search the default path (i.e. sys.path).
# If this raises an exception, the module is not found --
# let the caller handle the exception.
fp, pathname, (suffix, mode, type) = imp.find_module(name)
# See what we got...
# Note that fp will be closed automatically when we return.
# Extensions are written in C, and can just be loaded.
if type == imp.C_EXTENSION:
return imp.load_dynamic(name, pathname)
# For a compiled or source file, we'll check if there is a *.pys file
# present in the same directory.
if type == imp.PY_COMPILED or type == imp.PY_SOURCE:
root, ext = os.path.splitext(pathname)
testfile = root + '.pys'
try:
print testfile
secfile=open(testfile, 'rb')
except IOError, tuple:
if (tuple[0]==2): pass # Ignore 'file not found' error
else: raise IOError, tuple
else:
# Check the signature (a signed hash of the code object).
# We could sign the whole code object, but that would
# require a huge key and would double the size of the
# *.pys file.
import marshal
from Crypto.Hash import MD5
fp.close() # Close the original *.pyc file
from testkey import * # Get the key for verification
signature=marshal.load(secfile) # Read signature
position=secfile.tell() # Save position
data=secfile.read() # Read code object
hash=MD5.new(data).digest() # Compute its hash value
##print 'sigcheck:', key.verify(hash, signature)
if (not key.verify(hash, signature)):
raise ImportError, 'Signature check of '+ testfile + ' failed'
secfile.seek(position) # Rewind pointer to the
# beginning of the code object
fp=secfile
del secfile
# Now we can happily import the compiled code object.
return imp.load_compiled(name, pathname, fp)
# Shouldn't get here at all.
raise ImportError, '%s: unknown module type (%d)' % (name, type)
if __name__=='__main__':
# A sample invocation of the secure import looks like this:
print 'Attempting secure import'
r=secimport('testkey')
print 'Secure import succeeded'
|