a t~®`T6ã@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 úN/usr/lib/python3.9/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 Ú ,óz-_cf_dictionary_from_tuples..css|]}|dVqdS)rNr r r r r r-r)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. )ÚctypesZc_char_prZCFStringCreateWithCStringrrÚkCFStringEncodingUTF8)Zpy_bstrZc_strÚcf_strr r r Ú_cfstr;s ýrc Csºd}znt tjdt tj¡¡}|s*tdƒ‚|D]@}t|ƒ}|sFtdƒ‚zt ||¡Wt  |¡q.t  |¡0q.WnBt y´}z*|rt  |¡t   d|f¡‚WYd}~n d}~00|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ÚCFArrayAppendValueÚ CFReleaseÚ BaseExceptionÚsslÚSSLError)ZlstZcf_arrÚitemrÚer r r Ú_create_cfstring_arrayIs* ý &r%cCsnt |t tj¡¡}t |tj¡}|durXt d¡}t  ||dtj¡}|sRt dƒ‚|j }|durj|  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ÚcastZPOINTERZc_void_prZCFStringGetCStringPtrrrZcreate_string_bufferZCFStringGetCStringÚOSErrorÚvalueÚdecode)r)Zvalue_as_void_pÚstringÚbufferÚresultr r r Ú_cf_string_to_unicodehsÿ  ÿ r.cCs\|dkr dSt |d¡}t|ƒ}t |¡|dus:|dkrBd|}|durPtj}||ƒ‚dS)z[ Checks the return code and throws an exception if there is an error to report rNÚz OSStatus %s)rZSecCopyErrorMessageStringr.rrr!r")ÚerrorZexception_classZcf_error_stringÚoutputr r r Ú_assert_no_errors  r2cCsÖ| 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 |¡qZWntyÐt |¡Yn0|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)Úbase64Z 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: ÿ  ý  ÿ    r<cCst ¡}t |¡|kS)z= Returns True if a given CFTypeRef is a certificate. )rZSecCertificateGetTypeIDrÚ CFGetTypeID©r#Zexpectedr r r Ú_is_certÃsr?cCst ¡}t |¡|kS)z; Returns True if a given CFTypeRef is an identity. )rZSecIdentityGetTypeIDrr=r>r r r Ú _is_identityËsr@c 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Úurandomr4Z b16encoder*ÚtempfileZmkdtempÚpathÚjoinÚencoderZSecKeychainRefZSecKeychainCreaterrrr2)Z random_bytesÚfilenameÚpasswordZ tempdirectoryZ keychain_pathÚkeychainÚstatusr r r Ú_temporary_keychainÓs ÿrMc Cs.g}g}d}t|dƒ}| ¡}Wdƒn1s40YzÊt tj|t|ƒ¡}t ¡}t |ddddd|t   |¡¡}t |ƒt  |¡} t | ƒD]X} t || ¡} t  | tj¡} t| ƒrÐt | ¡| | ¡q”t| ƒr”t | ¡| | ¡q”W|rþt |¡t |¡n|rt |¡t |¡0||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ÚreadrrrrZ CFArrayRefrZ SecItemImportrrr2ZCFArrayGetCountÚrangeZCFArrayGetValueAtIndexr'rr?ZCFRetainÚappendr@r) rKrFÚ certificatesÚ identitiesZ result_arrayÚfZ raw_filedataZfiledatar-Z result_countÚindexr#r r r Ú_load_items_from_fileösL & ÿø         ý  rWc Gsg}g}dd„|Dƒ}zÜ|D]&}t||ƒ\}}| |¡| |¡q|sŠt ¡}t ||dt |¡¡}t|ƒ| |¡t   |  d¡¡t   t j dt t j¡¡} t ||¡D]} t  | | ¡q®| Wt ||¡D]} t   | ¡qÐS]} t   | ¡qân t ||¡D]} t   | ¡q0dS)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 rFr r r rQrz*_load_client_cert_chain..rN)rWÚextendrZSecIdentityRefZ SecIdentityCreateWithCertificaterrr2rRrrÚpoprrrÚ itertoolsÚchainr) rKÚpathsrSrTZ file_pathZnew_identitiesZ new_certsZ new_identityrLZ trust_chainr#Úobjr r r Ú_load_client_cert_chain-s>   ÿ  ý ýÿr^)ré)ér)r`r)r`r_)r`r`)ZSSLv2ZSSLv3ZTLSv1zTLSv1.1zTLSv1.2c CsHt|\}}d}d}t d||¡}t|ƒ}d}t d||||¡|}|S)z6 Builds a TLS alert record for an unknown CA. r_é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_alerts ri)N)Ú__doc__r4rrZrCÚrer!rdrEZbindingsrrrÚcompileÚDOTALLr9r rrr%r.r2r<r?r@rMrWr^rcrir r r r Ús> ÿ  -#7Lû