3 nf\/@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 Cs|jdd}ddtj|D}|s.tjdtjtjdtj tj }|sTtjdydx^|D]V}t |}|svtjdt j tj|}tj||stjdtj||tj|q\WWntk 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. s  cSsg|]}tj|jdqS)r)base64Z b64decodegroup)r matchr r r vsz(_cert_array_from_pem..zNo root certificates specifiedrzUnable to allocate memory!zUnable to build cert object!)replace _PEM_CERTS_REfinditerrrrCFArrayCreateMutablerrbyrefkCFTypeArrayCallBacksr rZSecCertificateCreateWithDatarCFArrayAppendValue Exception)Z pem_bundleZ der_certsZ cert_arrayZ der_bytesZcertdataZcertr r r _cert_array_from_pemms4         r0cCstj}tj||kS)z= Returns True if a given CFTypeRef is a certificate. )rZSecCertificateGetTypeIDr CFGetTypeID)itemexpectedr r r _is_certsr4cCstj}tj||kS)z; Returns True if a given CFTypeRef is an identity. )rZSecIdentityGetTypeIDrr1)r2r3r r r _is_identitysr5cCstjd}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 b16encodertempfileZmkdtemppathjoinencoderZSecKeychainRefZSecKeychainCreaterrr,r")Z random_bytesfilenameZpasswordZ tempdirectoryZ keychain_pathkeychainstatusr r r _temporary_keychains  rAc 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"ZCFArrayGetCountrangeZCFArrayGetValueAtIndexrrr4ZCFRetainappendr5r) r?r; certificates identitiesZ result_arrayfZ raw_filedataZfiledatarZ result_countindexr2r r r _load_items_from_filesH         rKc 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 r;r r r r2sz*_load_client_cert_chain..rN)rKextendrZSecIdentityRefZ SecIdentityCreateWithCertificaterr,r"rFrrpopr+rr- itertoolschainr.) r?pathsrGrHZ file_pathZnew_identitiesZ new_certsZ new_identityr@Z trust_chainr2objr r r _load_client_cert_chains6      rR)N)__doc__r$rrNrer8rr:ZbindingsrrrcompileDOTALLr)r rrr"r0r4r5rArKrRr r r r  s(   .(;