3 fݭ@spdZddlZddlZddlZddlZddlZddlmZddlm Z m Z m ZddlZddlmZmZmZddlmZmZmZddlmZmZmZmZmZmZddlmZmZdd lm Z m!Z!m"Z"m#Z#ydd lm$Z$Wne%k rYnXdd lm&Z&m'Z'm(Z(m)Z)m*Z*dd lm+Z+dd lm,Z,e j-de.ddedej-de.ddede j-de.ddede j-de.ddedej-de.ddede j-de.ddede/j0Z1e/_1dde/j2j3DZ4e5e/ddZ6ej7dkrdd lm8Z8m9Z9dd!l:m:Z:m;Z;mZ>m?Z?ddl@Z@ddlAZAddlBZBeCZDejEr>d#gZFngZFe+ZGGd$d%d%eHZIdRd'd(ZJd)d*ZKd+d,ZLed-d.ZMd/d0ZNGd1d2d2ed2d3ZOGd4d5d5eOe ZPGd6d7d7eZQePjRfdddd8d9d:ZSe0feTd;ePjRdddddd<d=d>ZUeSZVeUZWGd?d@d@ZXGdAdBdBe:ZYddd;eTe0ddCdCdf dDdEZZdFdGZ[dHZ\dIZ]dJdKZ^dLdMZ_e0dfdNdOZ`dPdQZadS)Sa This module provides some more Pythonic support for SSL. Object types: SSLSocket -- subtype of socket.socket which does SSL over the socket Exceptions: SSLError -- exception raised for I/O errors Functions: cert_time_to_seconds -- convert time string used for certificate notBefore and notAfter functions to integer seconds past the Epoch (the time values returned from time.time()) fetch_server_certificate (HOST, PORT) -- fetch the certificate provided by the server running on HOST at port PORT. No validation of the certificate is performed. Integer constants: SSL_ERROR_ZERO_RETURN SSL_ERROR_WANT_READ SSL_ERROR_WANT_WRITE SSL_ERROR_WANT_X509_LOOKUP SSL_ERROR_SYSCALL SSL_ERROR_SSL SSL_ERROR_WANT_CONNECT SSL_ERROR_EOF SSL_ERROR_INVALID_ERROR_CODE The following group define certificate requirements that one side is allowing/requiring from the other side: CERT_NONE - no certificates from the other side are required (or will be looked at if provided) CERT_OPTIONAL - certificates are not required, but if provided will be validated, and if validation fails, the connection will also fail CERT_REQUIRED - certificates are required, and will be validated, and if validation fails, the connection will also fail The following constants identify various SSL protocol variants: PROTOCOL_SSLv2 PROTOCOL_SSLv3 PROTOCOL_SSLv23 PROTOCOL_TLS PROTOCOL_TLS_CLIENT PROTOCOL_TLS_SERVER PROTOCOL_TLSv1 PROTOCOL_TLSv1_1 PROTOCOL_TLSv1_2 The following constants identify various SSL alert message descriptions as per http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 ALERT_DESCRIPTION_CLOSE_NOTIFY ALERT_DESCRIPTION_UNEXPECTED_MESSAGE ALERT_DESCRIPTION_BAD_RECORD_MAC ALERT_DESCRIPTION_RECORD_OVERFLOW ALERT_DESCRIPTION_DECOMPRESSION_FAILURE ALERT_DESCRIPTION_HANDSHAKE_FAILURE ALERT_DESCRIPTION_BAD_CERTIFICATE ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE ALERT_DESCRIPTION_CERTIFICATE_REVOKED ALERT_DESCRIPTION_CERTIFICATE_EXPIRED ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN ALERT_DESCRIPTION_ILLEGAL_PARAMETER ALERT_DESCRIPTION_UNKNOWN_CA ALERT_DESCRIPTION_ACCESS_DENIED ALERT_DESCRIPTION_DECODE_ERROR ALERT_DESCRIPTION_DECRYPT_ERROR ALERT_DESCRIPTION_PROTOCOL_VERSION ALERT_DESCRIPTION_INSUFFICIENT_SECURITY ALERT_DESCRIPTION_INTERNAL_ERROR ALERT_DESCRIPTION_USER_CANCELLED ALERT_DESCRIPTION_NO_RENEGOTIATION ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE ALERT_DESCRIPTION_UNRECOGNIZED_NAME ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY N) namedtuple)EnumIntEnumIntFlag)OPENSSL_VERSION_NUMBEROPENSSL_VERSION_INFOOPENSSL_VERSION) _SSLContext MemoryBIO SSLSession)SSLErrorSSLZeroReturnErrorSSLWantReadErrorSSLWantWriteErrorSSLSyscallError SSLEOFError)txt2objnid2obj) RAND_statusRAND_add RAND_bytesRAND_pseudo_bytes)RAND_egd)HAS_SNIHAS_ECDHHAS_NPNHAS_ALPN HAS_TLSv1_3)_DEFAULT_CIPHERS)_OPENSSL_API_VERSION _SSLMethodcCs|jdo|dkS)NZ PROTOCOL_PROTOCOL_SSLv23) startswith)namer$/usr/lib64/python3.6/ssl.py}sr&)sourceOptionscCs |jdS)NZOP_)r")r#r$r$r%r&sZAlertDescriptioncCs |jdS)NZALERT_DESCRIPTION_)r")r#r$r$r%r&sZSSLErrorNumbercCs |jdS)NZ SSL_ERROR_)r")r#r$r$r%r&s VerifyFlagscCs |jdS)NZVERIFY_)r")r#r$r$r%r&s VerifyModecCs |jdS)NZCERT_)r")r#r$r$r%r&scCsi|]\}}||qSr$r$).0r#valuer$r$r% sr-ZPROTOCOL_SSLv2win32)enum_certificates enum_crls)socketAF_INET SOCK_STREAMcreate_connection) SOL_SOCKETSO_TYPEz tls-uniquec@s eZdZdS)CertificateErrorN)__name__ __module__ __qualname__r$r$r$r%r7sr7c Csg}|s dS|jd^}}|jd}||kr|jdsx|jdr|jtj|n|jtj|j ddx|D]}|jtj|qWtj d d j |d tj }|j |S) zhMatching according to RFC 6125, section 6.4.3 http://tools.ietf.org/html/rfc6125#section-6.4.3 F.*z,too many wildcards in certificate DNS name: z[^.]+zxn--z\*z[^.]*z\Az\.z\Z)splitcountr7reprlowerappendr"reescapereplacecompilejoin IGNORECASEmatch) ZdnhostnameZ max_wildcardsZpatsZleftmostZ remainderZ wildcardsZfragZpatr$r$r%_dnsname_matchs&   rKcCstj|j}||kS)zExact matching of IP addresses. RFC 6125 explicitly doesn't define an algorithm for this (section 1.7.2 - "Out of Scope"). ) ipaddress ip_addressrstrip)Zipnamehost_ipZipr$r$r%_ipaddress_matchsrPcCsP|s tdytj|}Wntk r2d}YnXg}|jdf}xb|D]Z\}}|dkr||dkrpt||rpdS|j|qJ|dkrJ|dk rt||rdS|j|qJW|sxF|jdfD]6}x0|D](\}}|dkrt||rdS|j|qWqWt|dkr td |d j t t |fn,t|dkrDtd ||d fntd dS)a)Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 rules are followed, but IP addresses are not accepted for *hostname*. CertificateError is raised on failure. On success, the function returns nothing. ztempty or no certificate, match_hostname needs a SSL socket or SSL context with either CERT_OPTIONAL or CERT_REQUIREDNZsubjectAltNameZDNSz IP AddressZsubjectZ commonNamer;z&hostname %r doesn't match either of %sz, zhostname %r doesn't match %rrz=no appropriate commonName or subjectAltName fields were found) ValueErrorrLrMgetrKrBrPlenr7rGmapr@)certrJrOZdnsnamesZsankeyr,subr$r$r%match_hostnames>    rXDefaultVerifyPathszQcafile capath openssl_cafile_env openssl_cafile openssl_capath_env openssl_capathcCsdtj}tjj|d|d}tjj|d|d}ttjj|rF|ndtjj|rX|ndf|S)z/Return paths to default cafile and capath. rr;N) _sslget_default_verify_pathsosenvironrRrYpathisfileisdir)partscafilecapathr$r$r%r]-s r]csDeZdZdZfZfddZefddZefddZZ S) _ASN1Objectz#ASN.1 object identifier lookup cstj|ft|ddS)NF)r#)super__new___txt2obj)clsoid) __class__r$r%rh@sz_ASN1Object.__new__cstj|ft|S)z3Create _ASN1Object from OpenSSL numeric ID )rgrh_nid2obj)rjZnid)rlr$r%fromnidCsz_ASN1Object.fromnidcstj|ft|ddS)z=Create _ASN1Object from short name, long name or OID T)r#)rgrhri)rjr#)rlr$r%fromnameIsz_ASN1Object.fromname) r8r9r:__doc__ __slots__rh classmethodrnro __classcell__r$r$)rlr%rf;s  rfznid shortname longname oidc@seZdZdZdZdZdS)PurposezDSSLContext purpose flags with X509v3 Extended Key Usage objects z1.3.6.1.5.5.7.3.1z1.3.6.1.5.5.7.3.2N)r8r9r:rp SERVER_AUTHZ CLIENT_AUTHr$r$r$r%rtPsrtcseZdZdZd"Zd#ZefddZefdd Zd$d dZ d%ddZ ddZ ddZ ddZ ejfddZefddZejfddZefddZejfddZefdd Zejfd!d ZZS)& SSLContextz|An SSLContext holds various SSL-related configuration options and data, such as certificates and possibly a private key.protocol __weakref__CAROOTcOstj||}|S)N)r rh)rjrwargskwargsselfr$r$r%rh^s zSSLContext.__new__cCs ||_dS)N)rw)r}rwr$r$r%__init__bszSSLContext.__init__FTNc Cst|||||||dS)N)sock server_sidedo_handshake_on_connectsuppress_ragged_eofsserver_hostname_context_session) SSLSocket)r}rrrrrsessionr$r$r% wrap_socketes zSSLContext.wrap_socketcCs|j||||d}t||dS)N)rr)r)Z _wrap_bio SSLObject)r}ZincomingZoutgoingrrrsslobjr$r$r%wrap_bioos zSSLContext.wrap_biocCsdt}xN|D]F}t|d}t|dks2t|dkr:td|jt||j|q W|j|dS)Nasciirz(NPN protocols must be 1 to 255 in length) bytearraybytesrSr rBextendZ_set_npn_protocols)r} npn_protocolsprotosrwbr$r$r%set_npn_protocolsus  zSSLContext.set_npn_protocolscCsdt}xN|D]F}t|d}t|dks2t|dkr:td|jt||j|q W|j|dS)Nrrrz)ALPN protocols must be 1 to 255 in length)rrrSr rBrZ_set_alpn_protocols)r}Zalpn_protocolsrrwrr$r$r%set_alpn_protocolss  zSSLContext.set_alpn_protocolsc Cszt}y@x:t|D].\}}}|dkr|dks6|j|kr|j|qWWntk rdtjdYnX|rv|j|d|S)NZx509_asnTz-unable to enumerate Windows certificate store)cadata)rr/rkrPermissionErrorwarningswarnload_verify_locations)r} storenamepurposeZcertsrUencodingZtrustr$r$r%_load_windows_store_certss z$SSLContext._load_windows_store_certscCsDt|tst|tjdkr8x|jD]}|j||q$W|jdS)Nr.) isinstancerf TypeErrorsysplatform_windows_cert_storesrZset_default_verify_paths)r}rrr$r$r%load_default_certss    zSSLContext.load_default_certscs ttjS)N)r(rgoptions)r})rlr$r%rszSSLContext.optionscstttjj||dS)N)rgrvr__set__)r}r,)rlr$r%rscs ttjS)N)r)rg verify_flags)r})rlr$r%rszSSLContext.verify_flagscstttjj||dS)N)rgrvrr)r}r,)rlr$r%rsc s*tj}yt|Stk r$|SXdS)N)rg verify_moder*rQ)r}r,)rlr$r%rs zSSLContext.verify_modecstttjj||dS)N)rgrvrr)r}r,)rlr$r%rs)rwrx)ryrz)FTTNN)FNN)r8r9r:rprqr PROTOCOL_TLSrhr~rrrrrrtrurpropertyrsetterrrrsr$r$)rlr%rvWs*      rv)rdrercCsdt|tst|tt}|tjkr0t|_d|_ |s<|s<|rL|j |||n|jt kr`|j ||S)zCreate a SSLContext object with default settings. NOTE: The protocol and settings may change anytime without prior deprecation. The values represent a fair balance between maximum compatibility and security. T) rrfrrvrrtru CERT_REQUIREDrcheck_hostnamer CERT_NONEr)rrdrercontextr$r$r%create_default_contexts     rF) cert_reqsrrcertfilekeyfilerdrerc Cst|tst|t|} |s$d| _|dk r2|| _|rZ$d?d@Z%dAdBZ&dCdDZ'dEdFZ(dadGdHZ)dIdJZ*dKdLZ+dMdNZ,dOdPZ-dbdRdSZ.dTdUZ/Z0S)crzThis class implements a subtype of socket.socket that wraps the underlying OS socket in an SSL context when necessary, and provides read and write methods over that channel.NFTrc6Cs:d|_|r||_n|r$| r$td|r6| r6td|rD| rD|}t||_||j_|rf|jj||rx|jj|||r|jj||r|jj|||_ ||_ ||_ ||_ ||_ ||_|jtttkrtd|r|rtd|dk rtd|jjr| rtd||_||_||_||_| |_|dk rftj||j|j|j|jd|j }|j!n,| dk rtj|| dntj|| | | d y |j"Wnt#k r}z|j$t$j%kr‚d }|j d k}|j&d y|j'd }Wn>t#k r(}z |j$t$j%t$j(fkrd }WYdd}~XnX|j&||rd}t)|j$|}||_*d|_+y |j,Wnt#k rxYnXz|Wdd}XWYdd}~XnXd}|j-|d |_.d|_||_/|r6yN|jj0|||}t1|||jd|_|r|j }|dkrtd|j2Wn$t#tfk r4|j,YnXdS)Nz5certfile must be specified for server-side operationszcertfile must be specifiedz!only stream sockets are supportedz4server_hostname can only be specified in client modez,session can only be specified in client modez'check_hostname requires server_hostname)familytypeprotofileno)r)rrrFrr;z5Closed before TLS handshake with data in recv buffer.T)rrgzHdo_handshake_on_connect should not be specified for non-blocking sockets)3rrrQrvrrrrZ set_ciphersrrr ssl_versionca_certsciphersZ getsockoptr5r6r3rrrrrrrr1r~rrrr gettimeoutdetach getpeernameOSErrorerrnoZENOTCONNZ setblockingrecvZEINVALr reasonZlibraryclose settimeoutZ_closed _connected _wrap_socketrr)r}rrrrrrrrrrrrrrrrrrZ sock_timeouteZ connectedZblockingZnotconn_pre_handshake_datarZ notconn_pre_handshake_data_errorrtimeoutr$r$r%r~s                      zSSLSocket.__init__cCs|jS)N)r)r}r$r$r%r0szSSLSocket.contextcCs||_||j_dS)N)rrr)r}rr$r$r%r4scCs|jdk r|jjSdS)z!The SSLSession for client socket.N)rr)r}r$r$r%r9s zSSLSocket.sessioncCs||_|jdk r||j_dS)N)rrr)r}rr$r$r%r?s cCs|jdk r|jjSdS)z.Was the client session reused during handshakeN)rr)r}r$r$r%rEs zSSLSocket.session_reusedcCstd|jjdS)NzCan't dup() %s instances)rrlr8)r}r$r$r%dupKsz SSLSocket.dupcCsdS)Nr$)r}msgr$r$r% _checkClosedOszSSLSocket._checkClosedcCs|js|jdS)N)rr)r}r$r$r%_check_connectedSszSSLSocket._check_connectedcCst|j|jstdy|jj||Stk rn}z.|jdtkr\|jr\|dk rVdSdSnWYdd}~XnXdS)zORead up to LEN bytes and return them. Return zero-length string on EOF.z'Read on closed or unwrapped SSL socket.rNr)rrrQrr r{Z SSL_ERROR_EOFr)r}rSrxr$r$r%r[szSSLSocket.readcCs"|j|jstd|jj|S)zhWrite DATA to the underlying SSL channel. Returns number of bytes of DATA actually transmitted.z(Write on closed or unwrapped SSL socket.)rrrQr)r}rr$r$r%rmszSSLSocket.writecCs|j|j|jj|S)zReturns a formatted version of the data in the certificate provided by the other end of the SSL channel. Return None if no certificate was provided, {} if a certificate was provided, but not validated.)rrrr)r}rr$r$r%rvszSSLSocket.getpeercertcCs*|j|j stj rdS|jjSdS)N)rrr\rr)r}r$r$r%rszSSLSocket.selected_npn_protocolcCs*|j|j stj rdS|jjSdS)N)rrr\rr)r}r$r$r%rsz SSLSocket.selected_alpn_protocolcCs |j|jsdS|jjSdS)N)rrr)r}r$r$r%rszSSLSocket.ciphercCs|j|jsdS|jjS)N)rrr)r}r$r$r%rszSSLSocket.shared_cipherscCs |j|jsdS|jjSdS)N)rrr)r}r$r$r%rszSSLSocket.compressioncCsB|j|jr0|dkr$td|j|jj|Stj|||SdS)Nrz3non-zero flags not allowed in calls to send() on %s)rrrQrlrr1send)r}rflagsr$r$r%rs  zSSLSocket.sendcCsH|j|jrtd|jn&|dkr4tj|||Stj||||SdS)Nz%sendto not allowed on instances of %s)rrrQrlr1sendto)r}rZ flags_or_addraddrr$r$r%rs zSSLSocket.sendtocOstd|jdS)Nz&sendmsg not allowed on instances of %s)rrl)r}r{r|r$r$r%sendmsgszSSLSocket.sendmsgcCs|j|jr|dkr$td|jd}t|L}|jd6}t|}x&||krl|j||d}||7}qHWWdQRXWdQRXntj |||SdS)Nrz6non-zero flags not allowed in calls to sendall() on %sB) rrrQrl memoryviewcastrSrr1sendall)r}rrr?ZviewZ byte_viewZamountrr$r$r%rs  "zSSLSocket.sendallcs,|jdkrtj|||S|j|||SdS)zSend a file, possibly by using os.sendfile() if this is a clear-text socket. Return the total number of bytes sent. N)rrgsendfileZ_sendfile_use_send)r}fileoffsetr?)rlr$r%rs zSSLSocket.sendfilecCs@|j|jr.|dkr$td|j|j|Stj|||SdS)Nrz3non-zero flags not allowed in calls to recv() on %s)rrrQrlrr1r)r}buflenrr$r$r%rs  zSSLSocket.recvcCsf|j|r|dkrt|}n |dkr*d}|jrR|dkrFtd|j|j||Stj||||SdS)Nirz8non-zero flags not allowed in calls to recv_into() on %s)rrSrrQrlrr1 recv_into)r}rnbytesrr$r$r%rs    zSSLSocket.recv_intocCs0|j|jrtd|jntj|||SdS)Nz'recvfrom not allowed on instances of %s)rrrQrlr1recvfrom)r}rrr$r$r%rs  zSSLSocket.recvfromcCs2|j|jrtd|jntj||||SdS)Nz,recvfrom_into not allowed on instances of %s)rrrQrlr1 recvfrom_into)r}rrrr$r$r%rs  zSSLSocket.recvfrom_intocOstd|jdS)Nz&recvmsg not allowed on instances of %s)rrl)r}r{r|r$r$r%recvmsgszSSLSocket.recvmsgcOstd|jdS)Nz+recvmsg_into not allowed on instances of %s)rrl)r}r{r|r$r$r% recvmsg_intoszSSLSocket.recvmsg_intocCs |j|jr|jjSdSdS)Nr)rrr)r}r$r$r%r s zSSLSocket.pendingcCs|jd|_tj||dS)N)rrr1r)r}Zhowr$r$r%rszSSLSocket.shutdowncCs.|jr|jj}d|_|Stdt|dS)NzNo SSL wrapper around )rrrQstr)r}sr$r$r%rs  zSSLSocket.unwrapcCs$|jr|jjStdt|dS)NzNo SSL wrapper around )rrrQr)r}r$r$r%rs z&SSLSocket.verify_client_post_handshakecCsd|_tj|dS)N)rr1 _real_close)r}r$r$r%r#szSSLSocket._real_closec CsF|j|j}z$|dkr(|r(|jd|jjWd|j|XdS)zPerform a TLS/SSL handshake.gN)rrrrr)r}blockrr$r$r%r's  zSSLSocket.do_handshakec Cs|jrtd|jrtd|jj|d|j}t|||jd|_y>|rTt j ||}nd}t j |||s|d|_|j r||j |Sttfk rd|_YnXdS)Nz!can't connect in server-side modez/attempt to connect already-connected SSLSocket!F)rrT)rrQrrrrrrrr1 connect_exconnectrrr)r}rrrZrcr$r$r% _real_connect2s(  zSSLSocket._real_connectcCs|j|ddS)zQConnects to remote ADDR, and then wraps the connection in an SSL channel.FN)r)r}rr$r$r%rKszSSLSocket.connectcCs |j|dS)zQConnects to remote ADDR, and then wraps the connection in an SSL channel.T)r)r}rr$r$r%rPszSSLSocket.connect_excCs.tj|\}}|jj||j|jdd}||fS)zAccepts a new connection from a remote client, and returns a tuple containing that new connection wrapped with a server-side SSL channel, and the address of the remote client.T)rrr)r1acceptrrrr)r}Znewsockrr$r$r%rUs zSSLSocket.accept tls-uniquecCs|jdkrdS|jj|S)zGet channel binding data for current connection. Raise ValueError if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake). N)rr)r}rr$r$r%ras zSSLSocket.get_channel_bindingcCs|jdkrdS|jjS)z Return a string identifying the protocol version used by the current SSL channel, or None if there is no established channel. N)rr)r}r$r$r%rjs zSSLSocket.version)N)rN)F)r)N)r)rN)rr)Nr)rr)Nr)F)r )1r8r9r:rprrr2r3r~rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrsr$r$)rlr%rs`|             rTc Cst|||||||||| d S)N) rrrrrrrrrr)r) rrrrrrrrrrr$r$r%rts rc Csddlm}ddlm}d}d}y|j|ddjd}Wn$tk rbtd||fYn0X||dd|}||d|f|ddSdS)aReturn the time in seconds since the Epoch, given the timestring representing the "notBefore" or "notAfter" date from a certificate in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C locale). "notBefore" or "notAfter" dates must use UTC (RFC 5280). Month is one of: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec UTC should be specified as GMT (see ASN1_TIME_print()) r)strptime)timegmJanFebMarAprMayJunJulAugSepOctNovDecz %d %H:%M:%S %Y GMTNr[r;z*time data %r does not match format "%%b%s"rZ) r r rrrrrrrrrr)Ztimer Zcalendarr indextitlerQ)Z cert_timer r ZmonthsZ time_formatZ month_numberZttr$r$r%cert_time_to_secondss  rz-----BEGIN CERTIFICATE-----z-----END CERTIFICATE-----cCs2ttj|dd}tdtj|ddtdS)z[Takes a certificate in binary DER format and returns the PEM version of it as a string.ASCIIstrict @)rbase64Zstandard_b64encode PEM_HEADERtextwrapZfill PEM_FOOTER)Zder_cert_bytesfr$r$r%DER_cert_to_PEM_certsr%cCs\|jtstdt|jjts0tdt|jtttt }tj|j ddS)zhTakes a certificate in ASCII PEM format and returns the DER-encoded version of it as a byte sequencez(Invalid PEM encoding; must start with %sz&Invalid PEM encoding; must end with %srr) r"r!rQstripendswithr#rSr Z decodebytesencode)Zpem_cert_stringdr$r$r%PEM_cert_to_DER_certs r*c Csd|\}}|dk rt}nt}t|||d}t|&}|j|}|jd} WdQRXWdQRXt| S)zRetrieve the certificate from the server at the specified address, and return it as a PEM-encoded string. If 'ca_certs' is specified, validate the server cert against it. If 'ssl_version' is specified, use it in the connection attempt.N)rrdT)rr_create_stdlib_contextr4rrr%) rrrhostZportrrrZsslsockZdercertr$r$r%get_server_certificates  r-cCs tj|dS)Nz )_PROTOCOL_NAMESrR)Z protocol_coder$r$r%get_protocol_namesr/)r;)brprLr"rCrr^ collectionsrenumrZ_EnumrZ_IntEnumrZ_IntFlagr\rrrr r r r r rrrrrrirrmrrrrr ImportErrorrrrrrrr_convertr8r rr! __members__itemsr.getattrZ_SSLv2_IF_EXISTSrr/r0r1r2r3r4r5r6r rrrZ socket_errorZHAS_TLS_UNIQUErZ_RESTRICTED_SERVER_CIPHERSrQr7rKrPrXrYr]rfrtrvrurrrZ_create_default_https_contextr+rrrrr!r#r%r*r-r/r$r$r$r%[s        1 4g(O