1 | |
---|---|
2 | #include "cpr/ssl_ctx.h" |
3 | |
4 | #if SUPPORT_CURLOPT_SSL_CTX_FUNCTION |
5 | |
6 | #ifdef OPENSSL_BACKEND_USED |
7 | |
8 | #include <openssl/err.h> |
9 | #include <openssl/safestack.h> |
10 | #include <openssl/ssl.h> |
11 | |
12 | namespace cpr { |
13 | |
14 | /** |
15 | * The ssl_ctx parameter is actually a pointer to the SSL library's SSL_CTX for OpenSSL. |
16 | * If an error is returned from the callback no attempt to establish a connection is made and |
17 | * the perform operation will return the callback's error code. |
18 | * |
19 | * Sources: https://curl.se/libcurl/c/CURLOPT_SSL_CTX_FUNCTION.html |
20 | * https://curl.se/libcurl/c/CURLOPT_SSL_CTX_DATA.html |
21 | */ |
22 | CURLcode sslctx_function_load_ca_cert_from_buffer(CURL* /*curl*/, void* sslctx, void* raw_cert_buf) { |
23 | // Check arguments |
24 | if (raw_cert_buf == nullptr || sslctx == nullptr) { |
25 | printf(format: "Invalid callback arguments\n"); |
26 | return CURLE_ABORTED_BY_CALLBACK; |
27 | } |
28 | |
29 | // Setup pointer |
30 | X509_STORE* store = nullptr; |
31 | X509* cert = nullptr; |
32 | BIO* bio = nullptr; |
33 | char* cert_buf = static_cast<char*>(raw_cert_buf); |
34 | |
35 | // Create a memory BIO using the data of cert_buf. |
36 | // Note: It is assumed, that cert_buf is nul terminated and its length is determined by strlen. |
37 | bio = BIO_new_mem_buf(buf: cert_buf, len: -1); |
38 | |
39 | // Load the PEM formatted certicifate into an X509 structure which OpenSSL can use. |
40 | PEM_read_bio_X509(out: bio, x: &cert, cb: nullptr, u: nullptr); |
41 | if (cert == nullptr) { |
42 | printf(format: "PEM_read_bio_X509 failed\n"); |
43 | return CURLE_ABORTED_BY_CALLBACK; |
44 | } |
45 | |
46 | // Get a pointer to the current certificate verification storage |
47 | store = SSL_CTX_get_cert_store(static_cast<SSL_CTX*>(sslctx)); |
48 | |
49 | // Add the loaded certificate to the verification storage |
50 | const int status = X509_STORE_add_cert(ctx: store, x: cert); |
51 | if (status == 0) { |
52 | printf(format: "Error adding certificate\n"); |
53 | return CURLE_ABORTED_BY_CALLBACK; |
54 | } |
55 | |
56 | // Decrement the reference count of the X509 structure cert and frees it up |
57 | X509_free(a: cert); |
58 | |
59 | // Free the entire bio chain |
60 | BIO_free(a: bio); |
61 | |
62 | // The CA certificate was loaded successfully into the verification storage |
63 | return CURLE_OK; |
64 | } |
65 | |
66 | } // namespace cpr |
67 | |
68 | #endif // OPENSSL_BACKEND_USED |
69 | |
70 | #endif // SUPPORT_CURLOPT_SSL_CTX_FUNCTION |