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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With