[issue1384175] random module - Provider DLL failed to initialize correctly

eryksun report at bugs.python.org
Fri Aug 21 15:55:08 CEST 2015


eryksun added the comment:

Albert, this issue was opened for Python 2.4 and was closed over 6 years ago. Open a new issue if you believe there's a bug or room for improvement in a currently supported Python version. 

FYI, on Windows _PyOS_URandom first initializes the Crypto API by calling [CryptAcquireContext][1]. As shown in the debug session below, this function requires the SystemRoot environment variable to be correctly defined. 

    C:\>cdb -g "C:\Program Files\Python27\python.exe"

    Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
    Copyright (c) Microsoft Corporation. All rights reserved.

    ...

    >>> import os
    >>> from ctypes import *
    ...
    >>> PROV_RSA_FULL = 1
    >>> CRYPT_VERIFYCONTEXT = 0xf0000000
    >>> CryptAcquireContextA = WinDLL('advapi32').CryptAcquireContextA 
    >>> hcrypt = c_void_p()

    >>> del os.environ['SystemRoot']
    >>> CryptAcquireContextA(byref(hcrypt), None, None, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
    ModLoad: 000007fe`fc480000 000007fe`fc498000   C:\Windows\system32\CRYPTSP.dll
    CryptAcquireContext:  CheckSignatureInFile failed at cryptapi.c line 5198
    CryptAcquireContext:  Failed to read registry signature value at cryptapi.c line 873
    0

    >>> os.environ['SystemRoot'] = 'C:\\Windows'
    >>> CryptAcquireContextA(byref(hcrypt), None, None, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
    ModLoad: 000007fe`fc180000 000007fe`fc1c7000   C:\Windows\system32\rsaenh.dll
    ModLoad: 000007fe`fcae0000 000007fe`fcaef000   C:\Windows\system32\CRYPTBASE.dll
    1
    >>> hcrypt
    c_void_p(4407952L)

It has always struck me as odd that this API uses the environment variable instead of the object manager's secured \SystemRoot object symbolic link. C'est la vie. 

Anyway, I don't think Python's os and subprocess modules should prevent you from shooting yourself in the foot here. When creating an environment block for a child process, excluding SystemRoot is generally a bad idea, but the language shouldn't get in the way. 

I think it's prudent to include at least all of the system-defined variables. Here's a function that calls [CreateEnvironmentBlock][2] and returns the system variables in a dict. It excludes user variables and doesn't inherit from the current process.

    import ctypes

    userenv = ctypes.WinDLL('userenv', use_last_error=True)

    def errcheck_bool(result, func, args):
        if not result:
            raise ctypes.WinError(ctypes.get_last_error())
        return args

    userenv.CreateEnvironmentBlock.argtypes = (ctypes.POINTER(ctypes.c_void_p),
                                               ctypes.c_void_p,
                                               ctypes.c_int)
    userenv.DestroyEnvironmentBlock.argtypes = (ctypes.c_void_p,)

    def get_system_environ():
        WCHAR_SIZE = ctypes.sizeof(ctypes.c_wchar)
        environ = {}
        cenv = ctypes.c_void_p()
        userenv.CreateEnvironmentBlock(ctypes.byref(cenv), None, 0)
        addr = cenv.value    
        try:
            while True:
                s = ctypes.c_wchar_p(addr).value
                if not s:
                    break
                i = s.find('=', 1)
                if i != -1:
                    environ[s[:i]] = s[i+1:]
                addr += (len(s) + 1) * WCHAR_SIZE
        finally:
            userenv.DestroyEnvironmentBlock(cenv)
        return environ

[1]: https://msdn.microsoft.com/en-us/library/aa379886
[2]: https://msdn.microsoft.com/en-us/library/bb762270

----------
nosy: +eryksun

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue1384175>
_______________________________________


More information about the Python-bugs-list mailing list