U
    ÓZjQ3  ã                	   @   sD  d Z ddlZddlZddlmZmZ ddlmZmZ zddlm	Z	 e
e	jdƒ W n eefk
rl   dZ	Y nX ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlZddlZddlmZmZ ddlmZ ddlmZ ddl m!Z! ddlm"Z" e #e$¡Z%G dd„ de&ƒZ'dd„ Z(dd„ Z)dd„ Z*dd„ Z+dd„ Z,dS )z*Tools for checking certificate revocation.é    N)ÚdatetimeÚ	timedelta)ÚPopenÚPIPE)ÚocspÚsignature_hash_algorithm)Úx509)Údefault_backend)Úserialization)Úhashes)ÚUnsupportedAlgorithmÚInvalidSignature)ÚOptionalÚTuple)Úcrypto_util)Úerrors)ÚRenewableCert)Úutilc                   @   s*   e Zd ZdZd
dd„Zdd„ Zdd„ Zd	S )ÚRevocationCheckerzEThis class figures out OCSP checking on this system, and performs it.Fc                 C   s~   d| _ |pt | _| jrzt d¡s6t d¡ d| _ d S tdddddgttdd	�}| 	¡ \}}d
|krpdd„ | _
n
dd„ | _
d S )NFÚopensslz-openssl not installed, can't check revocationTr   ú-headerÚvarÚval)ÚstdoutÚstderrÚuniversal_newlinesz	Missing =c                 S   s
   d|  gS )NzHost=© ©Úhostr   r   úO/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/certbot/ocsp.pyÚ<lambda>1   ó    z,RevocationChecker.__init__.<locals>.<lambda>c                 S   s   d| gS )NÚHostr   r   r   r   r   r    3   r!   )Úbrokenr   Úuse_openssl_binaryr   Z
exe_existsÚloggerÚinfor   r   ÚcommunicateÚ	host_args)ÚselfZenforce_openssl_binary_usageZtest_host_formatZ_outÚerrr   r   r   Ú__init__"   s     

  ÿzRevocationChecker.__init__c                 C   sp   |j |j }}| jrdS tj t ¡ ¡}|j|kr6dS t	|ƒ\}}|rJ|sNdS | j
rd|  ||||¡S t|||ƒS )a  Get revoked status for a particular cert version.

        .. todo:: Make this a non-blocking call

        :param `.storage.RenewableCert` cert: Certificate object
        :returns: True if revoked; False if valid or the check failed or cert is expired.
        :rtype: bool

        F)ÚcertÚchainr#   ÚpytzÚUTCÚfromutcr   ÚutcnowZtarget_expiryÚ_determine_ocsp_serverr$   Ú_check_ocsp_openssl_binÚ_check_ocsp_cryptography)r)   r,   Ú	cert_pathÚ
chain_pathÚnowÚurlr   r   r   r   Úocsp_revoked5   s    
zRevocationChecker.ocsp_revokedc                 C   s’   dddd|d|d|d|d|d	d
g|   |¡ }t d|¡ t d |¡¡ ztj|tjd�\}}W n$ tjk
r„   t d|¡ Y dS X t	|||ƒS )Nr   r   z	-no_noncez-issuerz-certz-urlz-CAfilez-verify_otherz-trust_otherr   zQuerying OCSP for %sú )Úlogú*OCSP check failed for %s (are we offline?)F)
r(   r%   ÚdebugÚjoinr   Ú
run_scriptr   ÚSubprocessErrorr&   Ú_translate_ocsp_query)r)   r5   r6   r   r8   ÚcmdÚoutputr*   r   r   r   r3   T   s2         øø	z)RevocationChecker._check_ocsp_openssl_binN)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r9   r3   r   r   r   r   r      s   
r   c              	      sÆ   t | dƒ�}t | ¡ tƒ ¡}W 5 Q R X z:|j tj¡}tjj	‰ ‡ fdd„|j
D ƒ}|d jj
}W n( tjtfk
rŠ   t d| ¡ Y dS X | ¡ }| d¡d  d	¡}|r´||fS t d
|| ¡ dS )zÎExtract the OCSP server host from a certificate.

    :param str cert_path: Path to the cert we're checking OCSP for
    :rtype tuple:
    :returns: (OCSP server URL or None, OCSP server host or None)

    Úrbc                    s   g | ]}|j ˆ kr|‘qS r   )Zaccess_method)Ú.0Údescription©Zocsp_oidr   r   Ú
<listcomp>x   s    
ÿz*_determine_ocsp_server.<locals>.<listcomp>r   zCannot extract OCSP URI from %s)NNz://é   ú/z4Cannot process OCSP host from URL (%s) in cert at %s)Úopenr   Úload_pem_x509_certificateÚreadr	   Ú
extensionsÚget_extension_for_classZAuthorityInformationAccessZAuthorityInformationAccessOIDZOCSPÚvalueZaccess_locationÚExtensionNotFoundÚ
IndexErrorr%   r&   ÚrstripÚ	partition)r5   Úfile_handlerr,   Ú	extensionZdescriptionsr8   r   r   rK   r   r2   j   s     	r2   c              
   C   s   t |dƒ�}t | ¡ tƒ ¡}W 5 Q R X t | dƒ�}t | ¡ tƒ ¡}W 5 Q R X t ¡ }| ||t 	¡ ¡}| 
¡ }| tjj¡}ztj||ddid�}	W n* tjjk
rÂ   tjd| dd� Y dS X |	jd	krât d
| |	j¡ dS t |	j¡}
|
jtjjk�rt d| |
j¡ dS zt|
||| ƒ W n¸ tk
�rV } zt t|ƒ¡ W 5 d }~X Y n¦ tj k
�rˆ } zt t|ƒ¡ W 5 d }~X Y nt t!k
�r¨   t d| ¡ Y nT t"k
�rÜ } zt d| t|ƒ¡ W 5 d }~X Y n X t #d| |
j$¡ |
j$tj%j&kS dS )NrH   zContent-Typezapplication/ocsp-request)ÚdataÚheadersr<   T)Úexc_infoFéÈ   z*OCSP check failed for %s (HTTP status: %d)z'Invalid OCSP response status for %s: %sz)Invalid signature on OCSP response for %sz!Invalid OCSP response for %s: %s.z%OCSP certificate status for %s is: %s)'rO   r   rP   rQ   r	   r   ZOCSPRequestBuilderZadd_certificater   ÚSHA1ÚbuildZpublic_bytesr
   ZEncodingZDERÚrequestsÚpostÚ
exceptionsÚRequestExceptionr%   r&   Ústatus_codeZload_der_ocsp_responseÚcontentZresponse_statusZOCSPResponseStatusZ
SUCCESSFULÚerrorÚ_check_ocsp_responser   Ústrr   ÚErrorr   ÚAssertionErrorr=   Zcertificate_statusZOCSPCertStatusZREVOKED)r5   r6   r8   rY   Úissuerr,   ZbuilderÚrequestZrequest_binaryÚresponseÚresponse_ocspÚerg   r   r   r   r4   ‰   sR    ÿ

 ÿ$ ÿr4   c                 C   sª   | j |j krtdƒ‚t| ||ƒ t| jt|jƒƒrJ| j|jksJ| j|jkrRtdƒ‚t 	¡ }| j
shtdƒ‚| j
|tdd� kr„tdƒ‚| jr¦| j|tdd� k r¦tdƒ‚dS )	z4Verify that the OCSP is valid for serveral criteriaszMthe certificate in response does not correspond to the certificate in requestz<the issuer does not correspond to issuer of the certificate.zparam thisUpdate is not set.é   )Úminutesz"param thisUpdate is in the future.z param nextUpdate is in the past.N)Zserial_numberrk   Ú_check_ocsp_response_signatureÚ
isinstanceZhash_algorithmÚtypeZissuer_key_hashZissuer_name_hashr   r1   Zthis_updater   Znext_update)ro   Zrequest_ocspÚissuer_certr5   r7   r   r   r   rh   º   s     
ÿ
þrh   c              	      sô   ˆ j |jkrt d|¡ |}n´t d|¡ ‡ fdd„ˆ jD ƒ}|sJtdƒ‚|d }|j|jkrftdƒ‚z"|j t	j
¡}t	jjj|jk}W n t	jtfk
r¦   d}Y nX |s´td	ƒ‚|j}t | ¡ |j|j|¡ ˆ j}t | ¡ ˆ jˆ j|¡ d
S )zIVerify an OCSP response signature against certificate issuer or responderzGOCSP response for certificate %s is signed by the certificate's issuer.zGOCSP response for certificate %s is delegated to an external responder.c                    s   g | ]}|j ˆ jkr|‘qS r   )ÚsubjectÚresponder_name)rI   r,   ©ro   r   r   rL   è   s    ÿz2_check_ocsp_response_signature.<locals>.<listcomp>z0no matching responder certificate could be foundr   z?responder certificate is not signed by the certificate's issuerFz<responder is not authorized by issuer to sign OCSP responsesN)rx   rw   r%   r=   Zcertificatesrk   rl   rR   rS   r   ZExtendedKeyUsageÚoidZExtendedKeyUsageOIDZOCSP_SIGNINGrT   rU   rV   r   r   Zverify_signed_payloadZ
public_keyÚ	signatureZtbs_certificate_bytesZtbs_response_bytes)ro   rv   r5   Zresponder_certZresponder_certsrZ   Zdelegate_authorizedZchosen_hashr   ry   r   rs   Ü   s>    ÿÿ
 ÿ ÿrs   c           	         s¶   d}‡ fdd„|D ƒ}‡fdd„|D ƒ\}}}|r<|  d¡nd}d|ksT|rP|sT|rrt d	ˆ ¡ t d
ˆ|¡ dS |r~|s~dS |r |  d¡}|rœt d|¡ dS t dˆ|¡ dS dS )z7Parse openssl's weird output to work out what it means.)ÚgoodÚrevokedÚunknownc                    s   g | ]}d   ˆ |¡‘qS )z{0}: (WARNING.*)?{1})Úformat)rI   Ús)r5   r   r   rL     s     z)_translate_ocsp_query.<locals>.<listcomp>c                 3   s    | ]}t j|ˆ t jd �V  qdS ))ÚflagsN)ÚreÚsearchÚDOTALL)rI   Úp)Úocsp_outputr   r   Ú	<genexpr>  s     z(_translate_ocsp_query.<locals>.<genexpr>é   NzResponse verify OKz#Revocation status for %s is unknownzUncertain output:
%s
stderr:
%sFzOCSP revocation warning: %sTz2Unable to properly parse OCSP output: %s
stderr:%s)Úgroupr%   r&   r=   Úwarning)	r5   r†   Zocsp_errorsZstatesÚpatternsr|   r}   r~   rŠ   r   )r5   r†   r   rA     s(    
 ÿrA   )-rG   Úloggingr‚   r   r   Ú
subprocessr   r   Zcryptography.x509r   ÚgetattrZOCSPResponseÚImportErrorÚAttributeErrorZcryptographyr   Zcryptography.hazmat.backendsr	   Zcryptography.hazmat.primitivesr
   r   Zcryptography.exceptionsr   r   r.   ra   Zacme.magic_typingr   r   Zcertbotr   r   Zcertbot.storager   r   Ú	getLoggerrD   r%   Úobjectr   r2   r4   rh   rs   rA   r   r   r   r   Ú<module>   s8   

K1"1