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