Search code examples
pythonsslssl-certificatex509handshake

SSL in Python: Why it doesn't send certificate to server?


I'm writing some software that is supposed to acquire information from SSL-secured web page. Below there's piece of code I use to connect to server.

s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket (
    s,
    ca_certs = '/home/stilz/Desktop/Certyfikaty/GLOWNE_CA.cer',
    cert_reqs = ssl.CERT_REQUIRED,
    ssl_version = ssl.PROTOCOL_SSLv3,
)
ssl_sock.connect ((HOST, PORT))

However, this doesn't work. It throws exception with message "Handshake alert failed". I captured some TCP packets that come out of my script and also corresponding packets from Internet Explorer and figured out that my script doesn't send certificate at all (server returns something like "Fatal: no certificate supplied") while IE sends it normally. As far as I know file ca.cer is x509 certificate (beginning with "-----BEGIN CERTIFICATE-----").

Please help me and tell what I'm doing wrong. If I've supplied to few information, please let me know.

Regards


Solution

  • First of all, you need to determine if you need to authenticate yourself on the server (certificate is sent to the server only in this case) or you need to validate server's authenticity (in which case the certificate is not sent to the server).

    Now about issues in your code:

    Case 1: you don't need to authenticate on the server. In this case you don't need to specify your certificate and nothing is sent to the server.

    Case 2: you need to authenticate yourself on the server. In that case you need to provide your certificate and your private key file in keyfile and certfile parameters. Only then your certificate is sent to the server (and the private key is used in the handshake).

    I guess that your have case 1 in fact. So first of all you need to check if the server provides a valid certificate by connecting to it with a web browser and inspecting site's certificate chain. It can happen that the site sends its certificate but omits intermediate CA certificates.

    In any case I'd like to remind about the discussion about certificates in Python docs which I suggest you re-read.