o
    ȷeb6                     @   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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 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dd d!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   )CFConstCoreFoundationSecuritys;   -----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
   a/var/www/ideatree/venv/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   s    t | }ttj|tj}|S )zi
    Given a Python binary data, create a CFString.
    The string must be CFReleased by the caller.
    )ctypesc_char_pr   CFStringCreateWithCStringr   r   kCFStringEncodingUTF8)py_bstrc_strcf_strr
   r
   r   _cfstr;   s   
r%   c              
   C   s   d}z7t t jdtt j}|std| D ]}t|}|s#tdzt || W t 	| qt 	| w W |S  t
yT } z|rHt 	| td|f d}~ww )z
    Given a list of Python binary data, create an associated CFMutableArray.
    The array must be CFReleased by the caller.

    Raises an ssl.SSLError on failure.
    Nr   Unable to allocate memory!zUnable to allocate array: %s)r   CFArrayCreateMutabler   r   byrefkCFTypeArrayCallBacksMemoryErrorr%   CFArrayAppendValue	CFReleaseBaseExceptionsslSSLError)lstcf_arritemr$   er
   r
   r   _create_cfstring_arrayI   s0   

r4   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)r   castPOINTERc_void_pr   CFStringGetCStringPtrr   r!   create_string_bufferCFStringGetCStringOSErrorvaluedecode)r=   value_as_void_pstringbufferresultr
   r
   r   _cf_string_to_unicodeh   s   


rC   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   SecCopyErrorMessageStringrC   r   r,   r.   r/   )errorexception_classcf_error_stringoutputr
   r
   r   _assert_no_error   s   
rJ   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yh   t|  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>   s    z(_cert_array_from_pem.<locals>.<listcomp>zNo root certificates specifiedr   r&   zUnable to build cert object!)replace_PEM_CERTS_REfinditerr.   r/   r   r'   r   r   r(   r)   r   r   SecCertificateCreateWithDatar,   r+   	Exception)
pem_bundle	der_certs
cert_array	der_bytescertdatacertr
   r
   r   _cert_array_from_pem   s@   






r\   c                 C      t  }t| |kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   SecCertificateGetTypeIDr   CFGetTypeIDr2   expectedr
   r
   r   _is_cert      rb   c                 C   r]   )z;
    Returns True if a given CFTypeRef is an identity.
    )r   SecIdentityGetTypeIDr   r_   r`   r
   r
   r   _is_identity   rc   re   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   r5   F)osurandomrL   	b16encoder>   tempfilemkdtemppathjoinencoder   SecKeychainRefSecKeychainCreater   r   r(   rJ   )random_bytesfilenamepasswordtempdirectorykeychain_pathkeychainstatusr
   r
   r   _temporary_keychain   s   
ry   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   
CFArrayRefr   SecItemImportr   r(   rJ   CFArrayGetCountrangeCFArrayGetValueAtIndexr6   r   rb   CFRetainappendre   r,   )rw   rm   certificates
identitiesresult_arrayfraw_filedatafiledatarB   result_countindexr2   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   rm   r
   r
   r   r   R  r   z*_load_client_cert_chain.<locals>.<genexpr>r   )r   extendr   SecIdentityRef SecIdentityCreateWithCertificater   r(   rJ   r   r   r,   popr'   r   r)   	itertoolschainr+   )rw   pathsr   r   	file_pathnew_identities	new_certsnew_identityrx   trust_chainr2   objr
   r
   r   _load_client_cert_chain.  s:    


r   )r      )   r   )r   r   )r   r   )r   r   )SSLv2SSLv3TLSv1zTLSv1.1zTLSv1.2c           	      C   sH   t |  \}}d}d}td||}t|}d}td||||| }|S )z6
    Builds a TLS alert record for an unknown CA.
    r   0   z>BB   z>BBBH)TLS_PROTOCOL_VERSIONSstructpackr   )	versionver_majver_minseverity_fataldescription_unknown_camsgmsg_lenrecord_type_alertrecordr
   r
   r   _build_tls_unknown_ca_alert  s   r   r   )__doc__rL   r   r   rh   rer.   r   rk   bindingsr   r   r   compileDOTALLrR   r   r   r%   r4   rC   rJ   r\   rb   re   ry   r   r   r   r   r
   r
   r
   r   <module>   s@    	

.#7L	