I am trying to get https client authentication using this sample code in Python 2.7. Unfortunately, the client script does not seem to be authenticated correctly, and I could not find the reason.
I created test certificates for CA and server / client as follows:
# Generate CA key and certificate
openssl genrsa -des3 -out test.ca.key 8192
openssl req -new -key test.ca.key -x509 -days 30 -out test.ca.crt
# Generate server key and certificate
openssl genrsa -out www.testsite.com.key 1024
openssl req -new -key www.testsite.com.key -out www.testsite.com.csr
openssl x509 -req -days 30 -in www.testsite.com.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out www.testsite.com.crt
# Generate client key and certificate
openssl genrsa -out testclient.key 1024
openssl req -new -key testclient.key -out testclient.csr
openssl x509 -req -days 30 -in testclient.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out testclient.crt
Now, if I create a PKCS # 12 certificate:
openssl pkcs12 -export -clcerts -in testclient.crt -inkey testclient.key -out testclient.p12
... and import testclient.p12 into Firefox, I can view the test site as expected, so the server and keys will display correctly. However, if you try the sample code above, do the following:
import urllib2, httplib
class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
def __init__(self, key, cert):
urllib2.HTTPSHandler.__init__(self)
self.key = key
self.cert = cert
def https_open(self, req):
return self.do_open(self.getConnection, req)
def getConnection(self, host, timeout=300):
return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)
opener = urllib2.build_opener(HTTPSClientAuthHandler('testclient.key', 'testclient.crt') )
response = opener.open("https://www.testsite.com/")
print response.read()
... I get error 403:
Traceback (most recent call last):
File "./cert2.py", line 21, in <module>
response = opener.open("https://www.testsite.com/")
File "/usr/lib64/python2.6/urllib2.py", line 395, in open
response = meth(req, response)
File "/usr/lib64/python2.6/urllib2.py", line 508, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib64/python2.6/urllib2.py", line 433, in error
return self._call_chain(*args)
File "/usr/lib64/python2.6/urllib2.py", line 367, in _call_chain
result = func(*args)
File "/usr/lib64/python2.6/urllib2.py", line 516, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden
Where am I lost my way?
EDIT: here is the Apache config:
<VirtualHost *:80>
ServerAdmin webmaster@testsite.com
ServerName www.testsite.com
DocumentRoot /var/www/testsite/
<Directory "/">
Options FollowSymLinks
AllowOverride None
</Directory>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^/?(.*) https://www.testsite.com/$1 [L]
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@testsite.com
DocumentRoot /var/www/testsite/
ServerName www.testsite.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/www.testsite.com.crt
SSLCertificateKeyFile /etc/ssl/private/www.testsite.com.key
SSLCertificateChainFile /etc/ssl/ca/test.ca.crt
SSLCACertificateFile /etc/ssl/ca/test.ca.crt
<Location />
SSLRequireSSL
SSLVerifyClient require
SSLVerifyDepth 10
</Location>
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/testsite>
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/testsite/
<Directory "/usr/lib/cgi-bin/testsite">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined
</VirtualHost>