o
    q¨Êh´.  ã                   @   s´   d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
mZ e dej¡Zdd„ Zdd	„ Zd
d„ Zddd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )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é   )ÚSecurityÚCoreFoundationÚCFConsts;   -----BEGIN CERTIFICATE-----
(.*?)
-----END CERTIFICATE-----c                 C   s   t  t j| 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)Ú
bytestring© r
   ú\/var/www/html/env/lib/python3.10/site-packages/urllib3/contrib/_securetransport/low_level.pyÚ_cf_data_from_bytes   s   ÿr   c                 C   sZ   t | ƒ}dd„ | D ƒ}dd„ | D ƒ}tj| |Ž }tj| |Ž }t tj|||tjtj¡S )zK
    Given a list of Python tuples, create an associated CFDictionary.
    c                 s   ó   � | ]}|d  V  qdS )r   Nr
   ©Ú.0Útr
   r
   r   Ú	<genexpr>,   ó   € z-_cf_dictionary_from_tuples.<locals>.<genexpr>c                 s   r   )r   Nr
   r   r
   r
   r   r   -   r   )r   r   Ú	CFTypeRefÚCFDictionaryCreater   ÚkCFTypeDictionaryKeyCallBacksÚkCFTypeDictionaryValueCallBacks)ÚtuplesÚdictionary_sizeÚkeysÚvaluesÚcf_keysÚ	cf_valuesr
   r
   r   Ú_cf_dictionary_from_tuples%   s   úr   c                 C   sn   t  | t  t j¡¡}t |tj¡}|du r,t  d¡}t 	||dtj¡}|s)t
dƒ‚|j}|dur5| 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.
    Ni   z'Error copying C string from CFStringRefúutf-8)ÚctypesÚcastÚPOINTERÚc_void_pr   ÚCFStringGetCStringPtrr   ÚkCFStringEncodingUTF8Úcreate_string_bufferÚCFStringGetCStringÚOSErrorÚvalueÚdecode)r(   Úvalue_as_void_pÚstringÚbufferÚresultr
   r
   r   Ú_cf_string_to_unicode;   s   ÿ

ÿ
r.   c                 C   sX   | dkrdS t  | d¡}t|ƒ}t |¡ |du s|dkr!d|  }|du r(tj}||ƒ‚)z[
    Checks the return code and throws an exception if there is an error to
    report
    r   NÚ zOSStatus %s)r   ÚSecCopyErrorMessageStringr.   r   Ú	CFReleaseÚsslÚSSLError)ÚerrorÚexception_classÚcf_error_stringÚoutputr
   r
   r   Ú_assert_no_errorT   s   
r8   c                 C   sÖ   |   dd¡} dd„ t | ¡D ƒ}|st d¡‚t tjdt 	tj
¡¡}|s*t d¡‚z1|D ]+}t|ƒ}|s:t d¡‚t tj|¡}t |¡ |sMt d¡‚t ||¡ t |¡ q-W |S  tyj   t |¡ Y |S w )	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   
ó   
c                 S   s   g | ]
}t  | d ¡¡‘qS )r   )Úbase64Ú	b64decodeÚgroup)r   Úmatchr
   r
   r   Ú
<listcomp>q   s    ÿz(_cert_array_from_pem.<locals>.<listcomp>zNo root certificates specifiedr   zUnable to allocate memory!zUnable to build cert object!)ÚreplaceÚ_PEM_CERTS_REÚfinditerr2   r3   r   ÚCFArrayCreateMutabler   r   ÚbyrefÚkCFTypeArrayCallBacksr   r   ÚSecCertificateCreateWithDatar1   ÚCFArrayAppendValueÚ	Exception)Ú
pem_bundleÚ	der_certsÚ
cert_arrayÚ	der_bytesÚcertdataÚcertr
   r
   r   Ú_cert_array_from_pemi   s@   ÿ

ý

ÿ

ôúúrN   c                 C   ó   t  ¡ }t | ¡|kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   ÚSecCertificateGetTypeIDr   ÚCFGetTypeID©ÚitemÚexpectedr
   r
   r   Ú_is_cert–   ó   rU   c                 C   rO   )z;
    Returns True if a given CFTypeRef is an identity.
    )r   ÚSecIdentityGetTypeIDr   rQ   rR   r
   r
   r   Ú_is_identityž   rV   rX   c               
   C   s†   t  d¡} t | dd… ¡ d¡}t | dd… ¡}t ¡ }t j ||¡ 	d¡}t
 ¡ }t
 |t|ƒ|ddt |¡¡}t|ƒ ||fS )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Úurandomr:   Ú	b16encoder)   ÚtempfileÚmkdtempÚpathÚjoinÚencoder   ÚSecKeychainRefÚSecKeychainCreater   r   rC   r8   )Úrandom_bytesÚfilenameÚpasswordÚtempdirectoryÚkeychain_pathÚkeychainÚstatusr
   r
   r   Ú_temporary_keychain¦   s   
ÿrl   c                 C   s*  g }g }d}t |dƒ�}| ¡ }W d  ƒ n1 sw   Y  zht tj|t|ƒ¡}t ¡ }t |ddddd| t	 
|¡¡}t|ƒ t |¡}	t|	ƒD ],}
t ||
¡}t	 |tj¡}t|ƒrht |¡ | |¡ qJt|ƒrvt |¡ | |¡ qJW |rt |¡ t |¡ ||fS |r�t |¡ t |¡ w )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Úreadr   r   r   r   Ú
CFArrayRefr   ÚSecItemImportr   rC   r8   ÚCFArrayGetCountÚrangeÚCFArrayGetValueAtIndexr    r   rU   ÚCFRetainÚappendrX   r1   )rj   r`   ÚcertificatesÚ
identitiesÚresult_arrayÚfÚraw_filedataÚfiledatar-   Úresult_countÚindexrS   r
   r
   r   Ú_load_items_from_fileÉ   sR   
ÿÿø




€÷

û
r   c              
   G   s   g }g }dd„ |D ƒ}ze|D ]}t | |ƒ\}}| |¡ | |¡ q|sEt ¡ }t | |d t |¡¡}t|ƒ | |¡ t	 
| d¡¡ t	 t	jdt t	j¡¡}	t ||¡D ]}
t	 |	|
¡ qW|	W t ||¡D ]}t	 
|¡ qhS t ||¡D ]}t	 
|¡ qww )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.
    c                 s   s   � | ]}|r|V  qd S ©Nr
   )r   r`   r
   r
   r   r   $  r   z*_load_client_cert_chain.<locals>.<genexpr>r   )r   Úextendr   ÚSecIdentityRefÚ SecIdentityCreateWithCertificater   rC   r8   rv   r   r1   ÚpoprB   r   rD   Ú	itertoolsÚchainrF   )rj   Úpathsrw   rx   Ú	file_pathÚnew_identitiesÚ	new_certsÚnew_identityrk   Útrust_chainrS   Úobjr
   r
   r   Ú_load_client_cert_chain   s:    
ÿ

ýÿÿrŽ   r€   )Ú__doc__r:   r   r…   Úrer[   r2   r^   Úbindingsr   r   r   ÚcompileÚDOTALLr@   r   r   r.   r8   rN   rU   rX   rl   r   rŽ   r
   r
   r
   r   Ú<module>   s,    	ÿ

-#7