except ImportError:
    pass

try:
    import pkg_resources
except ImportError:
    pkg_resources = None


def popen(cmd,**kwds):
    kwds.setdefault("stdout",subprocess.PIPE)
    kwds.setdefault("stderr",subprocess.PIPE)
    return subprocess.Popen(cmd,**kwds)


KEY = RSAKey.generate(1024)

class TestSignedImp_DefaultImport(unittest.TestCase):

    def setUp(self):
        self.tdir = tempfile.mkdtemp()
        #  Ensure we have signedimp in the test environment.
        shutil.copytree(os.path.dirname(os.path.dirname(__file__)),
                        os.path.join(self.tdir,"signedimp"))
      
        #  Ensure we have pkgutil and pkg_resources in the test environment.
        with open(pkgutil.__file__,"rb") as fIn:
            with open(os.path.join(self.tdir,"pkgutil.pyc"),"wb") as fOut:
                shutil.copyfileobj(fIn,fOut)
        if pkg_resources is not None:
            pkgres_code = pkg_resources.resource_string("pkg_resources",
Beispiel #2
0
def sign_py2app_bundle(appdir, key=None, hash="sha1", check_modules=None, manager_class_name="SignedImportManager"):
    """Sign the py2app bundle found in the specified directory.

    This function signs the bundled modules found in the given py2app bundle
    directory, and modifies the bootstrapping code to enable signed imports
    using the given key.

    If the "check_modules" keyword arg is specified, the bootstrapping code
    checks that only those modules were imported before signed imports were
    enabled.  It's on by default to help you avoid errors - set it to False
    to disable this check.

    The bootstrapping code is embedded into the app's __boot__.py script.
    You'll need to be sure to sign this file as part of your applications
    signature.  The default signing scheme for OSX covers it as it's in the
    "Resources" folder, but if you write custom signing specs then you'll have
    to be careful.
    """
    if check_modules is None:
        check_modules = [
            "codecs",
            "encodings",
            "encodings.__builtin__",
            "encodings.codecs",
            "encodings.utf_8",
            "copy_reg",
            "site",
            "abc",
            "os",
            "wxhack",
            "posixpath",
            "_abcoll",
            "os.path",
            "genericpath",
            "stat",
            "warnings",
            "types",
            "linecache",
            "encodings.aliases",
            "encodings.encodings",
            "readline",
            "UserDict",
            "zlib",
        ]
    do_check_modules = check_modules != False
    #  Since the public key will be embedded in the executables, it's OK to
    #  generate a throw-away key that's purely for signing this particular app.
    if key is None:
        key = RSAKey.generate()
    pubkey = key.get_public_key()
    #  Build the bootstrap code and put it at start of __boot__.py.
    bscodestr = get_bootstrap_code()
    bscode = (
        """
import sys

#  Check the boot-time modules if necessary.
if %(do_check_modules)r and "signedimp" not in sys.modules:
    for mod in sys.modules:
        if mod in sys.builtin_module_names:
            continue
        if mod not in %(check_modules)r:
            err = "module '%%s' already loaded, integrity checks impossible"
            sys.stderr.write(err %% (mod,))
            sys.stderr.write("\\nTerminating the program.\\n")
            sys.exit(1)

#  Get a reference to the signedimp module, possibly by creating
#  it from raw code.
%(bscodestr)s

#  Add the specific key into the signed import machinery.
k = signedimp.%(pubkey)r
try:
    if isinstance(sys.meta_path[0],signedimp.SignedImportManager):
        sys.meta_path[0].add_valid_key(k)
    else:
        signedimp.%(manager_class_name)s([k]).install()
except (IndexError,AttributeError):
    signedimp.%(manager_class_name)s([k]).install()

"""
        % locals()
    )
    app = refreeze.Py2App(appdir)
    app.prepend_code(bscode)
    #  Sign the main library.zip
    libdir = os.path.join(appdir, "Contents", "Resources", "lib")
    libdir = os.path.join(libdir, "python%d.%d" % sys.version_info[:2])
    for nm in os.listdir(libdir):
        if nm.endswith(".zip"):
            sign_zipfile(os.path.join(libdir, nm), key, hash=hash)
    #  Sign a variety of potential code dirs
    try:
        sign_directory(os.path.join(libdir, "lib-dynload"), key, hash=hash)
    except EnvironmentError:
        pass
    try:
        sign_directory(os.path.join(libdir, "site-packages"), key, hash=hash)
    except EnvironmentError:
        pass
    try:
        sign_directory(os.path.join(libdir, "lib-tk"), key, hash=hash)
    except EnvironmentError:
        pass
    try:
        sign_directory(libdir, key, hash=hash)
    except EnvironmentError:
        pass
    #  Sign the main Resources dir.
    sign_directory(os.path.join(appdir, "Contents", "Resources"), key, hash=hash)
Beispiel #3
0
def sign_cxfreeze_app(appdir, key=None, hash="sha1", check_modules=None, manager_class_name="SignedImportManager"):
    """Sign the cxfreeze app found in the specified directory.

    This function signs the modules found in the given cxfreeze application
    directory, and modifies each executable to bootstrap signed imports using
    the given key.

    If the "check_modules" keyword arg is specified, the bootstrapping code
    checks that only those modules were imported before signed imports were
    enabled.  It's on by default to help you avoid errors - set it to False
    to disable this check.

    The bootstrapping code is embedded into each executable as an appended
    zipfile, which cxfreeze will helpfully place as the first item on sys.path.
    Due to an unfortunate limitation of the zipimport module, you'll need a
    patched version of python if you intend to sign the executables with e.g.
    Microsoft Authenticode; see Issue 5950 for more details:

        http://bugs.python.org/issue5950

    """
    initmod = "cx_Freeze__init__"
    if check_modules is None:
        check_modules = [
            "codecs",
            "encodings",
            "encodings.__builtin__",
            "encodings.codecs",
            "encodings.utf_8",
            "encodings.aliases",
            "encodings.encodings",
        ]
    do_check_modules = check_modules != False
    #  Since the public key will be embedded in the executables, it's OK to
    #  generate a throw-away key that's purely for signing this particular app.
    if key is None:
        key = RSAKey.generate()
    pubkey = key.get_public_key()
    #  Build the bootstrap code to be inserted into each executable.  Since
    #  it replaces the cx_Freeze__init__ script it needs to exec that once
    #  the signed imports are in place.
    bscode = (
        """
import sys

#  Check the boot-time modules if necessary.
if %(do_check_modules)r and "signedimp" not in sys.modules:
    for mod in sys.modules:
        if mod == "signedimp" or mod.startswith("signedimp."):
            continue
        if mod in sys.builtin_module_names:
            continue
        if mod not in %(check_modules)r:
            err = "module '%%s' already loaded, integrity checks impossible"
            sys.stderr.write(err %% (mod,))
            sys.stderr.write("\\nTerminating the program.\\n")
            sys.exit(1)

#  Since it's bundled into a zipfile, we always get at signedimp by
#  just importing it.  This will re-use an existing version if loaded.
import signedimp

#  Add the specific key into the signed import machinery.
k = signedimp.%(pubkey)r
try:
    if isinstance(sys.meta_path[0],signedimp.SignedImportManager):
        sys.meta_path[0].add_valid_key(k)
    else:
        signedimp.%(manager_class_name)s([k]).install()
except (IndexError,AttributeError):
    signedimp.%(manager_class_name)s([k]).install()
"""
        % locals()
    )
    #  Add the bootstrapping code to any executables found in the dir.
    for nm in os.listdir(appdir):
        fpath = os.path.join(appdir, nm)
        if not os.path.isfile(fpath) or not _is_executable(fpath):
            continue
        app = refreeze.CXFreeze(fpath)
        app.prepend_code(bscode)
        zf = zipfile.PyZipFile(fpath, "a")
        try:
            #  Make sure the signedimp module is bundled into the zipfile
            zf.writepy(os.path.dirname(signedimp.__file__))
            #  The python interpreter itself tries to import various encodings
            #  modules on startup.  They must also be bundled into the exe.
            #  Fortunately cxfreeze usually includes them as frozen modules
            #  directly into the exe; this is just to make sure.
            for nm2 in os.listdir(appdir):
                if nm2 == nm or not os.path.isfile(os.path.join(appdir, nm2)):
                    continue
                try:
                    zf2 = zipfile.ZipFile(os.path.join(appdir, nm2))
                except zipfile.BadZipfile:
                    pass
                else:
                    try:
                        for znm in zf2.namelist():
                            for incmod in ("encodings", "codecs"):
                                if znm.startswith(incmod):
                                    zf.writestr(znm, zf2.read(znm))
                    finally:
                        zf2.close()
        finally:
            zf.close()
    #  Sign any zipfiles in the appdir (inlcuding the exes from above)
    for nm in os.listdir(appdir):
        if not os.path.isfile(os.path.join(appdir, nm)):
            continue
        try:
            sign_zipfile(os.path.join(appdir, nm), key, hash=hash)
        except (zipfile.BadZipfile, EnvironmentError):
            pass
    #  Sign the main app dir.
    sign_directory(appdir, key, hash=hash)
Beispiel #4
0
def sign_py2exe_app(appdir, key=None, hash="sha1", check_modules=None, manager_class_name="SignedImportManager"):
    """Sign the py2exe app found in the specified directory.

    This function signs the bundled modules found in the given py2exe app
    directory, and modifies each executable to bootstrap the signed imports
    machinery using the given key.

    If the "check_modules" keyword arg is specified, the bootstrapping code
    checks that only those modules were imported before signed imports were
    enabled.  It's on by default to help you avoid errors - set it to False
    to disable this check.

    The bootstrapping code is embedded directly in the executable as part of
    py2exe's PYTHONSCRIPT resource.  It should therefore be covered by a
    signature over the executable itself.
    """
    if check_modules is None:
        check_modules = ["_memimporter"]
    do_check_modules = check_modules != False
    #  Since the public key will be embedded in the executables, it's OK to
    #  generate a throw-away key that's purely for signing this particular app.
    if key is None:
        key = RSAKey.generate()
    pubkey = key.get_public_key()
    #  Build the bootstrapping code needed for each executable.
    #  We init the bootstrap objects inside a function so they get their own
    #  namespace; py2exe's own bootstrap code does a "del sys" which would
    #  play havoc with the import machinery.
    bscodestr = get_bootstrap_code()
    bscode = (
        """
import sys

#  Check the boot-time modules if necessary.
if %(do_check_modules)r and "signedimp" not in sys.modules:
    for mod in sys.modules:
        if mod in sys.builtin_module_names:
            continue
        if mod not in %(check_modules)r:
            err = "module '%%s' already loaded, integrity checks impossible"
            sys.stderr.write(err %% (mod,))
            sys.stderr.write("\\nTerminating the program.\\n")
            sys.exit(1)

#  Get a reference to the signedimp module, possibly by creating
#  it from raw code.
%(bscodestr)s

#  Add the specific key into the signed import machinery.
k = signedimp.%(pubkey)r
try:
    if isinstance(sys.meta_path[0],signedimp.SignedImportManager):
        sys.meta_path[0].add_valid_key(k)
    else:
        signedimp.%(manager_class_name)s([k]).install()
except (IndexError,AttributeError):
    signedimp.%(manager_class_name)s([k]).install()

"""
        % locals()
    )
    #  Hack the bootstrap code into the start of each script to be run.
    for nm in os.listdir(appdir):
        if nm.endswith(".exe"):
            exepath = os.path.join(appdir, nm)
            try:
                app = refreeze.Py2Exe(exepath)
            except EnvironmentError:
                pass
            else:
                app.prepend_code(bscode)
    #  Sign anything that might be an importable zipfile.
    for nm in os.listdir(appdir):
        if nm.endswith(".exe") or nm.endswith(".zip"):
            try:

                sign_zipfile(os.path.join(appdir, nm), key, hash=hash)
            except zipfile.BadZipfile:
                pass
    #  Sign the appdir itself.  Doing this last means it will generate
    #  a correct hash for the modified exes and zipfiles.
    sign_directory(appdir, key, hash=hash)