1--- 2c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 3SPDX-License-Identifier: curl 4Title: CURLOPT_SSL_CTX_FUNCTION 5Section: 3 6Source: libcurl 7See-also: 8 - CURLOPT_SSL_CTX_DATA (3) 9 - CURLOPT_SSL_VERIFYPEER (3) 10 - CURLOPT_CAINFO (3) 11Protocol: 12 - TLS 13TLS-backend: 14 - OpenSSL 15 - wolfSSL 16 - mbedTLS 17 - BearSSL 18--- 19 20# NAME 21 22CURLOPT_SSL_CTX_FUNCTION - SSL context callback 23 24# SYNOPSIS 25 26~~~c 27#include <curl/curl.h> 28 29CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp); 30 31CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_FUNCTION, 32 ssl_ctx_callback); 33~~~ 34 35# DESCRIPTION 36 37Pass a pointer to your callback function, which should match the prototype 38shown above. 39 40This callback function gets called by libcurl just before the initialization 41of an SSL connection after having processed all other SSL related options to 42give a last chance to an application to modify the behavior of the SSL 43initialization. The *ssl_ctx* parameter is a pointer to the SSL library's 44*SSL_CTX* for OpenSSL or wolfSSL, a pointer to *mbedtls_ssl_config* for 45mbedTLS or a pointer to *br_ssl_client_context* for BearSSL. If an error is 46returned from the callback no attempt to establish a connection is made and 47the perform operation returns the callback's error code. Set the *clientp* 48argument passed in to this callback with the CURLOPT_SSL_CTX_DATA(3) option. 49 50This function gets called for all new connections made to a server, during the 51SSL negotiation. While *ssl_ctx* points to a newly initialized object each 52time, the pointer may still be the same as in a prior call. 53 54To use this callback, a non-trivial amount of knowledge of your SSL library is 55necessary. For example, you can use this function to call library-specific 56callbacks to add additional validation code for certificates, and even to 57change the actual URI of an HTTPS request. 58 59For OpenSSL, asynchronous certificate verification via *SSL_set_retry_verify* 60is supported. (Added in 8.3.0) 61 62The CURLOPT_SSL_CTX_FUNCTION(3) callback allows the application to reach in 63and modify SSL details in the connection without libcurl itself knowing 64anything about it, which then subsequently can lead to libcurl unknowingly 65reusing SSL connections with different properties. To remedy this you may set 66CURLOPT_FORBID_REUSE(3) from the callback function. 67 68If you are using DNS-over-HTTPS (DoH) via CURLOPT_DOH_URL(3) then this 69callback is also called for those transfers and the curl handle is set to an 70internal handle. **This behavior is subject to change.** We recommend setting 71CURLOPT_PRIVATE(3) on your curl handle so you can identify it correctly in the 72context callback. If you have a reason to modify DoH SSL context please let us 73know on the curl-library mailing list because we are considering removing this 74capability. 75 76libcurl does not guarantee the lifetime of the passed in object once this 77callback function has returned. Your application must not assume that it can 78keep using the SSL context or data derived from it once this function is 79completed. 80 81# DEFAULT 82 83NULL 84 85# EXAMPLE 86 87~~~c 88/* OpenSSL specific */ 89 90#include <openssl/ssl.h> 91#include <curl/curl.h> 92#include <stdio.h> 93 94static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) 95{ 96 X509_STORE *store; 97 X509 *cert = NULL; 98 BIO *bio; 99 char *mypem = parm; 100 /* get a BIO */ 101 bio = BIO_new_mem_buf(mypem, -1); 102 /* use it to read the PEM formatted certificate from memory into an 103 * X509 structure that SSL can use 104 */ 105 PEM_read_bio_X509(bio, &cert, 0, NULL); 106 if(!cert) 107 printf("PEM_read_bio_X509 failed...\n"); 108 109 /* get a pointer to the X509 certificate store (which may be empty) */ 110 store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx); 111 112 /* add our certificate to this store */ 113 if(X509_STORE_add_cert(store, cert) == 0) 114 printf("error adding certificate\n"); 115 116 /* decrease reference counts */ 117 X509_free(cert); 118 BIO_free(bio); 119 120 /* all set to go */ 121 return CURLE_OK; 122} 123 124int main(void) 125{ 126 CURL *ch; 127 CURLcode rv; 128 char *mypem = /* example CA cert PEM - shortened */ 129 "-----BEGIN CERTIFICATE-----\n" 130 "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n" 131 "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n" 132 "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n" 133 "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n" 134 "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n" 135 "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n" 136 "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n" 137 "-----END CERTIFICATE-----\n"; 138 139 curl_global_init(CURL_GLOBAL_ALL); 140 ch = curl_easy_init(); 141 142 curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM"); 143 curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L); 144 curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/"); 145 146 curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function); 147 curl_easy_setopt(ch, CURLOPT_SSL_CTX_DATA, mypem); 148 rv = curl_easy_perform(ch); 149 if(!rv) 150 printf("*** transfer succeeded ***\n"); 151 else 152 printf("*** transfer failed ***\n"); 153 154 curl_easy_cleanup(ch); 155 curl_global_cleanup(); 156 return rv; 157} 158~~~ 159 160# AVAILABILITY 161 162OpenSSL (added in 7.11.0), wolfSSL (added in 7.42.0), mbedTLS (added in 1637.54.0) or BearSSL (added in 7.83.0) 164 165# RETURN VALUE 166 167CURLE_OK if supported; or an error such as: 168 169CURLE_NOT_BUILT_IN - Not supported by the SSL backend 170