3

I'm looking for a way to get to the information about SSL certificate used by the remote site using requests (CA and CN would suffice).

I can easily get those when I use for example socket + OpenSSL, but in my code I use a special resolver ( Python 'requests' library - define specific DNS? ), so I need to use Requests or urllib2 - so far I examined most of the requests code through inspect module, and I see no way of getting to these values.

I'd appreciate any hints at this point, maybe I'm missing something obvious :)

[edit]:

To be more precise - I'm patching part of the requests lib (from 'socket' up to urllib2), to use a custom name resolver- it comes down to this:

self.my_opener = urllib2.build_opener(MyHTTPHandler,MyHTTPSHandler) (urllib2.OpenerDirector instance)

my_opener.open(url) returns an urllib.addinfourl object - from which I would need to extract certificate info if that's at all posible.

Unfortunately this is not the case for the question after which this one was marked as a duplicate.

Community
  • 1
  • 1
Taku
  • 562
  • 1
  • 6
  • 15

2 Answers2

1

Requests source code is quite explicit when it comes to validating certificates, see:

https://github.com/kennethreitz/requests/blob/826667a54c608d72d8813c3eddb75b27ab26c988/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py#L67

Either monkey-patch this code, or track down where it is called from:

https://github.com/kennethreitz/requests/blob/dae4026c18b29b5995d41c1e50741a3d34f1297e/requests/packages/urllib3/connection.py#L189

Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120
  • The certificate will always be invalid by requests standards (they're self-signed, generated on-the-fly). I just need the CA / CN from the certificate to check if other method changed it correctly on the recieving end - that's all. – Taku May 05 '14 at 13:10
  • Monkey patch requests to use your version of `ssl_match_hostname`. btw., there are 2 steps of certificate validation. An aside, there are 2 steps of certificate validation -- 1 ensure server owns private key for the cert it send (`verify=True` keyword, really happens on C level, in ssl extension and openssl) and check that this url/hostname is allowed for this cert (ssl_match_hostname). You only need to tweak the latter. – Dima Tisnek May 06 '14 at 09:28
0

Found it.

Example:

f=my_opener.open(url)
f.fp._sock.fp._sock._sslobj # here's the ssl object holding the 'issuer' (CA) and 'server' (CN) attributes.

This is valid when you use the patching from this question: Python 'requests' library - define specific DNS?

This case is so peculiar, that I hope no one else will ever have to use this. However, if you're using requests, switching between custom name resolvers and have to check the SSL cert CA/CN, I hope this helps :)

Community
  • 1
  • 1
Taku
  • 562
  • 1
  • 6
  • 15