3 Pf/@sdZddlZddlZddlZddlZddlZddlZddlZddlm Z m Z m Z ej dej ZddZdd Zd d Zdd d ZddZddZddZddZddZddZdS)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)SecurityCoreFoundationCFConsts;-----BEGIN CERTIFICATE----- (.*?) -----END CERTIFICATE-----cCstjtj|t|S)zv Given a bytestring, create a CFData object from it. This CFData object must be CFReleased by the caller. )r CFDataCreatekCFAllocatorDefaultlen)Z bytestringr /usr/lib/python3.6/low_level.py_cf_data_from_bytessr cCsZt|}dd|D}dd|D}tj||}tj||}tjtj|||tjtjS)zK Given a list of Python tuples, create an associated CFDictionary. css|]}|dVqdS)rNr ).0tr r r ,sz-_cf_dictionary_from_tuples..css|]}|dVqdS)rNr )r r r r r r-s)rr CFTypeRefZCFDictionaryCreaterZkCFTypeDictionaryKeyCallBacksZkCFTypeDictionaryValueCallBacks)ZtuplesZdictionary_sizekeysvaluesZcf_keysZ cf_valuesr r r _cf_dictionary_from_tuples%srcCsntj|tjtj}tj|tj}|dkrXtjd}tj ||dtj}|sRt d|j }|dk rj|j 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 CFStringRefzutf-8) ctypescastZPOINTERZc_void_prZCFStringGetCStringPtrrZkCFStringEncodingUTF8Zcreate_string_bufferZCFStringGetCStringOSErrorvaluedecode)rZvalue_as_void_pstringbufferresultr r r _cf_string_to_unicode;s"  rcCs\|dkr dStj|d}t|}tj||dks:|dkrBd|}|dkrPtj}||dS)z[ Checks the return code and throws an exception if there is an error to report rNz OSStatus %s)rZSecCopyErrorMessageStringrr CFReleasesslSSLError)errorZexception_classZcf_error_stringoutputr r r _assert_no_errorXs  r"c Csddtj|D}|s"tjdtjtjdtjtj }|sHtjdydx^|D]V}t |}|sjtjdt j tj|}tj ||stjdtj||tj |qPWWntk rtj |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. cSsg|]}tj|jdqS)r)base64Z b64decodegroup)r matchr r r ssz(_cert_array_from_pem..zNo root certificates specifiedrzUnable to allocate memory!zUnable to build cert object!) _PEM_CERTS_REfinditerrrrCFArrayCreateMutablerrbyrefkCFTypeArrayCallBacksr rZSecCertificateCreateWithDatarCFArrayAppendValue Exception)Z pem_bundleZ der_certsZ cert_arrayZ der_bytesZcertdataZcertr r r _cert_array_from_pemms2        r.cCstj}tj||kS)z= Returns True if a given CFTypeRef is a certificate. )rZSecCertificateGetTypeIDr CFGetTypeID)itemexpectedr r r _is_certsr2cCstj}tj||kS)z; Returns True if a given CFTypeRef is an identity. )rZSecIdentityGetTypeIDrr/)r0r1r r r _is_identitysr3cCstjd}tj|ddjd}tj|dd}tj}tjj||j d}t j }t j |t ||ddtj|}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. (Nzutf-8F)osurandomr#Z b64encodertempfileZmkdtemppathjoinencoderZSecKeychainRefZSecKeychainCreaterrr*r")Z random_bytesfilenameZpasswordZ tempdirectoryZ keychain_pathkeychainstatusr r r _temporary_keychains  r?c Csg}g}d}t|d}|j}WdQRXztjtj|t|}tj}tj|ddddd|t j |}t |tj |} xdt | D]X} tj|| } t j| tj} t| rtj| |j| qt| rtj| |j| qWWd|rtj|tj|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. Nrbr)openreadrrrrZ CFArrayRefrZ SecItemImportrr*r"ZCFArrayGetCountrangeZCFArrayGetValueAtIndexrrr2ZCFRetainappendr3r) r=r9 certificates identitiesZ result_arrayfZ raw_filedataZfiledatarZ result_countindexr0r r r _load_items_from_filesH         rIc Gsg}g}dd|D}zx.|D]&}t||\}}|j||j|qW|stj}tj||dtj|}t||j|t j |j dt j t j dtjt j} x tj||D]} t j| | qW| Sxtj||D]} t j | qWXdS)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 r9r r r r/sz*_load_client_cert_chain..rN)rIextendrZSecIdentityRefZ SecIdentityCreateWithCertificaterr*r"rDrrpopr)rr+ itertoolschainr,) r=pathsrErFZ file_pathZnew_identitiesZ new_certsZ new_identityr>Z trust_chainr0objr r r _load_client_cert_chain s6      rP)N)__doc__r#rrLrer6rr8ZbindingsrrrcompileDOTALLr'r rrr"r.r2r3r?rIrPr r r r  s(   +(;