How to open ssl socket using certificate stored in

2019-01-09 05:46发布

In Python, ssl.wrap_socket can read certificates from files, ssl.wrap_socket require the certificate as a file path.

How can I start an SSL connection using a certificate read from string variables?

My host environment does not allow write to files, and tempfile module is not functional
I'm using Python 2.7.
I store the certificate inside MySQL and read as a string.

Edit: I gave up, this is basically require implement ssl by pure python code, this is beyond my current knowledge.

4条回答
Emotional °昔
2楼-- · 2019-01-09 05:59

You can treat strings like files with StringIO.

查看更多
成全新的幸福
3楼-- · 2019-01-09 06:13

From Python 3.4, you can use SSLContext#load_verify_locations:

context = ssl.SSLContext()
context.load_verify_locations(cadata=cert)  # Where cert is str.

From https://docs.python.org/3/library/ssl.html#ssl.SSLContext.load_verify_locations

查看更多
迷人小祖宗
4楼-- · 2019-01-09 06:18

Looking at the source, ssl.wrap_socket calls directly into the native code (openssl) function SSL_CTX_use_cert_chain_file which requires a path to a file, so what you are trying to do is not possible.

For reference:

In ssl/init.py we see:

def wrap_socket(sock, keyfile=None, certfile=None,
                server_side=False, cert_reqs=CERT_NONE,
                ssl_version=PROTOCOL_SSLv23, ca_certs=None,
                do_handshake_on_connect=True):

    return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
                   server_side=server_side, cert_reqs=cert_reqs,
                   ssl_version=ssl_version, ca_certs=ca_certs,
                   do_handshake_on_connect=do_handshake_on_connect)

Points us to the SSLSocket constructor (which is in the same file) and we see the following happen:

self._sslobj = _ssl2.sslwrap(self._sock, server_side,
                                     keyfile, certfile,
                                     cert_reqs, ssl_version, ca_certs)

_ssl2 is implemented in C (_ssl2.c)

Looking at the sslwrap function, we see it's creating a new object:

    return (PyObject *) newPySSLObject(Sock, key_file, cert_file,
                                       server_side, verification_mode,
                                       protocol, cacerts_file);

Looking at the constructor for that object, we eventually see:

            ret = SSL_CTX_use_certificate_chain_file(self->ctx,
                                                     cert_file);

That function is defined in openssl, so now we need to switch to that codebase.

In ssl/ssl_rsa.c we eventually find in the function:

BIO_read_filename(in,file) 

If you dig far enough into the BIO code (part of openssl) you'll eventually come to a normal fopen():

fp=fopen(ptr,p);

So it looks like as it's currently written. It must be in a file openable by C's fopen().

Also, since python's ssl library so quickly jumps into C, I don't see a immediately obvious place to monkeypatch in a workaround either.

查看更多
干净又极端
5楼-- · 2019-01-09 06:21

Quick look though the ssl module source confirms what you want is not supported by the API: http://code.google.com/codesearch#2T6lfGELm_A/trunk/Modules/_ssl.c&q=sslwrap&type=cs

Which is not to say it is impossible, you could create a named pipe, feed one end from Python and give the filename to the ssl module.

For simpler, less secure use, dump cert from memory to mkstemp()'d file.

You could even mount FUSE volume and intercept file callback.

Finally, use ctypes to hack at ssl context at runtime and load cert/ket from a buffer following the C recipe Read certificate files from memory instead of a file using OpenSSL Things like these have been done before, but it's not for the faintest of heart.

It looks like you are trying to get out of e.g. app engine "jail," perhaps it is just not possible?

If you are not picky on ssl implementation, you can use M2Crypto, TLS Lite, pyOpenSSL or something else. The earlier is pure python, you can definitely hack it to use in-memory certificates/keys.

查看更多
登录 后发表回答