U
    ;g                     @   s  d dl mZmZmZm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 ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZ ddlm Z m!Z!m"Z" dd	l#m$Z$m%Z%m"Z& dd
l'm(Z( ddl)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZF ddlGmHZHmZ ddlImJZJ ejKdk reLZMejNZOnePZOejKdk rejQZRnejRZRddgZSeTdZUeV ZWeWd  eWd fZXG dd de0ZYG dd de/ZZG dd de[Z\G dd de[Z]dS )    )unicode_literalsdivisionabsolute_importprint_functionN   )Certificate)pretty_message)buffer_from_bytesbuffer_from_unicodebytes_from_buffercastderefis_nullnativenewnullrefsizeofstructunwrapwrite_to_buffer   )secur32Secur32Consthandle_error)crypt32Crypt32Constr   )kernel32)	type_namestr_clsbyte_cls	int_types)TLSErrorTLSVerificationErrorTLSDisconnectErrorTLSGracefulDisconnectError)detect_client_auth_requestdetect_other_protocolextract_chainget_dh_params_lengthparse_alertparse_session_inforaise_client_authraise_dh_paramsraise_disconnectionraise_expired_not_yet_validraise_handshakeraise_hostnameraise_no_issuerraise_protocol_errorraise_protocol_versionraise_revokedraise_self_signedraise_verificationraise_weak_signature)load_certificater   )parse_certificate)   )r;      
TLSSession	TLSSockets   (
||
)c                   @   s   e Zd ZdS )_TLSDowngradeErrorN)__name__
__module____qualname__ rC   rC   5/tmp/pip-unpacked-wheel-x1gypflw/oscrypto/_win/tls.pyr?   Q   s   r?   c                   @   s   e Zd ZdZdS )_TLSRetryErrorz
    TLSv1.2 on Windows 7 and 8 seems to have isuses with some DHE_RSA
    ServerKeyExchange messages due to variable length integer encoding. This
    exception is used to trigger a reconnection to attempt the handshake again.
    N)r@   rA   rB   __doc__rC   rC   rC   rD   rE   V   s   rE   c                   @   s>   e Zd ZdZdZdZdZdZdZd
ddZ	dd Z
dd	 ZdS )r=   zj
    A TLS session object that multiple TLSSocket objects can share for the
    sake of session reuse
    NFc              
   C   s<  t |tsttdt||| _|dkr8tdddg}t |trNt|g}nt |tsjttdt||tddddg }|rttdt	||| _
g | _|r0|D ]}t |tr|j}nbt |trt|}nNt |trt|d	}t| }W 5 Q R X nt |ts"ttd
t|| j| q|   dS )a]  
        :param protocol:
            A unicode string or set of unicode strings representing allowable
            protocols to negotiate with the server:

             - "TLSv1.2"
             - "TLSv1.1"
             - "TLSv1"
             - "SSLv3"

            Default is: {"TLSv1", "TLSv1.1", "TLSv1.2"}

        :param manual_validation:
            If certificate and certificate path validation should be skipped
            and left to the developer to implement

        :param extra_trust_roots:
            A list containing one or more certificates to be treated as trust
            roots, in one of the following formats:
             - A byte string of the DER encoded certificate
             - A unicode string of the certificate filename
             - An asn1crypto.x509.Certificate object
             - An oscrypto.asymmetric.Certificate object

        :raises:
            ValueError - when any of the parameters contain an invalid value
            TypeError - when any of the parameters are of the wrong type
            OSError - when an error is returned by the OS crypto library
        zM
                manual_validation must be a boolean, not %s
                NTLSv1TLSv1.1TLSv1.2zu
                protocol must be a unicode string or set of unicode strings,
                not %s
                SSLv3z
                protocol must contain only the unicode strings "SSLv3", "TLSv1",
                "TLSv1.1", "TLSv1.2", not %s
                rbz
                        extra_trust_roots must be a list of byte strings, unicode
                        strings, asn1crypto.x509.Certificate objects or
                        oscrypto.asymmetric.Certificate objects, not %s
                        )
isinstancebool	TypeErrorr   r   _manual_validationsetr   
ValueErrorrepr
_protocols_extra_trust_rootsr   asn1r    r:   openreadAsn1Certificateappend_obtain_credentials)selfprotocolZmanual_validationZextra_trust_rootsZunsupported_protocolsZextra_trust_rootfrC   rC   rD   __init__m   sN    





zTLSSession.__init__c                 C   s  t jt jt jt jd}d}| D ]\}}|| jkr"||O }q"t jt jt j	t j
t jt jt jt jt jt jg
}d| jkr|t jt jt jg ttdt| }t|D ]\}}|||< qt jt jB }	| js| js|	t jO }	n
|	t jO }	ttd}
t |
}t j!|_"d|_#t$ |_%t$ |_&d|_'t$ |_(t||_)||_*||_+d|_,d|_-d|_.|	|_/d|_0ttd}t1t$ t j2t j3t$ |
t$ t$ |t$ 	}t4| || _5dS )zU
        Obtains a credentials handle from secur32.dll for use with SChannel
        )rJ   rG   rH   rI   r   rI   z
ALG_ID[%s]ZSCHANNEL_CREDzCredHandle *N)6r   SP_PROT_SSL3_CLIENTSP_PROT_TLS1_CLIENTSP_PROT_TLS1_1_CLIENTSP_PROT_TLS1_2_CLIENTitemsrS   ZCALG_AES_128ZCALG_AES_256Z	CALG_3DESZ	CALG_SHA1Z
CALG_ECDHEZCALG_DH_EPHEMZCALG_RSA_KEYXZCALG_RSA_SIGNZ
CALG_ECDSAZCALG_DSS_SIGNextendZCALG_SHA512ZCALG_SHA384ZCALG_SHA256r   r   len	enumerateZSCH_USE_STRONG_CRYPTOZSCH_CRED_NO_DEFAULT_CREDSrO   rT   ZSCH_CRED_AUTO_CRED_VALIDATIONZSCH_CRED_MANUAL_CRED_VALIDATIONr   r   ZSCHANNEL_CRED_VERSIONZ	dwVersionZcCredsr   ZpaCredZ
hRootStoreZcMappersZ
aphMappersZcSupportedAlgsZpalgSupportedAlgsZgrbitEnabledProtocolsZdwMinimumCipherStrengthZdwMaximumCipherStrengthZdwSessionLifespandwFlagsZdwCredFormatZAcquireCredentialsHandleWZ
UNISP_NAMEZSECPKG_CRED_OUTBOUNDr   _credentials_handle)r[   Zprotocol_valuesZprotocol_bit_maskkeyvalueZalgsZ	alg_arrayindexalgflagsZschannel_cred_pointerZschannel_credZcred_handle_pointerresultrC   rC   rD   rZ      s~    







zTLSSession._obtain_credentialsc                 C   s$   | j r t| j }t| d | _ d S N)rh   r   ZFreeCredentialsHandler   )r[   rn   rC   rC   rD   __del__  s    zTLSSession.__del__)NFN)r@   rA   rB   rF   rS   Z_ciphersrO   rT   rh   r^   rZ   rp   rC   rC   rC   rD   r=   a   s   
ZQc                   @   s  e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZed=ddZd>ddZd	d
 Zdd Z d?ddZ!dd Z"d@ddZ#dd Z$dd Z%dd Z&dd Z'dAddZ(dd Z)dd  Z*d!d" Z+d#d$ Z,e-d%d& Z.e-d'd( Z/e-d)d* Z0e-d+d, Z1e-d-d. Z2e-d/d0 Z3e-d1d2 Z4e-d3d4 Z5e-d5d6 Z6e-d7d8 Z7e-d9d: Z8d;d< Z9dS )Br>   z8
    A wrapper around a socket.socket that adds TLS
    NFc              
   C   s   t |tjsttdt|t |ts:ttdt||dk	r^t |ts^ttdt|| dd|d}||_||_	z|
  W nb tk
r } zt|j|j}|W 5 d}~X Y n0 tk
r } zt|j}|W 5 d}~X Y nX |S )az  
        Takes an existing socket and adds TLS

        :param socket:
            A socket.socket object to wrap with TLS

        :param hostname:
            A unicode string of the hostname or IP the socket is connected to

        :param session:
            An existing TLSSession object to allow for session reuse, specific
            protocol or manual certificate validation

        :raises:
            ValueError - when any of the parameters contain an invalid value
            TypeError - when any of the parameters are of the wrong type
            OSError - when an error is returned by the OS crypto library
        zU
                socket must be an instance of socket.socket, not %s
                zK
                hostname must be a unicode string, not %s
                N`
                session must be an instance of oscrypto.tls.TLSSession, not %s
                )session)rL   socket_socketrN   r   r   r   r=   _socket	_hostname
_handshaker?   r#   messagecertificaterE   r"   )clsrt   hostnamerr   Z
new_socketeZnew_erC   rC   rD   wrapE  s6    

zTLSSocket.wrap
   c                 C   s  d| _ d| _|dkr$|dkr$d| _n|t|ts@ttdt|t|ts\ttdt||dk	rt|t	j
sttdt|t||f|| _| j| |dkrt }nt|tsttdt||| _| jr|| _z|   W n tk
r`   |   t|jtdg |j|j}|  d| _ || _t||f|| _| j| |   Y nB tk
r   d| _ t||f|| _| j| |   Y nX dS )a  
        :param address:
            A unicode string of the domain name or IP address to connect to

        :param port:
            An integer of the port number to connect to

        :param timeout:
            An integer timeout to use for the socket

        :param session:
            An oscrypto.tls.TLSSession object to allow for session reuse and
            controlling the protocols and validation performed
            NzR
                    address must be a unicode string, not %s
                    zI
                    port must be an integer, not %s
                    zJ
                    timeout must be a number, not %s
                    rq   rI   )_received_bytes_decrypted_bytesru   rL   r   rN   r   r   r!   numbersNumberrs   create_connection
settimeoutr=   _sessionrv   rw   r?   closerS   rP   rO   rT   rp   rE   )r[   addressporttimeoutrr   Znew_sessionrC   rC   rD   r^     sf    


zTLSSocket.__init__c                 C   sn   t td| }td|D ]&}d|| _tj|| _t || _qt	td}t
|}tj|_||_||_||fS )z
        Creates a SecBufferDesc struct and contained SecBuffer structs

        :param number:
            The number of contains SecBuffer objects to create

        :return:
            A tuple of (SecBufferDesc pointer, SecBuffer array)
        zSecBuffer[%d]r   SecBufferDesc)r   r   rangecbBufferr   SECBUFFER_EMPTY
BufferTyper   pvBufferr   r   SECBUFFER_VERSION	ulVersioncBufferspBuffers)r[   numberbuffersrk   sec_buffer_desc_pointersec_buffer_descrC   rC   rD   _create_buffers  s    

zTLSSocket._create_buffersc           (   
   C   s  d}d}zt tjtjt dt }t|r6t	d t
 }| jjD ]B}| }t |tj|t|tjt }|szt	d ||j qDtt d}t| jtj|}t| t|}tt d|}ttd}	t|	 tt d|	}
tt d}tt dtj|d< tt dtj|d< tt dtj |d	< t!t d
}t|}d|_"tt d||_#t!t d}t|}tj$|_%||_&t!t d}t|}||_'t(t |}||_)tt d}t *t ||
||tj+tj,B t |}t	| tj-}t|}t|}t.t/|j0}|dkrbt|j1}t|}t.t/|j2}|j3|d  }t|}t|j4}t5|j6t.t/|j7}t89|}|j|krb|tj:O }t!t d}t|} t(t | | _)tj;| _<d| _=tt dt>| j?| _@t!t d}!t|!}"t(t |"|"_)||"_Att d||"_Bt!t d}#t|#}$t(t |$|$_)t CtjD||!|#}t	| t|}%t5|%j6t.t/|%j7}t89|}|$jE}&|&r|&tjFkrRtG| |&tjHkrtI|}'|'jJrxtK| ntL| |&tjMkrtN|| j? |&tjOkrtP| |&tjQkrtR| tS| |jTt
ddgkrtP| W 5 |rt |d |r
t | X dS )z
        Manually invoked windows certificate chain builder and verification
        step when there are extra trust roots to include in the search process
        Nr   zPCERT_CONTEXT *ZPCERT_CONTEXTz
FILETIME *z	char *[3]zchar *r   r   ZCERT_ENHKEY_USAGEr;   zchar **ZCERT_USAGE_MATCHZCERT_CHAIN_PARAzPCERT_CHAIN_CONTEXT *Z SSL_EXTRA_CERT_CHAIN_POLICY_PARAz	wchar_t *ZCERT_CHAIN_POLICY_PARAzvoid *ZCERT_CHAIN_POLICY_STATUSmd5Zmd2)Ur   CertCloseStoreZCertFreeCertificateChainZCertOpenStorer   ZCERT_STORE_PROV_MEMORYZX509_ASN_ENCODINGr   r   handle_crypt32_errorrP   r   rT   dumpZ CertAddEncodedCertificateToStorere   ZCERT_STORE_ADD_USE_EXISTINGaddsha256r   r   QueryContextAttributesW_context_handle_pointerr   SECPKG_ATTR_REMOTE_CERT_CONTEXTr   r   r   r   ZGetSystemTimeAsFileTimeZPKIX_KP_SERVER_AUTHZSERVER_GATED_CRYPTOZSGC_NETSCAPEr   ZcUsageIdentifierZrgpszUsageIdentifierZUSAGE_MATCH_TYPE_ORZdwTypeUsageZRequestedUsager   ZcbSizeZCertGetCertificateChainZCERT_CHAIN_CACHE_END_CERTZ&CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLYZ.CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGSr   intZcChainZrgpChainZcElementZ
rgpElementZpCertContextr   pbCertEncodedcbCertEncodedrX   loadZ'CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAGZAUTHTYPE_SERVERZ
dwAuthTypeZ	fdwChecksr
   rv   ZpwszServerNamerg   ZpvExtraPolicyParaZ CertVerifyCertificateChainPolicyZCERT_CHAIN_POLICY_SSLZdwErrorZCERT_E_EXPIREDr/   ZCERT_E_UNTRUSTEDROOTr9   self_signedr6   r2   ZCERT_E_CN_NO_MATCHr1   TRUST_E_CERT_SIGNATUREr8   ZCRYPT_E_REVOKEDr5   r7   Z	hash_algo)(r[   storeZcert_chain_context_pointerZcert_hashescert	cert_datarn   cert_context_pointer_pointercert_context_pointerZorig_now_pointerZnow_pointerZusage_identifiersZcert_enhkey_usage_pointerZcert_enhkey_usageZcert_usage_match_pointerZcert_usage_matchZcert_chain_para_pointerZcert_chain_paraZcert_chain_para_sizeZ"cert_chain_context_pointer_pointerZcert_chain_policy_para_flagsZcert_chain_contextZ
num_chainsZfirst_simple_chain_pointerZfirst_simple_chainZnum_elementsZlast_element_pointerZlast_elementZlast_element_certZlast_element_cert_dataZ	last_certZ(ssl_extra_cert_chain_policy_para_pointerZ ssl_extra_cert_chain_policy_paraZcert_chain_policy_para_pointerZcert_chain_policy_paraZ cert_chain_policy_status_pointerZcert_chain_policy_statuscert_contexterroroscrypto_certrC   rC   rD   _extra_trust_root_validation  s   





















z&TLSSocket._extra_trust_root_validationc           !      C   s  d}d}d}zzd|r | j}nttd}|}tjdtj	dtj
dtjdtjd	tjd
tjdi}d| _|D ]}|  j|O  _qf| d\}}tj|d _| d\}	}tj|d _tj|d _ttd}
|r|}t }n
t }|}t| jj|| j| jddt d||	|
t }|ttjtjgkr*t|t |s6|}n|}d}d}|d jdkrt|d j|d j}||7 }| j !| d|d _t|d j t |d _t"d}t#td||d _d}|tjkrz$d}| j $d}|dkrt%  W n t&k
r
   d}Y nX ||7 }|  j'|7  _'t(| j'|d _t)|| j' t| jj|| j| jdd|dt |	|
t }|tj*krtj|d _|d jtj+krtj+|d _d|d _t |d jst|d j t |d _|rt%  q|tj,kr&t-|rt.  t/|}|r |dkr t0  t1  |tj2krJt3|}t4|d | j |tj5krjt3|}t6|d  |tj7krt3|}|d }t8|}|j9st:| t;| |tj<krt=|dk rt>  |tj?krt.  |t@jAkrtB| |tjCkr|d jdkr|t|d j|d j}||7 }|dd }|dksF|dkr|d| jjDkr|t(| jjDdkr|t3|}tEd|d t-|rt.  tF|rtG| t1  |tjHks|tjIkrd| jjDkrtJd|rt%  |tjKkrt=|dk rt>  |ttjtjgkrt|t |d jdkr~t|d j|d j}||7 }| j !| d|d _t|d j t |d _|d jtjLkr|d j}| j'| d | _'tj+|d _d|d _t|d j t |d _|tjkr || d }nd| _'qtMtd}tN|tjO|}t|t tP|}tjQdtjRdtjSd tjTd!tjUdiVtWtX|jYtZ|jY| _[| j[tdd d!dgkrt\||}|d" | _]|d# | _^|d$ | __|d% | _`ta|
}|D ]&}||B dkrtbtcd&|| q|sb|| _d}tMtd'}tN| jtjd|}t| tP|} tWtX| je| _ftWtX| jg| _htWtX| ji| _j| jf| jh | jj | _k| jjlrt| m  W n& tbtnjofk
r   | p   Y nX W 5 |rt |d jst|d j t |d jst|d j |rt| X dS )(z
        Perform an initial TLS handshake, or a renegotiation

        :param renegotiate:
            If the handshake is for a renegotiation
        Nr   r   zCtxtHandle *zreplay detectionzsequence detectionZconfidentialityzmemory allocationZ	integrityzstream orientationzdisable automatic client authr   ULONG *r   i   BYTE *F    T)r   F   i      r<      (   +rI   zMServer certificate verification failed - weak certificate signature algorithmzTLS handshake failedZSecPkgContext_ConnectionInfoZSSLv2rJ   rG   rH   cipher_suitecompression
session_idsession_ticketzl
                        Unable to obtain a credential context with the property %s
                        ZSecPkgContext_StreamSizes)qr   r   r   FreeContextBufferDeleteSecurityContextr   r   r   ZISC_REQ_REPLAY_DETECTZISC_REQ_SEQUENCE_DETECTZISC_REQ_CONFIDENTIALITYZISC_REQ_ALLOCATE_MEMORYZISC_REQ_INTEGRITYZISC_REQ_STREAMZISC_REQ_USE_SUPPLIED_CREDS_context_flagsr   SECBUFFER_TOKENr   SECBUFFER_ALERTr   InitializeSecurityContextWr   rh   rv   rP   SEC_E_OKSEC_I_CONTINUE_NEEDEDr   r"   r   r   ru   sendr	   r   recvr.   socket_error_clsr   re   r   SEC_E_INCOMPLETE_MESSAGEr   ZSEC_E_ILLEGAL_MESSAGEr&   r,   r*   r4   r0   ZSEC_E_WRONG_PRINCIPALr(   r1   ZSEC_E_CERT_EXPIREDr/   ZSEC_E_UNTRUSTED_ROOTr9   r   r2   r6   ZSEC_E_INTERNAL_ERRORr)   r-   ZSEC_I_INCOMPLETE_CREDENTIALSr   r   r8   ZSEC_E_INVALID_TOKENrS   r?   r'   r3   ZSEC_E_BUFFER_TOO_SMALLZSEC_E_MESSAGE_ALTEREDrE   ZSEC_E_INVALID_PARAMETERSECBUFFER_EXTRAr   r   ZSECPKG_ATTR_CONNECTION_INFOr   ZSP_PROT_SSL2_CLIENTr_   r`   ra   rb   getr   r   Z
dwProtocolr   	_protocolr+   _cipher_suite_compression_session_id_session_ticketr   OSErrorr   ZSECPKG_ATTR_STREAM_SIZESZcbHeader_header_sizeZcbMaximumMessage_message_sizeZ	cbTrailer_trailer_size_buffer_sizerT   r   rs   r   r   )!r[   renegotiateZ
in_buffersout_buffersZnew_context_handle_pointerZtemp_context_handle_pointerZrequested_flagsflagZin_sec_buffer_desc_pointerout_sec_buffer_desc_pointeroutput_context_flags_pointerZfirst_handleZsecond_handlern   Zhandshake_server_bytesZhandshake_client_bytestokenZin_data_buffer
bytes_readZ	fail_lateZ
alert_infochainr   r   Zalert_bytesZalert_numberextra_amountZconnection_info_pointerZconnection_infoZsession_infoZoutput_context_flagsZstream_sizes_pointerZstream_sizesrC   rC   rD   rw     s   
       








 








     
 







zTLSSocket._handshakec                    sX  t |tsttdt|jdkrZjdkrRjd| }j|d _|S   jst	j
_d\__tjjd _ttdjjd _t|j
}t jd  jd jd jd	  fd
d}j}t|}d_|dkr&ds&d_|S tjdk}||k r,|rp jj|7  _tjdkrpt  ttjj
}|dkrq,|jd _tjjd|  tjjdt }d}|tj kr|  d}q4nX|tj!krd_"#  q,n8|tj$kr*j%dd &|S |tj'kr@t(|t) t*tj+tj,tj-g}	d}
 fD ]f}|j}|tjkr|t.|j|j7 }t|}n2|tj/krt0t1|j}
n||	krdt2td|qd|
rj||
 d _nj|d _|  drd}|s4tjdkr4q,q4t||krT||d _|d| }|S )a0  
        Reads data from the TLS-wrapped socket

        :param max_length:
            The number of bytes to read

        :raises:
            socket.socket - when a non-TLS socket error occurs
            oscrypto.errors.TLSError - when a TLS-related error occurs
            ValueError - when any of the parameters contain an invalid value
            TypeError - when any of the parameters are of the wrong type
            OSError - when an error is returned by the OS crypto library

        :return:
            A byte string of the data read
        zG
                max_length must be an integer, not %s
                Nr   r      r   r   r   r;   c                      s^   t j _ttdj _d _t j__d_t j__d_t j__d_d S )Nr   r   )	r   SECBUFFER_DATAr   r   r   _decrypt_data_bufferr   r   r   rC   Zbuf0Zbuf1buf2Zbuf3Z
null_valuer[   rC   rD   _reset_buffers  s    z&TLSSocket.read.<locals>._reset_buffersFT)r   z]
                        Unexpected decrypt output buffer of type %s
                        )3rL   r!   rN   r   r   r   r   _raise_closedr   r	   r   r   _decrypt_desc_decrypt_buffersr   r   r   r   r   r   maxr   re   select_readr   ru   r   r.   minr   r   ZDecryptMessager   ZSEC_I_CONTEXT_EXPIRED_remote_closedshutdownZSEC_I_RENEGOTIATErw   rW   r   r   r"   rP   r   SECBUFFER_STREAM_HEADERSECBUFFER_STREAM_TRAILERr   r   r   r   r   )r[   
max_lengthoutputZto_recvr   Z
output_lenZdo_readdata_lenrn   Zvalid_buffer_typesr   bufZbuffer_typerC   r   rD   rW     s    













zTLSSocket.readc                 C   s8   t | jdkrdS t| jgg g |\}}}t |dkS )aZ  
        Blocks until the socket is ready to be read from, or the timeout is hit

        :param timeout:
            A float - the period of time to wait for data to be read. None for
            no time limit.

        :return:
            A boolean - if data is ready to be read. Will only be False if
            timeout is not None.
        r   T)re   r   selectru   )r[   r   Z
read_ready_rC   rC   rD   r     s    zTLSSocket.select_readc           	      C   s   t |ts&t |ts&ttdt|d}t |t}t| jdkrP| j}d| _n
| d}t|}||7 }|r|	|}|dk	r|
 }qq4td|t| d }|||}|dkr4|t| }qq4||d | j | _|d| S )a  
        Reads data from the socket until a marker is found. Data read may
        include data beyond the marker.

        :param marker:
            A byte string or regex object from re.compile(). Used to determine
            when to stop reading. Regex objects are more inefficient since
            they must scan the entire byte string of read data each time data
            is read off the socket.

        :return:
            A byte string of the data read
        z_
                marker must be a byte string or compiled regex object, not %s
                r   r   r   Nr   )rL   r    PatternrN   r   r   re   r   rW   searchendr   find)	r[   markerr   Zis_regexchunkoffsetmatchr   startrC   rC   rD   
read_until  s2    


zTLSSocket.read_untilc                 C   s
   |  tS )z
        Reads a line from the socket, including the line ending of "\r\n", "\r",
        or "\n"

        :return:
            A byte string of the next line from the socket
        )r   _line_regexr[   rC   rC   rD   	read_line  s    	zTLSSocket.read_linec                 C   s0   d}|}|dkr,||  |7 }|t| }q|S )z
        Reads exactly the specified number of bytes from the socket

        :param num_bytes:
            An integer - the exact number of bytes to read

        :return:
            A byte string of the data that was read
        r   r   )rW   re   )r[   	num_bytesr   	remainingrC   rC   rD   read_exactly  s    zTLSSocket.read_exactlyc              
   C   s  | j dkr|   | jst| j| j | j | _| d\| _| _	t
j| j	d _| j| j	d _ttd| j| j	d _t
j| j	d _t| j| j| j	d _t
j| j	d _| j| j	d _t| j| j| j | j	d _t|dkrtt|| j}t| j|d| | j || j	d _t| j| j| | j	d _t| j d| jd}|t
jkrVt|t tt| j	d j}|tt| j	d j7 }|tt| j	d j7 }z| jt| j| W n: t j!k
r } z|j"dkrt#   W 5 d}~X Y nX ||d }qdS )a  
        Writes data to the TLS-wrapped socket

        :param data:
            A byte string to write to the socket

        :raises:
            socket.socket - when a non-TLS socket error occurs
            oscrypto.errors.TLSError - when a TLS-related error occurs
            ValueError - when any of the parameters contain an invalid value
            TypeError - when any of the parameters are of the wrong type
            OSError - when an error is returned by the OS crypto library
        Nr   r   r   r   r   iE'  )$r   r   _encrypt_data_bufferr	   r   r   r   r   _encrypt_desc_encrypt_buffersr   r   r   r   r   r   r   r   r   r   re   r   r   ZEncryptMessager   r   r"   r   r   ru   r   r   rs   r   errnor.   )r[   dataZto_writern   Zto_sendr|   rC   rC   rD   write  sH    

zTLSSocket.writec                 C   s&   t  g | jgg |\}}}t|dkS )aw  
        Blocks until the socket is ready to be written to, or the timeout is hit

        :param timeout:
            A float - the period of time to wait for the socket to be ready to
            written to. None for no time limit.

        :return:
            A boolean - if the socket is ready for writing. Will only be False
            if timeout is not None.
        r   )r   ru   re   )r[   r   r   Zwrite_readyrC   rC   rD   select_write'  s    zTLSSocket.select_writec           
      C   s  | j dkrdS d}zHtdkrttd}d|d _tj|d _ttdtd|d _ttd	}t|}tj|_d|_||_t| j |}t|t | d
\}}tj|d _tj|d _ttd}t| jj | j | j!| j"ddt# dt# ||t# }t$tj%tj&tj'g}||krt|t t(|d j|d j}	z| j)|	 W n tj
k
rX   Y nX W 5 |rt|d jst|d j t|d jst|d j t| j  d| _ z| jtj	 W n tj
k
r   Y nX X dS )z
        Shuts down the TLS session and then shuts down the underlying socket

        :raises:
            OSError - when an error is returned by the OS crypto library
        Nr   r   )r   r   zSecBuffer[1]r   r   s      r   r   r   )*r   r   r   r   r   r   ru   r   rs   	SHUT_RDWRr   _win_version_infor   r   r   r   r   r   r	   r   r   r   r   r   r   ZApplyControlTokenr   r"   r   r   r   r   rh   rv   r   r   rP   r   ZSEC_E_CONTEXT_EXPIREDr   r   r   )
r[   r   r   r   r   rn   r   r   Zacceptable_resultsr   rC   rC   rD   r   7  sr    








zTLSSocket.shutdownc                 C   sF   z|   W 5 | j r@z| j   W n tjk
r8   Y nX d| _ X dS )zN
        Shuts down the TLS session and socket and forcibly closes it
        N)ru   r   rs   r   r   r  rC   rC   rD   r     s    zTLSSocket.closec           
   
   C   s   t td}t| jtj|}t|t t	|}t
td|}t	|}t|jtt|j}t|| _g | _d}zd|j}t|t }t|st	|}t|jtt|j}	|	|kr| jt|	 t||}qW 5 |rt|d X dS )zh
        Reads end-entity and intermediate certificate information from the
        TLS session
        zCERT_CONTEXT **zCERT_CONTEXT *Nr   )r   r   r   r   r   r   r   r   r"   r   r   r   r   r   r   r   rX   r   _certificate_intermediatesr   Z
hCertStoreZCertEnumCertificatesInStorer   r   rY   )
r[   r   rn   r   r   r   Zstore_handleZcontext_pointercontextr
  rC   rC   rD   _read_certificates  s2    

zTLSSocket._read_certificatesc                 C   s   | j rtdntddS )zi
        Raises an exception describing if the local or remote end closed the
        connection
        z$The remote end closed the connectionz!The connection was already closedN)r   r%   r$   r  rC   rC   rD   r     s    
zTLSSocket._raise_closedc                 C   s*   | j dkr|   | jdkr$|   | jS )zu
        An asn1crypto.x509.Certificate object of the end-entity certificate
        presented by the server
        N)r   r   r  r  r  rC   rC   rD   ry     s
    

zTLSSocket.certificatec                 C   s*   | j dkr|   | jdkr$|   | jS )zz
        A list of asn1crypto.x509.Certificate objects that were presented as
        intermediates by the server
        N)r   r   r  r  r  r  rC   rC   rD   intermediates  s
    

zTLSSocket.intermediatesc                 C   s   | j S )zg
        A unicode string of the IANA cipher suite name of the negotiated
        cipher suite
        )r   r  rC   rC   rD   r     s    zTLSSocket.cipher_suitec                 C   s   | j S )zM
        A unicode string of: "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3"
        )r   r  rC   rC   rD   r\     s    zTLSSocket.protocolc                 C   s   | j S )z5
        A boolean if compression is enabled
        )r   r  rC   rC   rD   r     s    zTLSSocket.compressionc                 C   s   | j S zM
        A unicode string of "new" or "reused" or None for no ticket
        )r   r  rC   rC   rD   r     s    zTLSSocket.session_idc                 C   s   | j S r  )r   r  rC   rC   rD   r     s    zTLSSocket.session_ticketc                 C   s   | j S )zM
        The oscrypto.tls.TLSSession object used for this connection
        )r   r  rC   rC   rD   rr     s    zTLSSocket.sessionc                 C   s   | j S )zN
        A unicode string of the TLS server domain name or IP address
        )rv   r  rC   rC   rD   r{     s    zTLSSocket.hostnamec                 C   s   | j  d S )zJ
        An integer of the port number the socket is connected to
        r   )rt   getpeernamer  rC   rC   rD   r   %  s    zTLSSocket.portc                 C   s   | j dkr|   | jS )z9
        The underlying socket.socket connection
        N)r   r   ru   r  rC   rC   rD   rt   -  s    
zTLSSocket.socketc                 C   s   |    d S ro   )r   r  rC   rC   rD   rp   8  s    zTLSSocket.__del__)N)r~   N)F)N)N):r@   rA   rB   rF   ru   r   r   r   rv   r   r   r   r   r   r  r  r  r   r   r   r  r  r   r   r   r   r   r   classmethodr}   r^   r   r   rw   rW   r   r   r  r  r  r  r   r   r  r   propertyry   r  r   r\   r   r   r   rr   r{   r   rt   rp   rC   rC   rC   rD   r>     s   >
W 3
  0 +
7>
T(











)^
__future__r   r   r   r   sysrert   rs   r   r   Z_asn1r   rX   _errorsr   _ffir	   r
   r   r   r   r   r   r   r   r   r   r   r   r   Z_secur32r   r   r   Z_crypt32r   r   r   Z	_kernel32r   _typesr   r   r    r!   errorsr"   r#   r$   r%   Z_tlsr&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   
asymmetricr9   keysr:   version_infoxranger   r   r   ZWindowsErrorZ_pattern_typer   __all__compiler   getwindowsversionZ_gwvr  r?   rE   objectr=   r>   rC   rC   rC   rD   <module>   sD   @T
 ?