3
ãdeb6  ã               @   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j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 j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	   úa/var/www/agendate/envp3/lib/python3.6/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j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>,   s    z-_cf_dictionary_from_tuples.<locals>.<genexpr>c             s   s   | ]}|d  V  qdS )r   Nr	   )r   r   r	   r	   r
   r   -   s    )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   s    t j| ƒ}tj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   ZCFStringCreateWithCStringr   r   ÚkCFStringEncodingUTF8)Zpy_bstrZc_strÚcf_strr	   r	   r
   Ú_cfstr;   s    
r   c             C   s²   d}yht jt jdtjt jƒƒ}|s*tdƒ‚x>| D ]6}t|ƒ}|sHtdƒ‚zt j||ƒ W dt j	|ƒ X q0W W n@ t
k
r¬ } z$|rŒt j	|ƒ tjd|f ƒ‚W Y dd}~X nX |S )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   zUnable to allocate memory!zUnable to allocate array: %s)r   ÚCFArrayCreateMutabler   r   ÚbyrefÚkCFTypeArrayCallBacksÚMemoryErrorr   ÚCFArrayAppendValueÚ	CFReleaseÚBaseExceptionÚsslÚSSLError)ÚlstZcf_arrÚitemr   Úer	   r	   r
   Ú_create_cfstring_arrayI   s(    

"r$   c             C   sn   t j| t jt jƒƒ}tj|tjƒ}|dkrXt jdƒ}tj	||dtjƒ}|sRt
dƒ‚|j}|dk	rj|j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 CFStringRefzutf-8)r   ÚcastÚPOINTERÚc_void_pr   ZCFStringGetCStringPtrr   r   Úcreate_string_bufferZCFStringGetCStringÚOSErrorÚvalueÚdecode)r*   Zvalue_as_void_pÚstringÚbufferÚresultr	   r	   r
   Ú_cf_string_to_unicodeh   s    


r/   c             C   s\   | dkrdS t j| dƒ}t|ƒ}tj|ƒ |dks:|dkrBd|  }|dk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   r   r   r    )ÚerrorZexception_classZcf_error_stringÚoutputr	   r	   r
   Ú_assert_no_error�   s    
r3   c             C   sÞ   | j ddƒ} dd„ tj| ƒD ƒ}|s.tjdƒ‚tjtjdtj	tj
ƒƒ}|sTtjdƒ‚ydx^|D ]V}t|ƒ}|svtjdƒ‚tjtj|ƒ}tj|ƒ |sœtjdƒ‚tj||ƒ tj|ƒ q\W W n  tk
rØ   tj|ƒ ‚ Y nX |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.
    s   
ó   
c             S   s   g | ]}t j|j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   zUnable to allocate memory!zUnable to build cert object!)ÚreplaceÚ_PEM_CERTS_REÚfinditerr   r    r   r   r   r   r   r   r   r   ZSecCertificateCreateWithDatar   r   Ú	Exception)Z
pem_bundleZ	der_certsZ
cert_arrayZ	der_bytesZcertdataÚcertr	   r	   r
   Ú_cert_array_from_pem–   s4    







r?   c             C   s   t jƒ }tj| ƒ|kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   ZSecCertificateGetTypeIDr   ÚCFGetTypeID)r"   Úexpectedr	   r	   r
   Ú_is_certÄ   s    rB   c             C   s   t jƒ }tj| ƒ|kS )z;
    Returns True if a given CFTypeRef is an identity.
    )r   ZSecIdentityGetTypeIDr   r@   )r"   rA   r	   r	   r
   Ú_is_identityÌ   s    rC   c              C   s†   t jdƒ} tj| dd… ƒjdƒ}tj| dd… ƒ}tjƒ }t jj||ƒj	dƒ}t
jƒ }t
j|t|ƒ|ddtj|ƒƒ}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é   zutf-8F)ÚosÚurandomr5   Ú	b16encoder+   ÚtempfileÚmkdtempÚpathÚjoinÚencoder   ZSecKeychainRefZSecKeychainCreater   r   r   r3   )Zrandom_bytesÚfilenameÚpasswordZtempdirectoryZkeychain_pathÚkeychainÚstatusr	   r	   r
   Ú_temporary_keychainÔ   s    
rR   c             C   s  g }g }d}t |dƒ�}|jƒ }W dQ R X z¶tjtj|t|ƒƒ}tjƒ }tj|ddddd| t	j
|ƒƒ}t|ƒ tj|ƒ}	xdt|	ƒD ]X}
tj||
ƒ}t	j|tjƒ}t|ƒr¾tj|ƒ |j|ƒ q‚t|ƒr‚tj|ƒ |j|ƒ q‚W W d|rðtj|ƒ tj|ƒ X ||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   r   r3   ZCFArrayGetCountÚrangeZCFArrayGetValueAtIndexr%   r   rB   ZCFRetainÚappendrC   r   )rP   rK   ÚcertificatesÚ
identitiesZresult_arrayÚfZraw_filedataZfiledatar.   Zresult_countÚindexr"   r	   r	   r
   Ú_load_items_from_file÷   sB    



r\   c             G   sò   g }g }dd„ |D ƒ}z´x.|D ]&}t | |ƒ\}}|j|ƒ |j|ƒ qW |sŽtjƒ }tj| |d tj|ƒƒ}t|ƒ |j|ƒ t	j
|jdƒƒ t	jt	jdtjt	jƒƒ}	x tj||ƒD ]}
t	j|	|
ƒ q´W |	S xtj||ƒD ]}t	j
|ƒ qÚW X 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   rK   r	   r	   r
   r   R  s    z*_load_client_cert_chain.<locals>.<genexpr>r   N)r\   Úextendr   ZSecIdentityRefZ SecIdentityCreateWithCertificater   r   r3   rW   r   r   Úpopr   r   r   Ú	itertoolsÚchainr   )rP   ÚpathsrX   rY   Ú	file_pathZnew_identitiesZ	new_certsZnew_identityrQ   Ztrust_chainr"   Úobjr	   r	   r
   Ú_load_client_cert_chain.  s0     


rd   é   é   )ZSSLv2ZSSLv3ÚTLSv1zTLSv1.1zTLSv1.2c       	      C   sH   t |  \}}d}d}tjd||ƒ}t|ƒ}d}tjd||||ƒ| }|S )z6
    Builds a TLS alert record for an unknown CA.
    re   é0   z>BBé   z>BBBH)ÚTLS_PROTOCOL_VERSIONSÚstructÚpackr   )	ÚversionZver_majZver_minZseverity_fatalZdescription_unknown_caÚmsgZmsg_lenZrecord_type_alertÚrecordr	   r	   r
   Ú_build_tls_unknown_ca_alert‚  s    rp   )N)r   re   )rf   r   )rf   r   )rf   re   )rf   rf   )Ú__doc__r5   r   r_   rF   Úrer   rk   rI   Zbindingsr   r   r   ÚcompileÚDOTALLr;   r   r   r   r$   r/   r3   r?   rB   rC   rR   r\   rd   rj   rp   r	   r	   r	   r
   Ú<module>	   s:   


.#7L