I have spent quite some time doing my research on how to tackle this problem but could not find a working solution yet.
Problem: I am using OpenSSL library and linux. I have a server process P1 accepting SSL connection from SSL client. P1 does tcp_accept() and then SSL_accept() and exchanges some protocol data with client with SSL_read/SSL_write(). Everything is fine till this point. Now by design P1 needs to fork a child process C1 to serve the client from this point onwards. C1 uses execve call to re-image itself and spawn a different binary. C1 still needs to talk to the SSL client over the same SSL connection that was used in P1. The problem is since C1 is a completely different process now how it can re-use the existing SSL connection for that client? I am able to pass the underlying TCP socket descriptor from P1 to C1 as it is maintained in kernel but I can not pass the SSL context since it's maintained in the Openssl Library.
I saw this tread on stackoverflow but unfortunately no solution is mentioned. OpenSSL: accept TLS connection and then transfer to another process
Possible Solution: I am not sure if anybody has already solved this kind of problem but I tried following.
I thought I can just create a new SSL conctext and do SSL renegotiation in the new child process. So in C1 I created a new SSL context over the same underlying tcp socket fd and tried to do SSL renegotiation. Here is what I did (Omiting the SSL_ctx initialization part)
ssl = SSL_new(ctx) // ctx is initialized the same as it was done in P1 server
SSL_set_fd(ssl, fd); // fd is the underlying tcp socket fd passed from P1 to C1
SSL_set_accept_state(ssl);
SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
SSL_renegotiate(ssl);
SSL_do_handshake(ssl);
ssl->state=SSL_ST_ACCEPT;
SSL_do_handshake(ssl);
But the renegotiation does not succeed and returns me an Openssl Internal error from first SSL_do_handshake() call. I am not even sure if this can really be done. The other solution that I can think of is following.
Has anybody faced similar problem and solved it? I will really appreciate any help regarding this.
Thanks a lot
A search online finds this discussion:
Passing TLS sessions between programs
Once you have the SSL_SESSION, convert it to ASN1 (via i2d_SSL_SESSION) and dump it to a file. Read that file in with your second program and convert it back from ASN1 to SSL_SESSION(via d2i_SSL_SESSION) and add it to the SSL_SESSION cache of the SSL_CTX (via SSL_CTX_add_session).
I found in doc/ssleay.txt :
[...]
The PEM_write_SSL_SESSION(fp,x) and PEM_read_SSL_SESSION(fp,x,cb) will write to a file pointer in base64 encoding. What you can do with this, is pass session information between separate processes.
[...]
So you need to serialize the SSL session data from P1 and pass it to C1 to deserialize, along with the socket descriptor. You can then create new SSL
and SSL_CTX
objects in C1 and associate them with the socket and deserialized session data so C1 can take over the conversation.
I did a search for "tls kernel mode" and found a kernel patch to give a normal fd for a TLS connection. Thus the fd can be passed to other processes as a normal socket.
The page is titled "TLS in the kernel" on lwn.net. Towards the bottom there are interesting discussions about it. Hope it may get its way into the kernel mainline. Or else wish someone may come up with a production quality patch set so people can make real use of it.
If you know some real products are using it, probably it's a good idea to share it here.
Update: This open source project "TLSe" as a replacement to openssh is specially designed for exporting context to another process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With