SSL_use_certificate seems to be causing a double free

▼魔方 西西 提交于 2019-12-05 12:35:26

I was plagued by this, and I thank you for your follow up answer.

My solution, was instead of deleting the ssl::context instance in the destructor of what created it, I posted the delete to the main io_service:

Something like:

MyThing::~MyThing() {
    boost::asio::ssl::context *c = ssl_context_;
    socket_.get_io_service().post([c](){ delete c; });
}

that seemed to cure it just fine for me. (I use new/delete because I only create it as needed).

I think that there must be a more deterministic way of doing this, maybe shared_ptr but I haven't worked it out yet.

So, Michael Foukarakis helped me question some of my assumptions in the comments which ultimately led to me solving this issue, so full credits to him. Here is where I went wrong in my approach and how I resolved it.

As mentioned in the question, I was originally creating a new SSL_CTX (boost::asio::ssl::context) object for every single proxy connection: one for the downstream, one up. The upstream, being the proxy acting as a client, was having boost::asio::ssl::context::load_verify_file("ca-bundle.crt") on it's context during initialization, which was leading to massive bloat in the application's ram consumption.

The second part of the original problem was that I was creating a new SSL_CTX for each downstream connection, the connection to our client where we're serving a spoofed certificate and handshaking pretending to be the origin server. Each new connection "bridge" is handed a reference to a "CertStore" object on construction that is designed to spoof, store and retrieve certificates and their keypairs, indexed by the host name.

So what we had going on was a central place holding certs and keys, but each individual SSL_CTX object being assigned these certs and keys and then destroyed when the connection closed, which eventually, "randomly" would lead to a double-free somewhere since openSSL uses internal reference counting on (most?) objects. These references would be increased and decreased by SSL_CTX's being created, having SSL_CTX_use_certificate and SSL_CTX_use_PrivateKey being called on them, then destroyed. Eventually two SSL_CTX's dying would be holding a reference to the same cert or keypair with a reference count of 1, leading to a double free of the memory when both contexts finally died.

The solution is to use a single shared context that you keep safe and alive somewhere until application shutdown for your upstream (client) connections. Call boost::asio::ssl::context::load_verify_file("ca-bundle.crt") on that single context once, then have all client SSL-Object spawn from it. As for server contexts, create one server context per-host that you're acting as, set the cert and private key of that context, and then share that context between all downstream SSL* sockets that act on behalf of that host.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!