/pypy/module/_ssl/interp_win32.py
Python | 180 lines | 165 code | 12 blank | 3 comment | 15 complexity | 60c05651bf40470914c8f56db71fe2fe MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
- from rpython.rlib import rwin32
- from rpython.rtyper.lltypesystem import rffi, lltype
- from rpython.rtyper.tool import rffi_platform
- from rpython.translator.tool.cbuild import ExternalCompilationInfo
- from pypy.interpreter.gateway import unwrap_spec
- from pypy.interpreter.error import wrap_windowserror
- from rpython.rlib.rarithmetic import intmask
- eci = ExternalCompilationInfo(
- includes = ['windows.h', 'wincrypt.h'],
- libraries = ['crypt32'],
- )
- class CConfig:
- _compilation_info_ = eci
- X509_ASN_ENCODING = rffi_platform.ConstantInteger('X509_ASN_ENCODING')
- PKCS_7_ASN_ENCODING = rffi_platform.ConstantInteger('PKCS_7_ASN_ENCODING')
- CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger('CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG')
- CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger('CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG')
- CRYPT_E_NOT_FOUND = rffi_platform.ConstantInteger('CRYPT_E_NOT_FOUND')
- CERT_ENHKEY_USAGE = rffi_platform.Struct(
- 'CERT_ENHKEY_USAGE', [('cUsageIdentifier', rwin32.DWORD),
- ('rgpszUsageIdentifier', rffi.CCHARPP)])
- CERT_CONTEXT = rffi_platform.Struct(
- 'CERT_CONTEXT', [('pbCertEncoded', rffi.CCHARP),
- ('cbCertEncoded', rwin32.DWORD),
- ('dwCertEncodingType', rwin32.DWORD)])
- CRL_CONTEXT = rffi_platform.Struct(
- 'CRL_CONTEXT', [('pbCrlEncoded', rffi.CCHARP),
- ('cbCrlEncoded', rwin32.DWORD),
- ('dwCertEncodingType', rwin32.DWORD)])
- for k, v in rffi_platform.configure(CConfig).items():
- globals()[k] = v
- PCERT_ENHKEY_USAGE = lltype.Ptr(CERT_ENHKEY_USAGE)
- PCCERT_CONTEXT = lltype.Ptr(CERT_CONTEXT)
- PCCRL_CONTEXT = lltype.Ptr(CRL_CONTEXT)
- def external(name, argtypes, restype, **kw):
- kw['compilation_info'] = eci
- kw['calling_conv'] = 'win'
- kw['save_err'] = rffi.RFFI_SAVE_LASTERROR
- return rffi.llexternal(
- name, argtypes, restype, **kw)
- CertOpenSystemStore = external(
- 'CertOpenSystemStoreA', [rffi.VOIDP, rffi.CCHARP], rwin32.HANDLE)
- CertCloseStore = external(
- 'CertCloseStore', [rwin32.HANDLE, rwin32.DWORD], rwin32.BOOL)
- CertGetEnhancedKeyUsage = external(
- 'CertGetEnhancedKeyUsage',
- [PCCERT_CONTEXT, rwin32.DWORD, PCERT_ENHKEY_USAGE, rwin32.LPDWORD],
- rwin32.BOOL)
- CertEnumCertificatesInStore = external(
- 'CertEnumCertificatesInStore',
- [rwin32.HANDLE, PCCERT_CONTEXT], PCCERT_CONTEXT)
- CertFreeCertificateContext = external(
- 'CertFreeCertificateContext', [PCCERT_CONTEXT], rwin32.BOOL)
- CertEnumCRLsInStore = external(
- 'CertEnumCRLsInStore',
- [rwin32.HANDLE, PCCRL_CONTEXT], PCCRL_CONTEXT)
- CertFreeCRLContext = external(
- 'CertFreeCRLContext', [PCCRL_CONTEXT], rwin32.BOOL)
- def w_certEncodingType(space, encodingType):
- if encodingType == X509_ASN_ENCODING:
- return space.wrap("x509_asn")
- elif encodingType == PKCS_7_ASN_ENCODING:
- return space.wrap("pkcs_7_asn")
- else:
- return space.wrap(encodingType)
- def w_parseKeyUsage(space, pCertCtx, flags):
- with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as size_ptr:
- if not CertGetEnhancedKeyUsage(pCertCtx, flags,
- lltype.nullptr(CERT_ENHKEY_USAGE), size_ptr):
- last_error = rwin32.lastSavedWindowsError()
- if last_error.winerror == CRYPT_E_NOT_FOUND:
- return space.w_True
- raise wrap_windowserror(space, last_error)
- size = intmask(size_ptr[0])
- with lltype.scoped_alloc(rffi.CCHARP.TO, size) as buf:
- usage = rffi.cast(PCERT_ENHKEY_USAGE, buf)
- # Now get the actual enhanced usage property
- if not CertGetEnhancedKeyUsage(pCertCtx, flags, usage, size_ptr):
- last_error= rwin32.lastSavedWindowsError()
- if last_error.winerror == CRYPT_E_NOT_FOUND:
- return space.w_True
- raise wrap_windowserror(space, last_error)
- result_w = [None] * usage.c_cUsageIdentifier
- for i in range(usage.c_cUsageIdentifier):
- if not usage.c_rgpszUsageIdentifier[i]:
- continue
- result_w[i] = space.wrap(rffi.charp2str(
- usage.c_rgpszUsageIdentifier[i]))
- return space.newset(result_w)
- @unwrap_spec(store_name=str)
- def enum_certificates_w(space, store_name):
- """enum_certificates(store_name) -> []
- Retrieve certificates from Windows' cert store. store_name may be one of
- 'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.
- The function returns a list of (bytes, encoding_type, trust) tuples. The
- encoding_type flag can be interpreted with X509_ASN_ENCODING or
- PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the
- boolean True."""
- result_w = []
- pCertCtx = lltype.nullptr(CERT_CONTEXT)
- hStore = CertOpenSystemStore(None, store_name)
- if not hStore:
- raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
- try:
- while True:
- pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)
- if not pCertCtx:
- break
- w_cert = space.newbytes(
- rffi.charpsize2str(pCertCtx.c_pbCertEncoded,
- intmask(pCertCtx.c_cbCertEncoded)))
- w_enc = w_certEncodingType(space, pCertCtx.c_dwCertEncodingType)
- w_keyusage = w_parseKeyUsage(
- space, pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG)
- if space.is_w(w_keyusage, space.w_True):
- w_keyusage = w_parseKeyUsage(
- space, pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG)
- result_w.append(space.newtuple([w_cert, w_enc, w_keyusage]))
- except:
- raise
- finally:
- if pCertCtx:
- # loop ended with an error, need to clean up context manually
- CertFreeCertificateContext(pCertCtx)
- if not CertCloseStore(hStore, 0):
- # This error case might shadow another exception.
- raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
- return space.newlist(result_w)
- @unwrap_spec(store_name=str)
- def enum_crls_w(space, store_name):
- """enum_crls(store_name) -> []
- Retrieve CRLs from Windows' cert store. store_name may be one of
- 'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.
- The function returns a list of (bytes, encoding_type) tuples. The
- encoding_type flag can be interpreted with X509_ASN_ENCODING or
- PKCS_7_ASN_ENCODING."""
- result_w = []
- pCrlCtx = lltype.nullptr(CRL_CONTEXT)
- hStore = CertOpenSystemStore(None, store_name)
- if not hStore:
- raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
- try:
- while True:
- pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)
- if not pCrlCtx:
- break
- w_crl = space.newbytes(
- rffi.charpsize2str(pCrlCtx.c_pbCrlEncoded,
- intmask(pCrlCtx.c_cbCrlEncoded)))
- w_enc = w_certEncodingType(space, pCrlCtx.c_dwCertEncodingType)
- result_w.append(space.newtuple([w_crl, w_enc]))
- except:
- raise
- finally:
- if pCrlCtx:
- # loop ended with an error, need to clean up context manually
- CertFreeCRLContext(pCrlCtx)
- if not CertCloseStore(hStore, 0):
- # This error case might shadow another exception.
- raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
- return space.newlist(result_w)