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