Question

I'm issuing a HTTPS GET request to a REST service I own with httplib2 but we're getting the error:

[Errno 8] _ssl.c:504: EOF occurred in violation of protocol

All other clients works well (browser, Java client, etc...) with the minor exception that PHP curl needed to be set to use SSL v3.

I've searched around and it seems that it is indeed an error regarding SSL version, but I can't seem to find a way to change it in httplib2. Is there any way around it besides changing the following line in the source code:

# We should be specifying SSL version 3 or TLS v1, but the ssl module
# doesn't expose the necessary knobs. So we need to go with the default
# of SSLv23.
return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
                       cert_reqs=cert_reqs, ca_certs=ca_certs)
Was it helpful?

Solution

I developed this workaround for httplib2 :

import httplib2

# Start of the workaround for SSL3
# This is a monkey patch / module function overriding 
# to allow pages that only work with SSL3

# Build the appropriate socket wrapper for ssl
try:
    import ssl # python 2.6
    httplib2.ssl_SSLError = ssl.SSLError
    def _ssl_wrap_socket(sock, key_file, cert_file,
                         disable_validation, ca_certs):
        if disable_validation:
            cert_reqs = ssl.CERT_NONE
        else:
            cert_reqs = ssl.CERT_REQUIRED
        # Our fix for sites the only accepts SSL3
        try:
            # Trying SSLv3 first
            tempsock = ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
                                       cert_reqs=cert_reqs, ca_certs=ca_certs,
                                       ssl_version=ssl.PROTOCOL_SSLv3)
        except ssl.SSLError, e:
            tempsock = ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file,
                                       cert_reqs=cert_reqs, ca_certs=ca_certs,
                                       ssl_version=ssl.PROTOCOL_SSLv23)
        return tempsock
    httplib2._ssl_wrap_socket = _ssl_wrap_socket
except (AttributeError, ImportError):
    httplib2.ssl_SSLError = None
    def _ssl_wrap_socket(sock, key_file, cert_file,
                         disable_validation, ca_certs):
        if not disable_validation:
            raise httplib2.CertificateValidationUnsupported(
                    "SSL certificate validation is not supported without "
                    "the ssl module installed. To avoid this error, install "
                    "the ssl module, or explicity disable validation.")
        ssl_sock = socket.ssl(sock, key_file, cert_file)
        return httplib.FakeSocket(sock, ssl_sock)
    httplib2._ssl_wrap_socket = _ssl_wrap_socket

# End of the workaround for SSL3

if __name__ == "__main__":
    h1 = httplib2.Http()
    resp, content = h1.request("YOUR_SSL3_ONLY_LINK_HERE", "GET")
    print(content)

This workaround was based on the workarounds for urllib2 presented at this bug report http://bugs.python.org/issue11220,

Update: Presenting a solution for httplib2. I didn't notice you were using httplib2, I thought it was urllib2.

OTHER TIPS

Please refer to another StackOverflow threads that specify a solution. The way to specify a TLS version force the SSL version to TLSv1 as mentioned in the response by user favoretti within the provided link.

Hopefully, this works

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top