title: Client certificate authentication over https is failing
body: <p>I'm attempting to get https client authentication working using <a href="https://stackoverflow.com/a/4464435/789671">this sample code</a> in Python 2.7. Unfortunately, the client script doesn't appear to be authenticating correctly and I've not been able to track down why.</p>
  
  <p>I generated a test CA and server/client certificates as follows:</p>
  
  <pre><code># 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
  </code></pre>
  
  <p>Now if I generate a PKCS#12 certificate:</p>
  
  <pre><code>openssl pkcs12 -export -clcerts -in testclient.crt -inkey testclient.key -out testclient.p12
  </code></pre>
  
  <p>...and import testclient.p12 into Firefox, I can browse the test site as expected, so the server and keys would appear to be configured properly. However, when trying the sample code referenced above, as follows:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>... I get a 403 error:</p>
  
  <pre><code>Traceback (most recent call last):
    File "./cert2.py", line 21, in &lt;module&gt;
      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
  </code></pre>
  
  <p>Where did I go astray?</p>
  
  <p>EDIT: Here's the site's Apache config:</p>
  
  <pre><code>&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@testsite.com
    ServerName www.testsite.com
  
    DocumentRoot /var/www/testsite/
    &lt;Directory "/"&gt;
      Options FollowSymLinks
      AllowOverride None
    &lt;/Directory&gt;
  
    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
  &lt;/VirtualHost&gt;
  
  &lt;VirtualHost *:443&gt;
    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
  
    &lt;Location /&gt;
      SSLRequireSSL
      SSLVerifyClient require
      SSLVerifyDepth 10
    &lt;/Location&gt;
  
    &lt;Directory /&gt;
      Options FollowSymLinks
      AllowOverride None
    &lt;/Directory&gt;
    &lt;Directory /var/www/testsite&gt;
      Options FollowSymLinks MultiViews
      AllowOverride None
      Order allow,deny
      allow from all
    &lt;/Directory&gt;
  
    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/testsite/
    &lt;Directory "/usr/lib/cgi-bin/testsite"&gt;
      AllowOverride None
      Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
      Order allow,deny
      Allow from all
    &lt;/Directory&gt;
  
    ErrorLog /var/log/apache2/error.log
    LogLevel warn
    CustomLog /var/log/apache2/access.log combined
  &lt;/VirtualHost&gt;
  </code></pre>