U 5oKab6ã@sädZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z m Z e  dej¡Zdd„Zdd „Zd d „Zd d „Zdd„Zd&dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zddd d!d"d#œZd$d%„ZdS)'a¦ Low-level helpers for the SecureTransport bindings. These are Python functions that are not directly related to the high-level APIs but are necessary to get them to work. They include a whole bunch of low-level CoreFoundation messing about and memory management. The concerns in this module are almost entirely about trying to avoid memory leaks and providing appropriate and useful assistance to the higher-level code. éNé)ÚCFConstÚCoreFoundationÚSecuritys;-----BEGIN CERTIFICATE----- (.*?) -----END CERTIFICATE-----cCst tj|t|ƒ¡S)zv Given a bytestring, create a CFData object from it. This CFData object must be CFReleased by the caller. )rÚ CFDataCreateÚkCFAllocatorDefaultÚlen)Z bytestring©r úT/usr/local/lib/python3.8/site-packages/urllib3/contrib/_securetransport/low_level.pyÚ_cf_data_from_bytess ÿr cCsZt|ƒ}dd„|Dƒ}dd„|Dƒ}tj||Ž}tj||Ž}t tj|||tjtj¡S)zK Given a list of Python tuples, create an associated CFDictionary. css|]}|dVqdS)rNr ©Ú.0Útr r r Ú ,sz-_cf_dictionary_from_tuples..css|]}|dVqdS)rNr r r r r r-s)rrÚ CFTypeRefZCFDictionaryCreaterZkCFTypeDictionaryKeyCallBacksZkCFTypeDictionaryValueCallBacks)ZtuplesZdictionary_sizeÚkeysÚvaluesZcf_keysZ cf_valuesr r r Ú_cf_dictionary_from_tuples%súrcCs t |¡}t tj|tj¡}|S)zi Given a Python binary data, create a CFString. The string must be CFReleased by the caller. )ÚctypesÚc_char_prZCFStringCreateWithCStringrrÚkCFStringEncodingUTF8)Zpy_bstrZc_strÚcf_strr r r Ú_cfstr;s ýrc Cs®d}zdt tjdt tj¡¡}|s*tdƒ‚|D]6}t|ƒ}|sFtdƒ‚zt  ||¡W5t |¡Xq.Wn@t k r¨}z"|rˆt |¡t   d|f¡‚W5d}~XYnX|S)zª Given a list of Python binary data, create an associated CFMutableArray. The array must be CFReleased by the caller. Raises an ssl.SSLError on failure. NrúUnable to allocate memory!zUnable to allocate array: %s) rÚCFArrayCreateMutablerrÚbyrefÚkCFTypeArrayCallBacksÚ MemoryErrorrÚ CFReleaseÚCFArrayAppendValueÚ BaseExceptionÚsslÚSSLError)ÚlstZcf_arrÚitemrÚer r r Ú_create_cfstring_arrayIs* ý "r&cCsnt |t tj¡¡}t |tj¡}|dkrXt d¡}t  ||dtj¡}|sRt dƒ‚|j }|dk rj|  d¡}|S)z¨ Creates a Unicode string from a CFString object. Used entirely for error reporting. Yes, it annoys me quite a lot that this function is this complex. Niz'Error copying C string from CFStringRefúutf-8) rÚcastÚPOINTERÚc_void_prZCFStringGetCStringPtrrrÚcreate_string_bufferZCFStringGetCStringÚOSErrorÚvalueÚdecode)r-Zvalue_as_void_pÚstringÚbufferÚresultr r r Ú_cf_string_to_unicodehs&ÿ ÿ r2cCs\|dkr dSt |d¡}t|ƒ}t |¡|dks:|dkrBd|}|dkrPtj}||ƒ‚dS)z[ Checks the return code and throws an exception if there is an error to report rNÚz OSStatus %s)rZSecCopyErrorMessageStringr2rrr!r")ÚerrorZexception_classZcf_error_stringÚoutputr r r Ú_assert_no_errors  r6cCsÚ| dd¡}dd„t |¡Dƒ}|s.t d¡‚t tjdt  tj ¡¡}|sTt d¡‚z`|D]V}t |ƒ}|stt d¡‚t   tj|¡}t |¡|sšt d¡‚t ||¡t |¡qZWn tk rÔt |¡‚YnX|S) z‚ Given a bundle of certs in PEM format, turns them into a CFArray of certs that can be used to validate a cert chain. s ó cSsg|]}t | d¡¡‘qS)r)Úbase64Ú b64decodeÚgroup)r Úmatchr r r Ú žsz(_cert_array_from_pem..zNo root certificates specifiedrrzUnable to build cert object!)ÚreplaceÚ _PEM_CERTS_REÚfinditerr!r"rrrrrrr rZSecCertificateCreateWithDatarrÚ Exception)Z pem_bundleZ der_certsZ cert_arrayZ der_bytesZcertdataZcertr r r Ú_cert_array_from_pem–s> ÿ  ý  ÿ    rAcCst ¡}t |¡|kS)z= Returns True if a given CFTypeRef is a certificate. )rZSecCertificateGetTypeIDrÚ CFGetTypeID©r$Zexpectedr r r Ú_is_certÄsrDcCst ¡}t |¡|kS)z; Returns True if a given CFTypeRef is an identity. )rZSecIdentityGetTypeIDrrBrCr r r Ú _is_identityÌsrEc Cs†t d¡}t |dd…¡ d¡}t |dd…¡}t ¡}tj ||¡  d¡}t   ¡}t   |t |ƒ|ddt |¡¡}t|ƒ||fS)a³ This function creates a temporary Mac keychain that we can use to work with credentials. This keychain uses a one-time password and a temporary file to store the data. We expect to have one keychain per socket. The returned SecKeychainRef must be freed by the caller, including calling SecKeychainDelete. Returns a tuple of the SecKeychainRef and the path to the temporary directory that contains it. é(Nér'F)ÚosÚurandomr8Ú b16encoder.ÚtempfileÚmkdtempÚpathÚjoinÚencoderZSecKeychainRefZSecKeychainCreaterrrr6)Z random_bytesÚfilenameÚpasswordZ tempdirectoryZ keychain_pathÚkeychainÚstatusr r r Ú_temporary_keychainÔs  ÿrTc Csg}g}d}t|dƒ}| ¡}W5QRXz²t tj|t|ƒ¡}t ¡}t  |ddddd|t   |¡¡}t |ƒt  |¡} t| ƒD]X} t || ¡} t  | tj¡} t| ƒr¼t | ¡| | ¡q€t| ƒr€t | ¡| | ¡q€W5|rìt |¡t |¡X||fS)zÊ Given a single file, loads all the trust objects from it into arrays and the keychain. Returns a tuple of lists: the first list is a list of identities, the second a list of certs. NÚrbr)ÚopenÚreadrrrrrZ CFArrayRefrZ SecItemImportrrr6ZCFArrayGetCountÚrangeZCFArrayGetValueAtIndexr(rrDZCFRetainÚappendrE) rRrMÚ certificatesÚ identitiesZ result_arrayÚfZ raw_filedataZfiledatar1Z result_countÚindexr$r r r Ú_load_items_from_file÷sJ ÿø         r^c Gsêg}g}dd„|Dƒ}z°|D]&}t||ƒ\}}| |¡| |¡q|sŠt ¡}t ||dt   |¡¡} t | ƒ|  |¡t |  d¡¡t tjdt   tj¡¡} t ||¡D]} t | | ¡q®| W¢St ||¡D]}t |¡qÔXdS)zü Load certificates and maybe keys from a number of files. Has the end goal of returning a CFArray containing one SecIdentityRef, and then zero or more SecCertificateRef objects, suitable for use as a client certificate trust chain. css|]}|r|VqdS)Nr )r rMr r r rRsz*_load_client_cert_chain..rN)Ú itertoolsÚchainrrr^ÚextendrZSecIdentityRefZ SecIdentityCreateWithCertificaterrr6rYÚpoprrrr) rRÚpathsrZr[ÚobjÚ file_pathZnew_identitiesZ new_certsZ new_identityrSZ trust_chainr$r r r Ú_load_client_cert_chain.s8   ÿ  ýrf)ré)ér)rhr)rhrg)rhrh)ZSSLv2ZSSLv3ZTLSv1zTLSv1.1zTLSv1.2c CsHt|\}}d}d}t d||¡}t|ƒ}d}t d||||¡|}|S)z6 Builds a TLS alert record for an unknown CA. rgé0z>BBéz>BBBH)ÚTLS_PROTOCOL_VERSIONSÚstructÚpackr) ÚversionZver_majZver_minZseverity_fatalZdescription_unknown_caÚmsgZmsg_lenZrecord_type_alertÚrecordr r r Ú_build_tls_unknown_ca_alert‚s rq)N)Ú__doc__r8rr_rHÚrer!rlrKZbindingsrrrÚcompileÚDOTALLr>r rrr&r2r6rArDrErTr^rfrkrqr r r r Ús@ ÿ  .#7Lû