a `: @spdZddlmZddlmZddlZddlZddlmZddlmZddlm Z ddl m Z dd l m Z dd l mZdd lmZdd lmZddlZddlZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZzddlm Z e!e j"dWne#e$fy(dZ Yn0e%e&Z'Gddde(Z)ddZ*ddZ+ddZ,ddZ-d d!Z.dS)"z*Tools for checking certificate revocation.)datetime) timedeltaN)PIPE)Popen)x509)InvalidSignature)UnsupportedAlgorithm)default_backend)hashes) serialization)Optional)Tuple) crypto_util)errors)util)getenv) RenewableCert)ocspsignature_hash_algorithmc@s4eZdZdZd ddZddZddd Zd d Zd S)RevocationCheckerzEThis class figures out OCSP checking on this system, and performs it.FcCs~d|_|pt |_|jrztds6tdd|_dStgdttdt d}| \}}d|vrpdd |_ n d d |_ dS) NFopensslz-openssl not installed, can't check revocationT)rr-headervarval)stdoutstderrZuniversal_newlinesenvz Missing =cSs d|gS)NzHost=hostrr./usr/lib/python3/dist-packages/certbot/ocsp.py:z,RevocationChecker.__init__..cSsd|gS)NZHostrrrrr r!<r") brokenruse_openssl_binaryrZ exe_existsloggerinforrZenv_no_snap_for_external_callsZ communicate host_args)selfZenforce_openssl_binary_usageZtest_host_formatZ_outerrrrr __init__*s     zRevocationChecker.__init__cCs||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(certrrr ocsp_revoked>s zRevocationChecker.ocsp_revoked cCsj|jr dStjt}t||kr,dSt|\}}|r@|sDdS|j r\| |||||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#pytzZUTCZfromutcrutcnowrZnotAfter_determine_ocsp_serverr$_check_ocsp_openssl_bin_check_ocsp_cryptography)r(r,r-timeoutnowurlrrrr r+Ks  z'RevocationChecker.ocsp_revoked_by_pathsc 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-pathrrz -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(r,r-rr8r6Zenv_http_proxyZenv_HTTP_PROXYZ proxy_hostZurl_optscmdoutputr)rrr r4is@     z)RevocationChecker._check_ocsp_openssl_binN)F)r0)__name__ __module__ __qualname____doc__r*r/r+r4rrrr r's   rc 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).0Z 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)r, file_handlerr. extensionZ descriptionsr8rrrJr r3s 0 r3c 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} | jtjjkrrErrorrAssertionErrorr?Zcertificate_statusZOCSPCertStatusZREVOKED)r,r-r8r6rXissuerr.ZbuilderZrequestZrequest_binaryZresponse response_ocsper_rrr r5sP 0 0   ""(r5cCs|j|jkrtdt|||t|jt|jrJ|j|jksJ|j|jkrRtdt }|j shtd|j |t ddkrtd|j r|j |t ddkrtddS) z2Verify that the OCSP is valid for several criteriazMthe certificate in response does not correspond to the certificate in requestz._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)rIr.rlrdrr rKs 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)rIp) ocsp_outputrr =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&r?warning) r,r{Z ocsp_errorsZstatesZpatternsrqrrrsrr)r,r{r rA8s&   rA)/rGrrZloggingrw subprocessrrZ cryptographyrZcryptography.exceptionsrrZcryptography.hazmat.backendsr Zcryptography.hazmat.primitivesr r r1r]Zacme.magic_typingr r ZcertbotrrrZcertbot.compat.osrZcertbot.interfacesrZcryptography.x509rgetattrZ OCSPResponse ImportErrorAttributeErrorZ getLoggerrDr%objectrr3r5r`rgrArrrr sB                    h2"6