a
    ‘db/  ã                   @   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)Z
bytestring© r	   ú{/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python3.9/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   s   | ]}|d  V  qdS )r   Nr	   ©Ú.0Útr	   r	   r
   Ú	<genexpr>,   ó    z-_cf_dictionary_from_tuples.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS )r   Nr	   r   r	   r	   r
   r   -   r   )r   r   Ú	CFTypeRefZCFDictionaryCreater   ZkCFTypeDictionaryKeyCallBacksZkCFTypeDictionaryValueCallBacks)ZtuplesZdictionary_sizeÚkeysÚvaluesZcf_keysZ	cf_valuesr	   r	   r
   Ú_cf_dictionary_from_tuples%   s    úr   c                 C   sn   t  | t  t j¡¡}t |tj¡}|du rXt  d¡}t 	||dtj¡}|sRt
dƒ‚|j}|durj| 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   ZCFStringGetCStringPtrr   ZkCFStringEncodingUTF8Úcreate_string_bufferZCFStringGetCStringÚOSErrorÚvalueÚdecode)r   Zvalue_as_void_pÚstringÚbufferÚresultr	   r	   r
   Ú_cf_string_to_unicode;   s&    þ
ü
r!   c                 C   s\   | dkrdS t  | d¡}t|ƒ}t |¡ |du s:|dkrBd|  }|du rPtj}||ƒ‚dS )z[
    Checks the return code and throws an exception if there is an error to
    report
    r   NÚ zOSStatus %s)r   ZSecCopyErrorMessageStringr!   r   Ú	CFReleaseÚsslÚSSLError)ÚerrorZexception_classZcf_error_stringÚoutputr	   r	   r
   Ú_assert_no_errorX   s    
r(   c                 C   sÊ   dd„ t  | ¡D ƒ}|s"t d¡‚t tjdt tj	¡¡}|sHt d¡‚z`|D ]V}t
|ƒ}|sht d¡‚t tj|¡}t |¡ |sŽt d¡‚t ||¡ t |¡ qNW n tyÄ   t |¡ Y n0 |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.
    c                 S   s   g | ]}t  | d ¡¡‘qS )r   )Úbase64Ú	b64decodeÚgroup)r   Úmatchr	   r	   r
   Ú
<listcomp>r   s   ÿz(_cert_array_from_pem.<locals>.<listcomp>zNo root certificates specifiedr   zUnable to allocate memory!zUnable to build cert object!)Ú_PEM_CERTS_REÚfinditerr$   r%   r   ÚCFArrayCreateMutabler   r   ÚbyrefÚkCFTypeArrayCallBacksr   r   ZSecCertificateCreateWithDatar#   ÚCFArrayAppendValueÚ	Exception)Z
pem_bundleZ	der_certsZ
cert_arrayZ	der_bytesZcertdataÚcertr	   r	   r
   Ú_cert_array_from_pemm   s8    þ

ý

ÿ

r6   c                 C   s   t  ¡ }t | ¡|kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   ZSecCertificateGetTypeIDr   ÚCFGetTypeID©ÚitemÚexpectedr	   r	   r
   Ú_is_cert˜   s    r;   c                 C   s   t  ¡ }t | ¡|kS )z;
    Returns True if a given CFTypeRef is an identity.
    )r   ZSecIdentityGetTypeIDr   r7   r8   r	   r	   r
   Ú_is_identity    s    r<   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)   Ú	b64encoder   ÚtempfileÚmkdtempÚpathÚjoinÚencoder   ZSecKeychainRefZSecKeychainCreater   r   r1   r(   )Zrandom_bytesÚfilenameÚpasswordZtempdirectoryZkeychain_pathÚkeychainÚstatusr	   r	   r
   Ú_temporary_keychain¨   s     
úrK   c                 C   s.  g }g }d}t |dƒ}| ¡ }W d  ƒ n1 s40    Y  zÊt tj|t|ƒ¡}t ¡ }t |ddddd| t	 
|¡¡}t|ƒ t |¡}	t|	ƒD ]X}
t ||
¡}t	 |tj¡}t|ƒrÐt |¡ | |¡ q”t|ƒr”t |¡ | |¡ q”W |rþt |¡ t |¡ n|rt |¡ t |¡ 0 ||fS )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   Z
CFArrayRefr   ZSecItemImportr   r1   r(   ZCFArrayGetCountÚrangeZCFArrayGetValueAtIndexr   r   r;   ZCFRetainÚappendr<   r#   )rI   rD   ÚcertificatesÚ
identitiesZresult_arrayÚfZraw_filedataZfiledatar    Zresult_countÚindexr9   r	   r	   r
   Ú_load_items_from_fileÐ   sT    &ýø

ÿ


ý
rU   c              
   G   s  g }g }dd„ |D ƒ}zÜ|D ]&}t | |ƒ\}}| |¡ | |¡ q|sŠt ¡ }t | |d t |¡¡}t|ƒ | |¡ t	 
| d¡¡ t	 t	jdt t	j¡¡}	t ||¡D ]}
t	 |	|
¡ q®|	W t ||¡D ]}t	 
|¡ qÐS ]}t	 
|¡ qân t ||¡D ]}t	 
|¡ q 0 dS )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   rD   r	   r	   r
   r   /  r   z*_load_client_cert_chain.<locals>.<genexpr>r   N)rU   Úextendr   ZSecIdentityRefZ SecIdentityCreateWithCertificater   r1   r(   rP   r   r#   Úpopr0   r   r2   Ú	itertoolsÚchainr3   )rI   ÚpathsrQ   rR   Ú	file_pathZnew_identitiesZ	new_certsZnew_identityrJ   Ztrust_chainr9   Úobjr	   r	   r
   Ú_load_client_cert_chain  sF     ÿ
ý

ýýÿr]   )N)Ú__doc__r)   r   rX   Úrer?   r$   rB   Zbindingsr   r   r   ÚcompileÚDOTALLr.   r   r   r!   r(   r6   r;   r<   rK   rU   r]   r	   r	   r	   r
   Ú<module>   s*   	ÿ

+(;