a ‚oeÌ:ã@sŒdZddlmZddlmZddlZddlZddlZddlmZddlmZddlm Z ddl m Z dd l m Z dd l mZdd lmZdd lmZdd lmZddlmZddlZddlZddlmZddlmZddlmZddlmZddlmZe  e!¡Z"Gdd„dƒZ#e$e ee$ee$fdœdd„Z%e$e$e$e&e'dœdd„Z(dde j)e$ddœdd „Z*de j)e$dd!œd"d#„Z+e$e$e$e'd$œd%d&„Z,dS)'z*Tools for checking certificate revocation.é)Údatetime)Ú timedeltaN)ÚPIPE)ÚOptional)ÚTuple)Úx509)ÚInvalidSignature)ÚUnsupportedAlgorithm)Údefault_backend)Úhashes)Ú serialization)Úocsp)Ú crypto_util)Úerrors)Úutil)Úgetenv)Ú RenewableCertc@s`eZdZdZdeddœdd„Zeedœdd „Zdeee ed œd d „Z eeeee edœdd„Z dS)ÚRevocationCheckerzEThis class figures out OCSP checking on this system, and performs it.FN)Úenforce_openssl_binary_usageÚreturncCsrd|_||_|jrnt d¡s0t d¡d|_dStjgd¢ttddt  ¡d�}d|j vrddd „|_ n d d „|_ dS) NFÚopensslz-openssl not installed, can't check revocationT)rr ú-headerÚvarÚval)ÚstdoutÚstderrZuniversal_newlinesÚcheckÚenvz Missing =cSs d|gS)NzHost=©©Úhostrrú-C:\Program Files\Certbot\pkgs\certbot\ocsp.pyÚ0óz,RevocationChecker.__init__..cSsd|gS)NZHostrrrrr!r"2r#) ÚbrokenÚuse_openssl_binaryrZ exe_existsÚloggerÚinfoÚ subprocessÚrunrZenv_no_snap_for_external_callsrÚ host_args)ÚselfrZtest_host_formatrrr!Ú__init__!s   þ  zRevocationChecker.__init__©ÚcertrcCs| |j|j¡S)a Get revoked status for a particular cert version. .. todo:: Make this a non-blocking call :param `.interfaces.RenewableCert` cert: Certificate object :returns: True if revoked; False if valid or the check failed or cert is expired. :rtype: bool )Úocsp_revoked_by_pathsÚ cert_pathÚ chain_path)r+r.rrr!Ú ocsp_revoked4s zRevocationChecker.ocsp_revokedé )r0r1ÚtimeoutrcCsf|jr dSt tj¡}t |¡|kr(dSt|ƒ\}}|r<|s@dS|jrX|  |||||¡St ||||ƒS)aEPerforms the OCSP revocation check :param str cert_path: Certificate filepath :param str chain_path: Certificate chain :param int timeout: Timeout (in seconds) for the OCSP query :returns: True if revoked; False if valid or the check failed or cert is expired. :rtype: bool F) r$rÚnowÚpytzÚUTCrZnotAfterÚ_determine_ocsp_serverr%Ú_check_ocsp_openssl_binÚ_check_ocsp_cryptography)r+r0r1r4r5Úurlr rrr!r/@s   z'RevocationChecker.ocsp_revoked_by_paths)r0r1r r;r4rc Cstdƒ}tdƒ}d}|dus$|dur4|dur0|n|}|durFd|g} n&| d¡r`|tdƒd…}d|d|g} ddd d |d |d |d |ddt|ƒdg| |¡| } t d|¡t d | ¡¡ztj | tjd�\} } Wn"t j yöt  d|¡YdS0t || | ƒS)NZ http_proxyZ HTTP_PROXYz-urlzhttp://z-hostz-pathrr z -no_noncez-issuerz-certz-CAfilez -verify_otherz -trust_otherz-timeoutrzQuerying OCSP for %sú )Úlogú*OCSP check failed for %s (are we offline?)F)rÚ startswithÚlenÚstrr*r&ÚdebugÚjoinrZ run_scriptrZSubprocessErrorr'Ú_translate_ocsp_query) r+r0r1r r;r4Zenv_http_proxyZenv_HTTP_PROXYZ proxy_hostZurl_optsÚcmdÚoutputÚerrrrr!r9]s@   øøø  z)RevocationChecker._check_ocsp_openssl_bin)F)r3) Ú__name__Ú __module__Ú __qualname__Ú__doc__Úboolr,rr2rAÚintr/r9rrrr!rs ÿr)r0rc sØt|dƒ�"}t | ¡tƒ¡}Wdƒn1s20Yz:|j tj¡}tjj ‰‡fdd„|j Dƒ}|dj j }Wn&tj t fyœt d|¡YdS0| ¡}| d¡d  d ¡}|rÆ||fSt d ||¡dS) 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) ÚrbNcsg|]}|jˆkr|‘qSr)Z access_method)Ú.0Ú description©Zocsp_oidrr!Ú �s ÿz*_determine_ocsp_server..rzCannot extract OCSP URI from %s)NNz://éú/z;Cannot process OCSP host from URL (%s) in certificate at %s)ÚopenrÚload_pem_x509_certificateÚreadr Ú extensionsÚget_extension_for_classZAuthorityInformationAccessZAuthorityInformationAccessOIDZOCSPÚvalueZaccess_locationÚExtensionNotFoundÚ IndexErrorr&r'ÚrstripÚ partition)r0Ú file_handlerr.Ú extensionZ descriptionsr;r rrQr!r8ƒs  0 r8)r0r1r;r4rc Cs.t|dƒ�"}t | ¡tƒ¡}Wdƒn1s20Yt|dƒ�"}t | ¡tƒ¡}Wdƒn1sn0Yt ¡}| ||t  ¡¡}|  ¡}|  t j j¡} ztj|| ddi|d�} Wn(tjjyêtjd|dd�YdS0| jd k�r t d || j¡dSt | j¡} | jtjjk�rT)Ú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)'rUrrVrWr r ZOCSPRequestBuilderZadd_certificater ZSHA1ÚbuildZ public_bytesr ZEncodingZDERÚrequestsZpostÚ exceptionsZRequestExceptionr&r'Z status_codeZload_der_ocsp_responseZcontentZresponse_statusZOCSPResponseStatusZ SUCCESSFULÚwarningÚ_check_ocsp_responser rArÚErrorrÚAssertionErrorrBZcertificate_statusZOCSPCertStatusZREVOKED)r0r1r;r4r_Úissuerr.ZbuilderZrequestZrequest_binaryZresponseÚ response_ocspÚeÚerrorrrr!r:¡sP 0 0þ   ÿ""(ÿr:zocsp.OCSPResponsezocsp.OCSPRequest)rlÚ request_ocspÚ issuer_certr0rcCs¶|j|jkrtdƒ‚t|||ƒt|jt|jƒƒrJ|j|jksJ|j|jkrRtdƒ‚t  t j ¡j dd�}|j sttdƒ‚|j |tdd�kr�tdƒ‚|jr²|j|tdd�kr²td ƒ‚dS) z2Verify that the OCSP is valid for several criteriazMthe certificate in response does not correspond to the certificate in requestzt d|¡|}n¼t d|¡‡‡fdd„ˆjDƒ}|slt dƒ‚|d }|j |jkrˆt d ƒ‚z"|j   tj ¡}tjjj|jv}WntjtfyÆd }Yn0|sÔt d ƒ‚|j}|sâJ‚t | ¡|j|j|¡ˆj}|�st d ƒ‚t | ¡ˆjˆj|¡dS)zIVerify an OCSP response signature against certificate issuer or responderr-cSstj | ¡¡jS)N)rZSubjectKeyIdentifierZfrom_public_keyÚ public_keyZdigest)r.rrr!Ú _key_hashùsz1_check_ocsp_response_signature.._key_hashzGOCSP response for certificate %s is signed by the certificate's issuer.zGOCSP response for certificate %s is delegated to an external responder.cs*g|]"}ˆj|jks"ˆjˆ|ƒkr|‘qSr)Úresponder_nameÚsubjectÚresponder_key_hash)rOr.©rwrlrr!rRs þz2_check_ocsp_response_signature..z0no matching responder certificate could be foundrz?responder certificate is not signed by the certificate's issuerFz.c3s |]}tj|ˆtjd�VqdS))ÚflagsN)ÚreÚsearchÚDOTALL)rOÚp)r~rr!Ú 5r#z(_translate_ocsp_query..éNzResponse verify OKz#Revocation status for %s is unknownzUncertain output: %s stderr: %sFzOCSP revocation warning: %sTz2Unable to properly parse OCSP output: %s stderr:%s)Úgroupr&r'rBrg) r0r~rZstatesÚpatternsr€r�r‚rgr)r0r~r!rD0s&   ÿrD)-rKrrZloggingr†r(rÚtypingrrZ cryptographyrZcryptography.exceptionsrr Zcryptography.hazmat.backendsr Zcryptography.hazmat.primitivesr r Zcryptography.x509r r6reZcertbotrrrZcertbot.compat.osrZcertbot.interfacesrZ getLoggerrHr&rrAr8rMrLr:r|rhrrrDrrrr!ÚsB                  e 1ÿ $ÿ :