Python - SSL - wrong version number

Torxed picture Torxed · Apr 1, 2012 · Viewed 76.2k times · Source

This will probably be just another unsolved thread but i'll fill in some info anyway.

I can't get my SSL wrapping together not even for a second. Any ideas to what i'm doing wrong with my wrap_socket() and do_handshake()?

The key files appear to be 100% perfect, and i've tried with AND without the .recv() before the handshake. That just generates these depending on where i put the recv():

SSL3_GET_CLIENT_HELLO:wrong version number

SSL3_GET_RECORD:wrong version number

class Server():
    def __init__(self, listen = '', port = 8080, ssl = False):
        self.sock = socket.socket()
        self.sock.bind((listen, port))
        self.sock.listen(5)

    def accept(self):
        newsocket, fromaddr = self.sock.accept()
        newsocket.recv(32)
        newsocket.setblocking(0)
        sslsock = ssl.wrap_socket(newsocket,
                                    server_side=True,
                                    certfile="./kernel/sock/server.crt",
                                    keyfile="./kernel/sock/server.key",
                                    cert_reqs=ssl.CERT_NONE,
                                    ssl_version=ssl.PROTOCOL_TLSv1,
                                    do_handshake_on_connect=False,
                                    suppress_ragged_eofs=True)
        sslsock.do_handshake()
        return sslsock, fromaddr

For the record, if it's not obvious or i'm wrong, it's the handshake that fails :)

I modified the code a bit, trying SSLv3 and also change the position of the wrapping a bit:

import socket, ssl, time, select

class Server():
    def __init__(self, listen = '', port = 443, ssl = False):
        self.sock = socket.socket()
        self.sock.bind((listen, port))
        self.sock.listen(5)

    def accept(self):
        self.sock = ssl.wrap_socket(self.sock,
                                    server_side=True,
                                    certfile="./kernel/sock/server.crt",
                                    keyfile="./kernel/sock/server.key",
                                    cert_reqs=ssl.CERT_NONE,
                                    ssl_version=ssl.PROTOCOL_SSLv3,
                                    do_handshake_on_connect=False,
                                    suppress_ragged_eofs=True)

        newsocket, fromaddr = self.sock.accept()

        print [newsocket.recv(32)]
        newsocket.setblocking(False)
        newsocket.do_handshake()

        return newsocket, fromaddr

s = Server()
ns, na = s.accept()
print ns.recv(1024)

Now i get with the newsocket.recv(32):

ssl.SSLError: [Errno 1] _ssl.c:1331: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure

and without:

ssl.SSLError: [Errno 2] _ssl.c:490: The operation did not complete (read)

Also: i refuse to use Twisted

Scaling things down:

import socket, ssl, time, select
from OpenSSL import SSL

class Server():
    def __init__(self, listen = '', port = 443, ssl = False):
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.use_privatekey_file("server.pem")
        ctx.use_certificate_file("server.pem")
        self.sock = SSL.Connection(ctx, socket.socket())

        self.sock.bind((listen, port))
        self.sock.listen(5)

    def accept(self):
        newsocket, fromaddr = self.sock.accept()
        return newsocket, fromaddr

s = Server()
ns, na = s.accept()
print ns.recv(1024)

This works just as good as the "native" ssl library. However now i get this error:

OpenSSL.SSL.Error: [('SSL routines', 'SSL23_READ', 'ssl handshake failure')]


This is where i'm at now:

import socket, ssl, time #, select

class Server():
    def __init__(self, listen = '', port = 443, ssl = False):
        self.sock = socket.socket()
        self.sock.bind((listen, port))
        self.sock.listen(5)

    def accept(self):
        self.ssl_sock = None
        while not self.ssl_sock:
            self.ssl_sock = ssl.wrap_socket(self.sock,
                server_side=True,
                certfile=r"C:\moo.pem",
                keyfile=r"C:\moo.key",
                cert_reqs=ssl.CERT_NONE,
                ssl_version=ssl.PROTOCOL_TLSv1)

        newsocket, fromaddr = self.ssl_sock.accept()

        print([newsocket.recv()])

        return newsocket, fromaddr

s = Server()
ns, na = s.accept()
print(ns.recv(1024))

This works "prefectly" in Firefox, but NOT in Google Chrome. Why? what's the difference? -.-

Answer

Cratylus picture Cratylus · Apr 1, 2012

I don't know Python at all to tell you if you have a problem in your code.
The error though is clear. The client supports SSLv3 and your server only TLSv1.
So you should enable support for SSLv3 or upgrade your client.

This line seems to be the problem:ssl_version=ssl.PROTOCOL_TLSv1. Perhaps you can also add SSLv3 here?

Update:
I see that you have problem between browsers. See if SSLv3 is enabled in Crome.
In IE for example this is under Internet Options-> Advanced Tab.
Something similar should be in Chrome. Disable SSv3 and enable TLSv1 instead