PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/_ssl/interp_win32.py

https://bitbucket.org/pypy/pypy/
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
  1. from rpython.rlib import rwin32
  2. from rpython.rtyper.lltypesystem import rffi, lltype
  3. from rpython.rtyper.tool import rffi_platform
  4. from rpython.translator.tool.cbuild import ExternalCompilationInfo
  5. from pypy.interpreter.gateway import unwrap_spec
  6. from pypy.interpreter.error import wrap_windowserror
  7. from rpython.rlib.rarithmetic import intmask
  8. eci = ExternalCompilationInfo(
  9. includes = ['windows.h', 'wincrypt.h'],
  10. libraries = ['crypt32'],
  11. )
  12. class CConfig:
  13. _compilation_info_ = eci
  14. X509_ASN_ENCODING = rffi_platform.ConstantInteger('X509_ASN_ENCODING')
  15. PKCS_7_ASN_ENCODING = rffi_platform.ConstantInteger('PKCS_7_ASN_ENCODING')
  16. CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger('CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG')
  17. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger('CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG')
  18. CRYPT_E_NOT_FOUND = rffi_platform.ConstantInteger('CRYPT_E_NOT_FOUND')
  19. CERT_ENHKEY_USAGE = rffi_platform.Struct(
  20. 'CERT_ENHKEY_USAGE', [('cUsageIdentifier', rwin32.DWORD),
  21. ('rgpszUsageIdentifier', rffi.CCHARPP)])
  22. CERT_CONTEXT = rffi_platform.Struct(
  23. 'CERT_CONTEXT', [('pbCertEncoded', rffi.CCHARP),
  24. ('cbCertEncoded', rwin32.DWORD),
  25. ('dwCertEncodingType', rwin32.DWORD)])
  26. CRL_CONTEXT = rffi_platform.Struct(
  27. 'CRL_CONTEXT', [('pbCrlEncoded', rffi.CCHARP),
  28. ('cbCrlEncoded', rwin32.DWORD),
  29. ('dwCertEncodingType', rwin32.DWORD)])
  30. for k, v in rffi_platform.configure(CConfig).items():
  31. globals()[k] = v
  32. PCERT_ENHKEY_USAGE = lltype.Ptr(CERT_ENHKEY_USAGE)
  33. PCCERT_CONTEXT = lltype.Ptr(CERT_CONTEXT)
  34. PCCRL_CONTEXT = lltype.Ptr(CRL_CONTEXT)
  35. def external(name, argtypes, restype, **kw):
  36. kw['compilation_info'] = eci
  37. kw['calling_conv'] = 'win'
  38. kw['save_err'] = rffi.RFFI_SAVE_LASTERROR
  39. return rffi.llexternal(
  40. name, argtypes, restype, **kw)
  41. CertOpenSystemStore = external(
  42. 'CertOpenSystemStoreA', [rffi.VOIDP, rffi.CCHARP], rwin32.HANDLE)
  43. CertCloseStore = external(
  44. 'CertCloseStore', [rwin32.HANDLE, rwin32.DWORD], rwin32.BOOL)
  45. CertGetEnhancedKeyUsage = external(
  46. 'CertGetEnhancedKeyUsage',
  47. [PCCERT_CONTEXT, rwin32.DWORD, PCERT_ENHKEY_USAGE, rwin32.LPDWORD],
  48. rwin32.BOOL)
  49. CertEnumCertificatesInStore = external(
  50. 'CertEnumCertificatesInStore',
  51. [rwin32.HANDLE, PCCERT_CONTEXT], PCCERT_CONTEXT)
  52. CertFreeCertificateContext = external(
  53. 'CertFreeCertificateContext', [PCCERT_CONTEXT], rwin32.BOOL)
  54. CertEnumCRLsInStore = external(
  55. 'CertEnumCRLsInStore',
  56. [rwin32.HANDLE, PCCRL_CONTEXT], PCCRL_CONTEXT)
  57. CertFreeCRLContext = external(
  58. 'CertFreeCRLContext', [PCCRL_CONTEXT], rwin32.BOOL)
  59. def w_certEncodingType(space, encodingType):
  60. if encodingType == X509_ASN_ENCODING:
  61. return space.wrap("x509_asn")
  62. elif encodingType == PKCS_7_ASN_ENCODING:
  63. return space.wrap("pkcs_7_asn")
  64. else:
  65. return space.wrap(encodingType)
  66. def w_parseKeyUsage(space, pCertCtx, flags):
  67. with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as size_ptr:
  68. if not CertGetEnhancedKeyUsage(pCertCtx, flags,
  69. lltype.nullptr(CERT_ENHKEY_USAGE), size_ptr):
  70. last_error = rwin32.lastSavedWindowsError()
  71. if last_error.winerror == CRYPT_E_NOT_FOUND:
  72. return space.w_True
  73. raise wrap_windowserror(space, last_error)
  74. size = intmask(size_ptr[0])
  75. with lltype.scoped_alloc(rffi.CCHARP.TO, size) as buf:
  76. usage = rffi.cast(PCERT_ENHKEY_USAGE, buf)
  77. # Now get the actual enhanced usage property
  78. if not CertGetEnhancedKeyUsage(pCertCtx, flags, usage, size_ptr):
  79. last_error= rwin32.lastSavedWindowsError()
  80. if last_error.winerror == CRYPT_E_NOT_FOUND:
  81. return space.w_True
  82. raise wrap_windowserror(space, last_error)
  83. result_w = [None] * usage.c_cUsageIdentifier
  84. for i in range(usage.c_cUsageIdentifier):
  85. if not usage.c_rgpszUsageIdentifier[i]:
  86. continue
  87. result_w[i] = space.wrap(rffi.charp2str(
  88. usage.c_rgpszUsageIdentifier[i]))
  89. return space.newset(result_w)
  90. @unwrap_spec(store_name=str)
  91. def enum_certificates_w(space, store_name):
  92. """enum_certificates(store_name) -> []
  93. Retrieve certificates from Windows' cert store. store_name may be one of
  94. 'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.
  95. The function returns a list of (bytes, encoding_type, trust) tuples. The
  96. encoding_type flag can be interpreted with X509_ASN_ENCODING or
  97. PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the
  98. boolean True."""
  99. result_w = []
  100. pCertCtx = lltype.nullptr(CERT_CONTEXT)
  101. hStore = CertOpenSystemStore(None, store_name)
  102. if not hStore:
  103. raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
  104. try:
  105. while True:
  106. pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)
  107. if not pCertCtx:
  108. break
  109. w_cert = space.newbytes(
  110. rffi.charpsize2str(pCertCtx.c_pbCertEncoded,
  111. intmask(pCertCtx.c_cbCertEncoded)))
  112. w_enc = w_certEncodingType(space, pCertCtx.c_dwCertEncodingType)
  113. w_keyusage = w_parseKeyUsage(
  114. space, pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG)
  115. if space.is_w(w_keyusage, space.w_True):
  116. w_keyusage = w_parseKeyUsage(
  117. space, pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG)
  118. result_w.append(space.newtuple([w_cert, w_enc, w_keyusage]))
  119. except:
  120. raise
  121. finally:
  122. if pCertCtx:
  123. # loop ended with an error, need to clean up context manually
  124. CertFreeCertificateContext(pCertCtx)
  125. if not CertCloseStore(hStore, 0):
  126. # This error case might shadow another exception.
  127. raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
  128. return space.newlist(result_w)
  129. @unwrap_spec(store_name=str)
  130. def enum_crls_w(space, store_name):
  131. """enum_crls(store_name) -> []
  132. Retrieve CRLs from Windows' cert store. store_name may be one of
  133. 'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.
  134. The function returns a list of (bytes, encoding_type) tuples. The
  135. encoding_type flag can be interpreted with X509_ASN_ENCODING or
  136. PKCS_7_ASN_ENCODING."""
  137. result_w = []
  138. pCrlCtx = lltype.nullptr(CRL_CONTEXT)
  139. hStore = CertOpenSystemStore(None, store_name)
  140. if not hStore:
  141. raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
  142. try:
  143. while True:
  144. pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)
  145. if not pCrlCtx:
  146. break
  147. w_crl = space.newbytes(
  148. rffi.charpsize2str(pCrlCtx.c_pbCrlEncoded,
  149. intmask(pCrlCtx.c_cbCrlEncoded)))
  150. w_enc = w_certEncodingType(space, pCrlCtx.c_dwCertEncodingType)
  151. result_w.append(space.newtuple([w_crl, w_enc]))
  152. except:
  153. raise
  154. finally:
  155. if pCrlCtx:
  156. # loop ended with an error, need to clean up context manually
  157. CertFreeCRLContext(pCrlCtx)
  158. if not CertCloseStore(hStore, 0):
  159. # This error case might shadow another exception.
  160. raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
  161. return space.newlist(result_w)