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
12namespace 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 */
22CURLcode 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