13

I have a site that has PKI security enabled. Each client used either a card reader to load their certificate, or the certificate is installed in the IE certificate storage on their box.

So my question are:

  1. How can I use either the card reader certificate or the certificate stored on the system to verify the system?
  2. How do I pass the credentials onto the site to say, hey I'm me and I can access the service? They example can be using soft certificates. I can figure out the card reader part later.

I've been searching around, and I haven't come up with anything to help me in this situation. Django has a bunch of modules, but this isn't an option because I'm only concerned of the client side of things. I'm not creating a site to host the service. I need to just access these services.

I have this code working sort of. I just do not know how to handle the redirect I am getting:

import httplib
KEYFILE = r"C:\cert\my.key"
CERTFILE = r"c:\cert\my.pem"
HOSTNAME = 'machine.com'

conn = httplib.HTTPSConnection(
    HOSTNAME,
    key_file = KEYFILE,
    cert_file = CERTFILE
)

conn.putrequest('GET', '/arcgis/sharing/rest?f=json')
conn.endheaders()
response = conn.getresponse()
print response.read()

The result of all of this is:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://machine.com/pki?https://machine.com/arcgis/sharing/rest%3f&amp;f=json">here</a>.</p>
</body></html>

Any help provided would be great!

Software specs: python 2.7.8, Windows 2012 R2

code base 5000
  • 3,812
  • 13
  • 44
  • 73
  • Can you share a bit about what you've tried so far? Punting on #1 (obtaining the certificate) for the moment, assuming "PKI auth" means "client certificate auth", I believe #2 is baked into libraries that wrap https/ssl/tls. E.g., in requests, use: `requests.get(url, cert=('path/to/cert', 'path/to/key'))` (sorry - didn't mean to post as an answer) – bimsapi Jun 08 '15 at 21:09
  • It looks like what you're calling "PKI" is in fact "client certificate authentication" (PKI is a broader field than that, and generally includes verifying server certificates). Do you know if your card reader provides PKCS#11 drivers, or is it just the Windows API? – Bruno Jun 08 '15 at 22:52
  • Are you planning to use any specific libraries in Python, by the way? – Bruno Jun 09 '15 at 00:50
  • @Bruno - I do not have any python libraries in mind. I'm not married to any one solution. – code base 5000 Jun 09 '15 at 14:51
  • @bimsapi - I've tries variations of the following solution: http://code.activestate.com/recipes/577548-https-httplib-client-connection-with-certificate-v/ without success. – code base 5000 Jun 09 '15 at 14:53
  • Try http://stackoverflow.com/questions/2195179/need-help-using-m2crypto-engine-to-access-usb-token for smartcard-based authentication. Depending on your environment / situation, that may be the best you'll be able to do. It's easier if you can get a signed cert with local key on file to use ("soft certs"). – Sean Baker Jun 10 '15 at 00:12
  • You may need to follow PC/SC standard, there's PyCSC library, e.g. here https://github.com/imrehg/pcsc-lite-clone but it's not for the faint of heart! – Dima Tisnek Jun 12 '15 at 08:20

2 Answers2

4

I created a PKI handler to handle the requests so I can use it work urllib2 library.

import httplib, urllib2

class HTTPSClientAuthHandler(urllib2.HTTPSHandler):

    def __init__(self, key, cert):
        urllib2.HTTPSHandler.__init__(self)
        self.key = key
        self.cert = cert
    def https_open(self, req):
        #Rather than pass in a reference to a connection class, we pass in
        # a reference to a function which, for all intents and purposes,
        # will behave as a constructor
        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,
                                             timeout=timeout)

To use this, you will need to use a cookiejar with the handler.

from cookielib import CookieJar
cookiejar = CookieJay()
handlers = []
handlers.append(HTTPSClientAuthHandler(somekey, somecert))
handlers.append(urllib2.HTTPCookieProcessor(cookiejar))
opener = urllib2.build_opener(*handlers)
... do other urllib2 calls ....

Hope this helps everyone!

code base 5000
  • 3,812
  • 13
  • 44
  • 73
1

Try this code

#!/usr/bin/env python

import httplib

CERTFILE = '/home/robr/mycert'
HOSTNAME = 'localhost'

conn = httplib.HTTPSConnection(
    HOSTNAME,
    key_file = CERTFILE,
    cert_file = CERTFILE
)
conn.putrequest('GET', '/ssltest/')
conn.endheaders()
response = conn.getresponse()
print response.read()
Jaffer Wilson
  • 7,029
  • 10
  • 62
  • 139