views:

98

answers:

3

I'm not sure how to word this exactly but I have a script that downloads an SSL certificate from a web server to check it's expiration date.

To do this, I need to download the CA certificates. Currently I write them to a temporary file in the /tmp directory and read it back later but I am sure there must be a way to do this without writing to disk.

Here's the portion that's downloading the certificates

CA_FILE = '/tmp/ca_certs.txt'

root_cert = urllib.urlopen('https://www.cacert.org/certs/root.txt')
class3_cert = urllib.urlopen('https://www.cacert.org/certs/class3.txt')

temp_file = open(CA_FILE, 'w')    
temp_file.write(root_cert.read())
temp_file.write(class3_cert.read())
temp_file.close()

EDIT

Here's the portion that uses the file to get the certificate

 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 ssl_sock = ssl.wrap_socket(s, ca_certs=CA_FILE, cert_reqs=ssl.CERT_REQUIRED)
 ssl_sock.connect(('mail.google.com', 443))

 date = ssl_sock.getpeercert()['notAfter']
+2  A: 

the response from urllib is a file object. just use those wherever you are using the actual files instead. This is assuming that the code that consumes the file objects doesn't need to write to them of course.

aaronasterling
I've tried and it produces the following errorTypeError: sslwrap() argument 7 must be string or None, not instance
Seth
it seems like `ssl.wrap_socket` requires a filename for the certs and opens the file itself
aaronasterling
Yes, exactly. Is there a way to trick it by making a variable in memory that looks like an actual file name?
Seth
as near as I can determine, the files get opened in a c extension. So there isn't much a chance of being able to change this behavior without rewriting that code. bummer
aaronasterling
I think you're correct. Guess I'll leave it as is. It's working anyhow. Thanks for your help.
Seth
+1  A: 

In the following line:

temp_file.write(root_cert.read())

you are actually reading the certificate into memory, and writing it out again. That line is equivalent to:

filedata = root_cert.read()
temp_file.write(filedata)

Now filedata is a variable containing the bytes of the root certificate, that you can use in any way you like (including not writing it to temp_file and doing something else with it instead).

Greg Hewgill
I see what you're saying but I can't get it to work correctly with ssl.wrap_socket. When I do that I get the following errorssl.SSLError: [Errno 185090050] _ssl.c:326: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system libI think it's just what format ssl.wrap_socket expects. I've only been able to make it work by feeding it a physical file on disk.
Seth
+3  A: 

Wow, don't do this. You're hitting cacert's site every time? That's INCREDIBLY rude and needlessly eats their resources. It's also ridiculously bad security practice. You're supposed to get the root certificate once and validate that it's the correct root cert and not some forgery, otherwise you can't rely on the validity of certificates signed by it.

Cache their root cert, or better yet, install it with the rest of the root certificates on your system like you're supposed to.

Nicholas Knight
I agree with you. I'm not hitting it every time. Only when the file doesn't already exist.The script isn't about security at all though. It's just a simple script to query a server's certificate to see when it will expire. I don't care about it's validity as it's my server. I just want to be reminded of expiration dates since I monitor hundreds of certificates.If you have a solution to only extract the expiration, that would be best for me.
Seth