6

I have written a simple webserver & client with python, following is my code. I want to implement HTTPS, for that I am using standard SSL library. I am using Python 2.7.3. I generated certificate file and self signed it. So I have .crt and .key files which I use it to bind on the socket.

When I browse it from the browser, I get the exception error that certificate is self signed and I have to add it to the exceptions. Then it works.

Code of my sever :

import BaseHTTPServer
import urlparse
import urllib 
import SocketServer
import threading
import ssl

HOST_NAME = 'localhost'
PORT_NUMBER = 8089


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_GET(self):

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        if self.path == '/get/':
            self.wfile.write('On /get/')
            return
        self.wfile.write('On root')
        return    

    def do_POST(self):
        pass

class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
    pass


if __name__ == '__main__':
    httpd = BaseHTTPServer.HTTPServer((HOST_NAME, PORT_NUMBER), Handler)
    httpd.socket = ssl.wrap_socket (httpd.socket, keyfile='my_key.key', certfile='my_cert.crt', server_side=True)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        httpd.server_close()
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER)

However I am trying to use requests module and when I provide the .crt file with the requests, I get the following error:

requests.get('https://localhost:8089', verify=True)
#requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

requests.get('https://localhost:8089', verify='my_cert.crt')
#requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

requests.get('https://localhost:8089', cert='my_crt.crt')
#requests.exceptions.SSLError: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

requests.get('https://localhost:8089', cert=('my_crt.crt', 'my_key.key'))
# requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed    

requests.get('https://localhost:8089', verify=False)
#<Response [200]>

1) Why I am getting this error? I certainly don't want to use 'verify=False'. I want to validate the certificate at the client side.

2) (Assuming I get to make it work) If I enforce cert_reqs=CERT_REQUIRED by changing :

httpd.socket = ssl.wrap_socket (httpd.socket, keyfile='my_key.key', certfile='my_cert.crt', cert_reqs=CERT_REQUIRED, server_side=True)

then does it mean only people who have my cert file (my_cert.crt) will be able to send request and get the response and people who don't, will not be able to?

3
  • Compare your certfile to the one provided with Requests, make sure they're both in the same format. That's the most obvious failure cause. Commented Dec 9, 2013 at 14:27
  • they are same. Infact I am running both client and server from same folder and they use same key Commented Dec 9, 2013 at 14:34
  • That's not what I meant. Requests ships with a default cacert.pem file, as you can see here. I meant that you should make sure the format here matches the format of your certfile. Commented Dec 9, 2013 at 17:01

1 Answer 1

5

An SSL certificate can only be validated by the client if it has the certificate used for signing the validating certificate. This is the main reason why self-signed certificate are not commonly used on the Internet. Usually you ask some organization (Certification Authority) to sign you certificate with its. Those CA are commonly trusted by people and other organization so that their certificates are already built-in in many clients.

So, if you want to make everybody able to validate your certificate, you should not self-sign it. There are many CA out there and some of them issues certificate for free. Unless you get a CA-signed certificate only people who already have your certificate would validate it.

EDIT:

As a side note: when you tell your browser to add an exception for a particular site you are telling him to not validate at all its certificate. So you will not be protected against MITM.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't want everybody able to validate my certificate. Only few people whom I know.
In this case you can use a self-signed certificate, but you have to give it to everyone who have to connect to your server. Then they should add it in their browser. If instead they add an exception, the use of SSL becomes pointless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.