Show More
@@ -22,6 +22,7 b' from . import (' | |||||
22 | _kernel32 = ctypes.windll.kernel32 |
|
22 | _kernel32 = ctypes.windll.kernel32 | |
23 | _advapi32 = ctypes.windll.advapi32 |
|
23 | _advapi32 = ctypes.windll.advapi32 | |
24 | _user32 = ctypes.windll.user32 |
|
24 | _user32 = ctypes.windll.user32 | |
|
25 | _crypt32 = ctypes.windll.crypt32 | |||
25 |
|
26 | |||
26 | _BOOL = ctypes.c_long |
|
27 | _BOOL = ctypes.c_long | |
27 | _WORD = ctypes.c_ushort |
|
28 | _WORD = ctypes.c_ushort | |
@@ -31,6 +32,7 b' from . import (' | |||||
31 | _LPCSTR = _LPSTR = ctypes.c_char_p |
|
32 | _LPCSTR = _LPSTR = ctypes.c_char_p | |
32 | _HANDLE = ctypes.c_void_p |
|
33 | _HANDLE = ctypes.c_void_p | |
33 | _HWND = _HANDLE |
|
34 | _HWND = _HANDLE | |
|
35 | _PCCERT_CONTEXT = ctypes.c_void_p | |||
34 |
|
36 | |||
35 | _INVALID_HANDLE_VALUE = _HANDLE(-1).value |
|
37 | _INVALID_HANDLE_VALUE = _HANDLE(-1).value | |
36 |
|
38 | |||
@@ -134,8 +136,74 b' class _CONSOLE_SCREEN_BUFFER_INFO(ctypes' | |||||
134 | _STD_OUTPUT_HANDLE = _DWORD(-11).value |
|
136 | _STD_OUTPUT_HANDLE = _DWORD(-11).value | |
135 | _STD_ERROR_HANDLE = _DWORD(-12).value |
|
137 | _STD_ERROR_HANDLE = _DWORD(-12).value | |
136 |
|
138 | |||
|
139 | # CERT_TRUST_STATUS dwErrorStatus | |||
|
140 | CERT_TRUST_IS_PARTIAL_CHAIN = 0x10000 | |||
|
141 | ||||
|
142 | # CertCreateCertificateContext encodings | |||
|
143 | X509_ASN_ENCODING = 0x00000001 | |||
|
144 | PKCS_7_ASN_ENCODING = 0x00010000 | |||
|
145 | ||||
|
146 | # These structs are only complete enough to achieve what we need. | |||
|
147 | class CERT_CHAIN_CONTEXT(ctypes.Structure): | |||
|
148 | _fields_ = ( | |||
|
149 | ("cbSize", _DWORD), | |||
|
150 | ||||
|
151 | # CERT_TRUST_STATUS struct | |||
|
152 | ("dwErrorStatus", _DWORD), | |||
|
153 | ("dwInfoStatus", _DWORD), | |||
|
154 | ||||
|
155 | ("cChain", _DWORD), | |||
|
156 | ("rgpChain", ctypes.c_void_p), | |||
|
157 | ("cLowerQualityChainContext", _DWORD), | |||
|
158 | ("rgpLowerQualityChainContext", ctypes.c_void_p), | |||
|
159 | ("fHasRevocationFreshnessTime", _BOOL), | |||
|
160 | ("dwRevocationFreshnessTime", _DWORD), | |||
|
161 | ) | |||
|
162 | ||||
|
163 | class CERT_USAGE_MATCH(ctypes.Structure): | |||
|
164 | _fields_ = ( | |||
|
165 | ("dwType", _DWORD), | |||
|
166 | ||||
|
167 | # CERT_ENHKEY_USAGE struct | |||
|
168 | ("cUsageIdentifier", _DWORD), | |||
|
169 | ("rgpszUsageIdentifier", ctypes.c_void_p), # LPSTR * | |||
|
170 | ) | |||
|
171 | ||||
|
172 | class CERT_CHAIN_PARA(ctypes.Structure): | |||
|
173 | _fields_ = ( | |||
|
174 | ("cbSize", _DWORD), | |||
|
175 | ("RequestedUsage", CERT_USAGE_MATCH), | |||
|
176 | ("RequestedIssuancePolicy", CERT_USAGE_MATCH), | |||
|
177 | ("dwUrlRetrievalTimeout", _DWORD), | |||
|
178 | ("fCheckRevocationFreshnessTime", _BOOL), | |||
|
179 | ("dwRevocationFreshnessTime", _DWORD), | |||
|
180 | ("pftCacheResync", ctypes.c_void_p), # LPFILETIME | |||
|
181 | ("pStrongSignPara", ctypes.c_void_p), # PCCERT_STRONG_SIGN_PARA | |||
|
182 | ("dwStrongSignFlags", _DWORD), | |||
|
183 | ) | |||
|
184 | ||||
137 | # types of parameters of C functions used (required by pypy) |
|
185 | # types of parameters of C functions used (required by pypy) | |
138 |
|
186 | |||
|
187 | _crypt32.CertCreateCertificateContext.argtypes = [_DWORD, # cert encoding | |||
|
188 | ctypes.c_char_p, # cert | |||
|
189 | _DWORD] # cert size | |||
|
190 | _crypt32.CertCreateCertificateContext.restype = _PCCERT_CONTEXT | |||
|
191 | ||||
|
192 | _crypt32.CertGetCertificateChain.argtypes = [ | |||
|
193 | ctypes.c_void_p, # HCERTCHAINENGINE | |||
|
194 | _PCCERT_CONTEXT, | |||
|
195 | ctypes.c_void_p, # LPFILETIME | |||
|
196 | ctypes.c_void_p, # HCERTSTORE | |||
|
197 | ctypes.c_void_p, # PCERT_CHAIN_PARA | |||
|
198 | _DWORD, | |||
|
199 | ctypes.c_void_p, # LPVOID | |||
|
200 | ctypes.c_void_p # PCCERT_CHAIN_CONTEXT * | |||
|
201 | ] | |||
|
202 | _crypt32.CertGetCertificateChain.restype = _BOOL | |||
|
203 | ||||
|
204 | _crypt32.CertFreeCertificateContext.argtypes = [_PCCERT_CONTEXT] | |||
|
205 | _crypt32.CertFreeCertificateContext.restype = _BOOL | |||
|
206 | ||||
139 | _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p, |
|
207 | _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p, | |
140 | _DWORD, _DWORD, _HANDLE] |
|
208 | _DWORD, _DWORD, _HANDLE] | |
141 | _kernel32.CreateFileA.restype = _HANDLE |
|
209 | _kernel32.CreateFileA.restype = _HANDLE | |
@@ -234,6 +302,51 b' def _getfileinfo(name):' | |||||
234 | finally: |
|
302 | finally: | |
235 | _kernel32.CloseHandle(fh) |
|
303 | _kernel32.CloseHandle(fh) | |
236 |
|
304 | |||
|
305 | def checkcertificatechain(cert, build=True): | |||
|
306 | '''Tests the given certificate to see if there is a complete chain to a | |||
|
307 | trusted root certificate. As a side effect, missing certificates are | |||
|
308 | downloaded and installed unless ``build=False``. True is returned if a | |||
|
309 | chain to a trusted root exists (even if built on the fly), otherwise | |||
|
310 | False. NB: A chain to a trusted root does NOT imply that the certificate | |||
|
311 | is valid. | |||
|
312 | ''' | |||
|
313 | ||||
|
314 | chainctxptr = ctypes.POINTER(CERT_CHAIN_CONTEXT) | |||
|
315 | ||||
|
316 | pchainctx = chainctxptr() | |||
|
317 | chainpara = CERT_CHAIN_PARA(cbSize=ctypes.sizeof(CERT_CHAIN_PARA), | |||
|
318 | RequestedUsage=CERT_USAGE_MATCH()) | |||
|
319 | ||||
|
320 | certctx = _crypt32.CertCreateCertificateContext(X509_ASN_ENCODING, cert, | |||
|
321 | len(cert)) | |||
|
322 | if certctx is None: | |||
|
323 | _raiseoserror('CertCreateCertificateContext') | |||
|
324 | ||||
|
325 | flags = 0 | |||
|
326 | ||||
|
327 | if not build: | |||
|
328 | flags |= 0x100 # CERT_CHAIN_DISABLE_AUTH_ROOT_AUTO_UPDATE | |||
|
329 | ||||
|
330 | try: | |||
|
331 | # Building the certificate chain will update root certs as necessary. | |||
|
332 | if not _crypt32.CertGetCertificateChain(None, # hChainEngine | |||
|
333 | certctx, # pCertContext | |||
|
334 | None, # pTime | |||
|
335 | None, # hAdditionalStore | |||
|
336 | ctypes.byref(chainpara), | |||
|
337 | flags, | |||
|
338 | None, # pvReserved | |||
|
339 | ctypes.byref(pchainctx)): | |||
|
340 | _raiseoserror('CertGetCertificateChain') | |||
|
341 | ||||
|
342 | chainctx = pchainctx.contents | |||
|
343 | ||||
|
344 | return chainctx.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN == 0 | |||
|
345 | finally: | |||
|
346 | if pchainctx: | |||
|
347 | _crypt32.CertFreeCertificateChain(pchainctx) | |||
|
348 | _crypt32.CertFreeCertificateContext(certctx) | |||
|
349 | ||||
237 | def oslink(src, dst): |
|
350 | def oslink(src, dst): | |
238 | try: |
|
351 | try: | |
239 | if not _kernel32.CreateHardLinkA(dst, src, None): |
|
352 | if not _kernel32.CreateHardLinkA(dst, src, None): |
General Comments 0
You need to be logged in to leave comments.
Login now