Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL certificate pinning #1019

Open
arekmula opened this issue Jan 26, 2024 · 3 comments
Open

SSL certificate pinning #1019

arekmula opened this issue Jan 26, 2024 · 3 comments
Assignees
Milestone

Comments

@arekmula
Copy link

Is your feature request related to a problem?

Hey,
For the past 2 years, my team has been using raw CURL implementation to perform networking. We basically had our own wrapper around CURL. Some time ago, we decided to use a well-established CURL wrapper, and we ended up with cpr :)

We have a requirement to pin SSL certificates. I mean: the client application needs to pin leaf domain certificate first. If domain certificate is valid -> validation process is done. If domain certificate is invalid then as a fallback the client app should check intermediate CA certificate. If CA certificate is valid that means the domain's SSL certificate was changed or expired and new SSL fingerprint update is needed in the client application as soon as possible, but application still can communicate and transfer data. If both certificates are invalid then application shouldn't send or use any data to/from that source because man-in-the-middle attack is possible.

We were given SHA-256 fingerprints of the CA and domain certificates and we used CURLOPT_SSL_CTX_FUNCTION and CURLOPT_SSL_CTX_DATA to pass the certificates and perform the validation.

Is it possible to achieve the pinning with the current state of CPR? I couldn't find anything inside the docs regarding that. I see in the code this part:

#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
#ifdef OPENSSL_BACKEND_USED
    if (!options.ca_buffer.empty()) {
        curl_easy_setopt(curl_->handle, CURLOPT_SSL_CTX_FUNCTION, sslctx_function_load_ca_cert_from_buffer);
        curl_easy_setopt(curl_->handle, CURLOPT_SSL_CTX_DATA, options.ca_buffer.c_str());
    }
#endif
#endif

but I don't see an option to provide a custom callback.

Possible Solution

Add the API to set a custom CURLOPT_SSL_CTX_FUNCTION callback with custom CURLOPT_SSL_CTX_DATA data.

Alternatives

No response

Additional Context

No response

@COM8
Copy link
Member

COM8 commented Jan 27, 2024

@arekmula thanks for reporting!
You are right, there is no real support for it yet. But I will try to add support for it over the weekend if everything goes as planed.
The Interface would than look something like:

    /**
     * This callback function gets called by libcurl just before the initialization of an SSL connection
     * after having processed all other SSL related options to give a last chance to an application
     * to modify the behavior of the SSL initialization.
     *
     * If an error is returned from the callback no attempt to establish a connection is made
     * and the perform operation returns the callback's error code.
     * For no error return CURLE_OK from inside 'curl/curl.h'
     *
     * More/Source: https://curl.se/libcurl/c/CURLOPT_SSL_CTX_FUNCTION.html
     **/
    void SetSslCtxCallback(const SslCtxCallback& ssl_ctx);

Resulting in something like:

std::function<CURLcode(const std::shared_ptr<CurlHolder>& curl_holder, void* ssl_ctx, intptr_t userdata)>

for your custom callback.

@COM8 COM8 added this to the CPR 1.11.0 milestone Jan 27, 2024
@COM8 COM8 self-assigned this Jan 27, 2024
@arekmula
Copy link
Author

I have it already implemented and tested on my side. I can raise the MR. I would only need to adapt the API slightly to your proposed one and cover it with tests.

@arekmula
Copy link
Author

Raised the WIP Pull request: #1020

I was not sure about passing the CurlHolder. There's no constructor of CurlHolder accepting CURL* which I could use inside of sslCtxUserFunction. We can pass CURL* or don't pass it at all.

Tests are missing but I will try to add them tomorrow or on monday.

@COM8 COM8 modified the milestones: CPR 1.11.0, CPR 1.12.0 Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants