� ��^c@s�dZddlZddlZddlZddlZddlZddlZddlZddlm Z m Z m Z ej dej �Zd�Zd�Zd�Zdd �Zd �Zd �Zd �Zd �Zd�Zd�ZdS(s� 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. i����Ni(tSecuritytCoreFoundationtCFConsts;-----BEGIN CERTIFICATE----- (.*?) -----END CERTIFICATE-----cCstjtj|t|��S(sv Given a bytestring, create a CFData object from it. This CFData object must be CFReleased by the caller. (Rt CFDataCreatetkCFAllocatorDefaulttlen(t bytestring((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_cf_data_from_bytesscCswt|�}d�|D�}d�|D�}tj||�}tj||�}tjtj|||tjtj�S(sK Given a list of Python tuples, create an associated CFDictionary. css|]}|dVqdS(iN((t.0tt((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pys ,scss|]}|dVqdS(iN((RR ((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pys -s(RRt CFTypeReftCFDictionaryCreateRtkCFTypeDictionaryKeyCallBackstkCFTypeDictionaryValueCallBacks(ttuplestdictionary_sizetkeystvaluestcf_keyst cf_values((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_cf_dictionary_from_tuples%s cCs�tj|tjtj��}tj|tj�}|dkr�tj d�}tj ||dtj�}|s~t d��n|j }n|dk r�|j d�}n|S(s� 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. is'Error copying C string from CFStringRefsutf-8N(tctypestcasttPOINTERtc_void_pRtCFStringGetCStringPtrRtkCFStringEncodingUTF8tNonetcreate_string_buffertCFStringGetCStringtOSErrortvaluetdecode(Rtvalue_as_void_ptstringtbuffertresult((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_cf_string_to_unicode;s   cCs�|dkrdStj|d�}t|�}tj|�|dksS|dkr`d|}n|dkrxtj}n||��dS(s[ Checks the return code and throws an exception if there is an error to report iNuu OSStatus %s(RtSecCopyErrorMessageStringRR%Rt CFReleasetssltSSLError(terrortexception_classtcf_error_stringtoutput((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_assert_no_errorTs      cCsO|jdd�}gtj|�D]}tj|jd��^q"}|s^tjd��ntj tj dt j tj ��}|s�tjd��ny�x�|D]�}t|�}|s�tjd��ntjtj |�}tj|�|stjd��ntj||�tj|�q�WWntk rJtj|�nX|S(s� 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 s isNo root certificates specifiedisUnable to allocate memory!sUnable to build cert object!(treplacet _PEM_CERTS_REtfinditertbase64t b64decodetgroupR(R)RtCFArrayCreateMutableRRtbyreftkCFTypeArrayCallBacksRRtSecCertificateCreateWithDataR'tCFArrayAppendValuet Exception(t pem_bundletmatcht der_certst cert_arrayt der_bytestcertdatatcert((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_cert_array_from_pemis24    cCstj�}tj|�|kS(s= Returns True if a given CFTypeRef is a certificate. (RtSecCertificateGetTypeIDRt CFGetTypeID(titemtexpected((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_is_cert�s cCstj�}tj|�|kS(s; Returns True if a given CFTypeRef is an identity. (RtSecIdentityGetTypeIDRRD(RERF((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt _is_identity�s cCs�tjd�}tj|d �jd�}tj|d�}tj�}tjj||�j d�}t j �}t j |t |�|tdtj|��}t|�||fS(s� 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. i(isutf-8N(tosturandomR2t b16encodeR ttempfiletmkdtemptpathtjointencodeRtSecKeychainReftSecKeychainCreateRtFalseRRR6R.(t random_bytestfilenametpasswordt tempdirectoryt keychain_pathtkeychaintstatus((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_temporary_keychain�s  ' c Cskg}g}d}t|d��}|j�}WdQXztjtj|t|��}tj�}tj |ddddd|t j |��}t |�tj |�} x�t| �D]} tj|| �} t j| tj�} t| �r tj| �|j| �q�t| �r�tj| �|j| �q�q�WWd|rStj|�ntj|�X||fS(s� 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. trbNi(RtopentreadRRRRt CFArrayRefRt SecItemImportRR6R.tCFArrayGetCounttrangetCFArrayGetValueAtIndexRR RGtCFRetaintappendRIR'( RZROt certificatest identitiest result_arraytft raw_filedatatfiledataR$t result_counttindexRE((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_load_items_from_file�sB      c GsKg}g}d�|D�}z�x=|D]5}t||�\}}|j|�|j|�q&W|s�tj�}tj||dtj|��}t|�|j|�t j |j d��nt j t j dtjt j��} x*tj||�D]} t j| | �q�W| SWdx'tj||�D]} t j | �q/WXdS(s� 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(N((RRO((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pys $siN(RotextendRtSecIdentityReft SecIdentityCreateWithCertificateRR6R.RfRR'tpopR5RR7t itertoolstchainR9( RZtpathsRgRht file_pathtnew_identitiest new_certst new_identityR[t trust_chainREtobj((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt_load_client_cert_chains0      (t__doc__R2RRttreRJR(RMtbindingsRRRtcompiletDOTALLR0RRR%RR.RBRGRIR\RoR}(((sK/tmp/pip-build-1THPZW/urllib3/urllib3/contrib/_securetransport/low_level.pyt s(           -   # 7