
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
nf·\‚/  ã               @   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j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 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	   ú/usr/lib/python3.6/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   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)ÚctypesÚcastZPOINTERZc_void_pr   ZCFStringGetCStringPtrr   ZkCFStringEncodingUTF8Z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 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   Ú	CFReleaseÚsslÚSSLError)ÚerrorZexception_classZcf_error_stringÚoutputr	   r	   r
   Ú_assert_no_errorX   s    
r"   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   )Úbase64Z	b64decodeÚgroup)r   Úmatchr	   r	   r
   ú
<listcomp>v   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certdataZcertr	   r	   r
   Ú_cert_array_from_pemm   s4    






r0   c             C   s   t jƒ }tj| ƒ|kS )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   ZSecCertificateGetTypeIDr   ÚCFGetTypeID)ÚitemÚexpectedr	   r	   r
   Ú_is_cert›   s    r4   c             C   s   t jƒ }tj| ƒ|kS )z;
    Returns True if a given CFTypeRef is an identity.
    )r   ZSecIdentityGetTypeIDr   r1   )r2   r3   r	   r	   r
   Ú_is_identity£   s    r5   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Úurandomr$   Z	b16encoder   ÚtempfileZmkdtempÚpathÚjoinÚencoder   ZSecKeychainRefZSecKeychainCreater   r   r,   r"   )Zrandom_bytesÚfilenameZpasswordZtempdirectoryZkeychain_pathÚkeychainÚstatusr	   r	   r
   Ú_temporary_keychain«   s    
rA   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,   r"   ZCFArrayGetCountÚrangeZCFArrayGetValueAtIndexr   r   r4   ZCFRetainÚappendr5   r   )r?   r;   ÚcertificatesÚ
identitiesZresult_arrayÚfZraw_filedataZfiledatar   Zresult_countÚindexr2   r	   r	   r
   Ú_load_items_from_fileÓ   sH    




rK   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   r;   r	   r	   r
   r   2  s    z*_load_client_cert_chain.<locals>.<genexpr>r   N)rK   Úextendr   ZSecIdentityRefZ SecIdentityCreateWithCertificater   r,   r"   rF   r   r   Úpopr+   r   r-   Ú	itertoolsÚchainr.   )r?   ÚpathsrG   rH   Z	file_pathZnew_identitiesZ	new_certsZnew_identityr@   Ztrust_chainr2   Úobjr	   r	   r
   Ú_load_client_cert_chain  s6     


rR   )N)Ú__doc__r$   r   rN   Úrer8   r   r:   Zbindingsr   r   r   ÚcompileÚDOTALLr)   r   r   r   r"   r0   r4   r5   rA   rK   rR   r	   r	   r	   r
   Ú<module>	   s(   


.(;