o
    b/                     @   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	   i/var/www/secure340b-portal/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   	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 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   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   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   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} 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>u   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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   s@   





r9   c                 C      t  }t| |kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   ZSecCertificateGetTypeIDr   CFGetTypeIDitemexpectedr	   r	   r
   _is_cert      r?   c                 C   r:   )z;
    Returns True if a given CFTypeRef is an identity.
    )r   ZSecIdentityGetTypeIDr   r;   r<   r	   r	   r
   _is_identity   r@   rA   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   ZSecKeychainRefZSecKeychainCreater   r   r4   r)   )Zrandom_bytesfilenamepasswordZtempdirectoryZkeychain_pathkeychainstatusr	   r	   r
   _temporary_keychain   s    
rP   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 |rt| 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   Z
CFArrayRefr   ZSecItemImportr   r4   r)   ZCFArrayGetCountrangeZCFArrayGetValueAtIndexr   r   r?   ZCFRetainappendrA   r$   )rN   rI   certificates
identitiesZresult_arrayfZraw_filedataZfiledatar!   Zresult_countindexr=   r	   r	   r
   _load_items_from_file   sZ   








rZ   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   rI   r	   r	   r
   r   2  r   z*_load_client_cert_chain.<locals>.<genexpr>r   )rZ   extendr   ZSecIdentityRefZ SecIdentityCreateWithCertificater   r4   r)   rU   r   r$   popr3   r   r5   	itertoolschainr6   )rN   pathsrV   rW   	file_pathZnew_identitiesZ	new_certsZnew_identityrO   Ztrust_chainr=   objr	   r	   r
   _load_client_cert_chain  sB    


rc   r[   )__doc__r+   r   r^   rerD   r%   rG   Zbindingsr   r   r   compileDOTALLr1   r   r   r"   r)   r9   r?   rA   rP   rZ   rc   r	   r	   r	   r
   <module>   s,    	

.(;