a }|ge<@sdZddlmZddlmZddlZddlZddlZddlmZddlmZddlm Z ddl Z ddl m Z dd l mZdd l mZdd lmZdd lmZdd lmZddlmZddlZddlZddlmZddlmZddlmZddlmZddlm Z e!e"Z#GdddZ$e%e ee%ee%fdddZ&e%e%e%e'e(dddZ)dde j*e%dddd 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`eZdZdZdeddddZeeddd Zdeee ed d d Z eeeee edddZ dS)RevocationCheckerzEThis class figures out OCSP checking on this system, and performs it.FN)enforce_openssl_binary_usagereturncCsrd|_||_|jrntds0tdd|_dStjgdttddt d}d|j vrddd |_ n d d |_ dS) NFopensslz-openssl not installed, can't check revocationT)rr -headervarval)stdoutstderrZuniversal_newlinescheckenvz Missing =cSs d|gS)NzHost=hostrr0/usr/lib/python3.9/site-packages/certbot/ocsp.py1z,RevocationChecker.__init__..cSsd|gS)NZHostrrrrr!r"3r#) brokenuse_openssl_binaryrZ exe_existsloggerinfo subprocessrunrZenv_no_snap_for_external_callsr host_args)selfrZtest_host_formatrrr!__init__"s     zRevocationChecker.__init__certrcCs||j|jS)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_revoked5s zRevocationChecker.ocsp_revoked )r0r1timeoutrcCsf|jr dSttj}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$rnowpytzUTCrZnotAfter_determine_ocsp_serverr%_check_ocsp_openssl_bin_check_ocsp_cryptography)r+r0r1r4r5urlr rrr!r/As   z'RevocationChecker.ocsp_revoked_by_paths)r0r1r r;r4rc Cstd}td}d}|dus$|dur4|dur0|n|}|durFd|g} n&|dr`|tdd}d|d|g} ddd d |d |d |d |ddt|dg||| } td|td| ztj | tjd\} } Wn"t j yt 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 startswithlenstrr*r&debugjoinrZ run_scriptrZSubprocessErrorr'_translate_ocsp_query) r+r0r1r r;r4Zenv_http_proxyZenv_HTTP_PROXYZ proxy_hostZurl_optscmdoutputerrrrr!r9^s@     z)RevocationChecker._check_ocsp_openssl_bin)F)r3) __name__ __module__ __qualname____doc__boolr,rr2rAintr/r9rrrr!rs r)r0rc st|d"}t|t}Wdn1s20Yz:|jtj}tjj fdd|j D}|dj j }Wn&tj t fytd|YdS0|}|dd d }|r||fStd ||dS) zExtract 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|]}|jkr|qSr)Z access_method).0 descriptionZocsp_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)openrload_pem_x509_certificatereadr extensionsget_extension_for_classZAuthorityInformationAccessZAuthorityInformationAccessOIDZOCSPvalueZaccess_locationExtensionNotFound IndexErrorr&r'rstrip partition)r0 file_handlerr. extensionZ descriptionsr;r rrQr!r8s  0 r8)r0r1r;r4rc Cs.t|d"}t|t}Wdn1s20Yt|d"}t|t}Wdn1sn0Yt}|||t }| }| t j j} ztj|| ddi|d} Wn(tjjytjd|ddYdS0| jd kr td || jdSt| j} | jtjjkrT)exc_infoFz*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 ZSHA1ZbuildZ public_bytesr ZEncodingZDERrequestsZpost exceptionsZRequestExceptionr&r'Z status_codeZload_der_ocsp_responseZcontentZresponse_statusZOCSPResponseStatusZ SUCCESSFULwarning_check_ocsp_responser rArErrorrAssertionErrorrBZcertificate_statusZOCSPCertStatusZREVOKED)r0r1r;r4r_issuerr.ZbuilderZrequestZrequest_binaryZresponse response_ocspeerrorrrr!r:sP 0 0   ""(r:zocsp.OCSPResponsezocsp.OCSPRequest)rk request_ocsp issuer_certr0rcCs|j|jkrtdt|||t|jt|jrJ|j|jksJ|j|jkrRtdt t j j dd}t jt jddd|jstd|j|td d krtd |jr|j|td d krtd Wdn1s0YdS) z2Verify that the OCSP is valid for several criteriazMthe certificate in response does not correspond to the certificate in requestztd||}ntd|fddjD}|slt d|d }|j |jkrt d z"|j tj }tjjj|jv}Wntjtfyd }Yn0|st d |j}t||j|j|j}|st d t|jj|dS)zIVerify an OCSP response signature against certificate issuer or responderr-cSstj|jS)N)rZSubjectKeyIdentifierZfrom_public_key public_keyZdigest)r.rrr! _key_hashsz1_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_namesubjectresponder_key_hash)rOr.r{rkrr!rR s z2_check_ocsp_response_signature..z0no matching responder certificate could be foundrz?responder certificate is not signed by the certificate's issuerFz.c3s |]}tj|tjdVqdS))flagsN)researchDOTALL)rOp)rrr! ;r#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'rBrf) r0rrZstatespatternsrrrrfr)r0rr!rD6s&   rD).rKrrZloggingrr(rtypingrrrwZ cryptographyrZcryptography.exceptionsrr Zcryptography.hazmat.backendsr Zcryptography.hazmat.primitivesr r Zcryptography.x509r r6rdZcertbotrrrZcertbot.compat.osrZcertbot.interfacesrZ getLoggerrHr&rrAr8rMrLr:rrgrsrDrrrr!sD                  e 1 ) :