Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,16 @@ intentionally re-add the 1024-bit roots back into your bundle by calling
all possible you should upgrade to a newer OpenSSL. However, if you have no
other option, this may work for you.


Windows Certificates store support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

On Windows, the CA and ROOT store will be automatically queried for available
certificates. The result will be appended to the cacert.pem file and put in the
directory defined in the environment variable APPDATA.

This is done each time the module is loaded.


.. _`Certifi`: http://certifi.io/en/latest/
.. _`Requests`: http://docs.python-requests.org/en/latest/
12 changes: 7 additions & 5 deletions certifi/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
This module returns the installation location of cacert.pem.
"""
import os
import sys
import warnings


Expand All @@ -17,11 +18,12 @@ class DeprecatedBundleWarning(DeprecationWarning):
provider to get them to stop using cross-signed roots.
"""


def where():
f = os.path.split(__file__)[0]

return os.path.join(f, 'cacert.pem')
if sys.platform == 'win32':
from .win import where
else:
def where():
f = os.path.split(__file__)[0]
return os.path.join(f, 'cacert.pem')


def old_where():
Expand Down
81 changes: 81 additions & 0 deletions certifi/win.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import ctypes
from ctypes import wintypes
import os

import wincertstore

"""
win.py
~~~~~~~~~~

This module copies the local store certificates to the current cacert.pem
file and caches it localy.
"""

# Create ctypes wrapper for Win32 functions we need, with correct argument/return types
_CreateMutex = ctypes.windll.kernel32.CreateMutexA
_CreateMutex.argtypes = [wintypes.LPCVOID, wintypes.BOOL, wintypes.LPCSTR]
_CreateMutex.restype = wintypes.HANDLE

_WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
_WaitForSingleObject.argtypes = [wintypes.HANDLE, wintypes.DWORD]
_WaitForSingleObject.restype = wintypes.DWORD

_ReleaseMutex = ctypes.windll.kernel32.ReleaseMutex
_ReleaseMutex.argtypes = [wintypes.HANDLE]
_ReleaseMutex.restype = wintypes.BOOL

_CloseHandle = ctypes.windll.kernel32.CloseHandle
_CloseHandle.argtypes = [wintypes.HANDLE]
_CloseHandle.restype = wintypes.BOOL

INFINITE = 0xFFFFFFFF


PEM_PATH = os.path.join(os.environ['APPDATA'], '.certifi', 'cacert.pem')


def where():
return PEM_PATH


def get_pems(store_names=None):
store_names = store_names or ("CA", "ROOT")
for store_name in store_names:
with wincertstore.CertSystemStore(store_name) as store:
for cert in store.itercerts(usage=wincertstore.SERVER_AUTH):
try:
pem_entry = '# Label: "{name}"\n{pem}'.format(
name=cert.get_name(),
pem=cert.get_pem().decode('ascii')
)
except UnicodeEncodeError:
pem_entry = ''

yield pem_entry


handle = _CreateMutex(None, False, 'Global_certifi')
_WaitForSingleObject(handle, INFINITE)

if not os.path.exists(PEM_PATH):
os.makedirs(os.path.dirname(PEM_PATH))

with open(PEM_PATH, 'w') as f:

local_pem = os.path.join(os.path.split(__file__)[0], 'cacert.pem')
with open(local_pem) as lf:
f.write(lf.read())

for pem in get_pems():
f.write(pem)

_ReleaseMutex(handle)
_CloseHandle(handle)


if __name__ == '__main__':
print(PEM_PATH)
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
package_data={'certifi': ['*.pem']},
# data_files=[('certifi', ['certifi/cacert.pem'])],
include_package_data=True,
extras_require={
':sys_platform=="win32"': ['wincertstore']
},
license='ISC',
classifiers=(
'Development Status :: 5 - Production/Stable',
Expand Down