1717#include " google/cloud/internal/curl_options.h"
1818#include " google/cloud/internal/make_status.h"
1919#include " google/cloud/log.h"
20+ #ifndef _WIN32
2021#include < openssl/err.h>
2122#include < openssl/ssl.h>
23+ #endif
2224#include < algorithm>
2325#include < iterator>
2426
@@ -42,7 +44,8 @@ struct X509InfoPtrCleanup {
4244};
4345
4446using X509InfoPtr = std::unique_ptr<STACK_OF(X509_INFO), X509InfoPtrCleanup>;
45-
47+ #else
48+ using SSL_CTX = void ;
4649#endif
4750
4851Status SetCurlCAInMemory (CurlHandleFactory const & factory, SSL_CTX* ssl_ctx) {
@@ -91,7 +94,7 @@ Status SetCurlCAInMemory(CurlHandleFactory const& factory, SSL_CTX* ssl_ctx) {
9194
9295extern " C" {
9396
94- static CURLcode SslCtxFunction ( // NOLINT(misc-use-anonymous-namespace)
97+ static CURLcode SslCtxCAInMemory ( // NOLINT(misc-use-anonymous-namespace)
9598 CURL*, void * ssl_ctx, void * userdata) {
9699 auto * handle_factory = reinterpret_cast <CurlHandleFactory*>(userdata);
97100 auto result = SetCurlCAInMemory (*handle_factory, (SSL_CTX*)ssl_ctx);
@@ -101,6 +104,13 @@ static CURLcode SslCtxFunction( // NOLINT(misc-use-anonymous-namespace)
101104 }
102105 return CURLE_OK;
103106}
107+
108+ static CURLcode SslCtxSanitized ( // NOLINT(misc-use-anonymous-namespace)
109+ CURL*, void * ssl_ctx, void * userdata) {
110+ auto * handle_factory = reinterpret_cast <CurlHandleFactory*>(userdata);
111+ return (CURLcode)handle_factory->ssl_ctx_callback ()(nullptr , ssl_ctx,
112+ nullptr );
113+ }
104114}
105115
106116void CurlHandleFactory::SetCurlStringOption (CURL* handle, CURLoption option_tag,
@@ -125,18 +135,24 @@ std::shared_ptr<CurlHandleFactory> GetDefaultCurlHandleFactory(
125135}
126136
127137DefaultCurlHandleFactory::DefaultCurlHandleFactory (Options const & o) {
138+ if (o.has <experimental::SslCtxCallbackOption>()) {
139+ ssl_ctx_callback_ = o.get <experimental::SslCtxCallbackOption>();
140+ return ;
141+ }
142+
128143 if (o.has <experimental::CAInMemoryOption>()) {
129144 ca_certs_ = o.get <experimental::CAInMemoryOption>();
130145 if (ca_certs_.empty ()) {
131146 GCP_LOG (FATAL) << internal::InvalidArgumentError (
132147 " No CA certificates specified" , GCP_ERROR_INFO ());
133148 }
134- } else {
135- if (o.has <CARootsFilePathOption>()) {
136- cainfo_ = o.get <CARootsFilePathOption>();
137- }
138- if (o.has <CAPathOption>()) capath_ = o.get <CAPathOption>();
149+ return ;
139150 }
151+
152+ if (o.has <CARootsFilePathOption>()) {
153+ cainfo_ = o.get <CARootsFilePathOption>();
154+ }
155+ if (o.has <CAPathOption>()) capath_ = o.get <CAPathOption>();
140156}
141157
142158CurlPtr DefaultCurlHandleFactory::CreateHandle () {
@@ -166,7 +182,7 @@ void DefaultCurlHandleFactory::CleanupMultiHandle(CurlMulti m,
166182}
167183
168184void DefaultCurlHandleFactory::SetCurlOptions (CURL* handle) {
169- if (!ca_certs_. empty () ) {
185+ if (ssl_ctx_callback_ ) {
170186 SetCurlStringOption (handle, CURLOPT_CAINFO, nullptr );
171187 SetCurlStringOption (handle, CURLOPT_CAPATH, nullptr );
172188 auto result = curl_easy_setopt (handle, CURLOPT_SSL_CTX_DATA, this );
@@ -175,27 +191,61 @@ void DefaultCurlHandleFactory::SetCurlOptions(CURL* handle) {
175191 GCP_ERROR_INFO ());
176192 }
177193 result =
178- curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxFunction );
194+ curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxSanitized );
179195 if (result != CURLE_OK) {
180196 GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
181197 GCP_ERROR_INFO ());
182198 }
183- } else {
184- if (cainfo_) {
185- SetCurlStringOption (handle, CURLOPT_CAINFO, cainfo_->c_str ());
199+ return ;
200+ }
201+
202+ if (!ca_certs_.empty ()) {
203+ SetCurlStringOption (handle, CURLOPT_CAINFO, nullptr );
204+ SetCurlStringOption (handle, CURLOPT_CAPATH, nullptr );
205+ auto result = curl_easy_setopt (handle, CURLOPT_SSL_CTX_DATA, this );
206+ if (result != CURLE_OK) {
207+ GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
208+ GCP_ERROR_INFO ());
186209 }
187- if (capath_) {
188- SetCurlStringOption (handle, CURLOPT_CAPATH, capath_->c_str ());
210+ result =
211+ curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxCAInMemory);
212+ if (result != CURLE_OK) {
213+ GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
214+ GCP_ERROR_INFO ());
189215 }
216+ return ;
217+ }
218+
219+ if (cainfo_) {
220+ SetCurlStringOption (handle, CURLOPT_CAINFO, cainfo_->c_str ());
221+ }
222+ if (capath_) {
223+ SetCurlStringOption (handle, CURLOPT_CAPATH, capath_->c_str ());
190224 }
191225}
192226
193227PooledCurlHandleFactory::PooledCurlHandleFactory (std::size_t maximum_size,
194228 Options const & o)
195- : maximum_size_(maximum_size),
196- cainfo_ (CAInfo(o)),
197- capath_(CAPath(o)),
198- ca_certs_(CACerts(o)) {}
229+ : maximum_size_(maximum_size) {
230+ if (o.has <experimental::SslCtxCallbackOption>()) {
231+ ssl_ctx_callback_ = o.get <experimental::SslCtxCallbackOption>();
232+ return ;
233+ }
234+
235+ if (o.has <experimental::CAInMemoryOption>()) {
236+ ca_certs_ = o.get <experimental::CAInMemoryOption>();
237+ if (ca_certs_.empty ()) {
238+ GCP_LOG (FATAL) << internal::InvalidArgumentError (
239+ " No CA certificates specified" , GCP_ERROR_INFO ());
240+ }
241+ return ;
242+ }
243+
244+ if (o.has <CARootsFilePathOption>()) {
245+ cainfo_ = o.get <CARootsFilePathOption>();
246+ }
247+ if (o.has <CAPathOption>()) capath_ = o.get <CAPathOption>();
248+ }
199249
200250PooledCurlHandleFactory::~PooledCurlHandleFactory () = default ;
201251
@@ -303,7 +353,7 @@ void PooledCurlHandleFactory::CleanupMultiHandle(CurlMulti m,
303353}
304354
305355void PooledCurlHandleFactory::SetCurlOptions (CURL* handle) {
306- if (!ca_certs_. empty () ) {
356+ if (ssl_ctx_callback_ ) {
307357 SetCurlStringOption (handle, CURLOPT_CAINFO, nullptr );
308358 SetCurlStringOption (handle, CURLOPT_CAPATH, nullptr );
309359 auto result = curl_easy_setopt (handle, CURLOPT_SSL_CTX_DATA, this );
@@ -312,39 +362,37 @@ void PooledCurlHandleFactory::SetCurlOptions(CURL* handle) {
312362 GCP_ERROR_INFO ());
313363 }
314364 result =
315- curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxFunction );
365+ curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxSanitized );
316366 if (result != CURLE_OK) {
317367 GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
318368 GCP_ERROR_INFO ());
319369 }
320- } else {
321- if (cainfo_) {
322- SetCurlStringOption (handle, CURLOPT_CAINFO, cainfo_->c_str ());
370+ return ;
371+ }
372+
373+ if (!ca_certs_.empty ()) {
374+ SetCurlStringOption (handle, CURLOPT_CAINFO, nullptr );
375+ SetCurlStringOption (handle, CURLOPT_CAPATH, nullptr );
376+ auto result = curl_easy_setopt (handle, CURLOPT_SSL_CTX_DATA, this );
377+ if (result != CURLE_OK) {
378+ GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
379+ GCP_ERROR_INFO ());
323380 }
324- if (capath_) {
325- SetCurlStringOption (handle, CURLOPT_CAPATH, capath_->c_str ());
381+ result =
382+ curl_easy_setopt (handle, CURLOPT_SSL_CTX_FUNCTION, &SslCtxCAInMemory);
383+ if (result != CURLE_OK) {
384+ GCP_LOG (FATAL) << internal::InternalError (curl_easy_strerror (result),
385+ GCP_ERROR_INFO ());
326386 }
387+ return ;
327388 }
328- }
329-
330- absl::optional<std::string> PooledCurlHandleFactory::CAInfo (Options const & o) {
331- if (!o.has <CARootsFilePathOption>()) return absl::nullopt ;
332- return o.get <CARootsFilePathOption>();
333- }
334-
335- absl::optional<std::string> PooledCurlHandleFactory::CAPath (Options const & o) {
336- if (!o.has <CAPathOption>()) return absl::nullopt ;
337- return o.get <CAPathOption>();
338- }
339389
340- std::vector<absl::string_view> PooledCurlHandleFactory::CACerts (
341- Options const & o) {
342- if (!o.has <experimental::CAInMemoryOption>()) return {};
343- if (o.get <experimental::CAInMemoryOption>().empty ()) {
344- GCP_LOG (FATAL) << internal::InvalidArgumentError (
345- " No CA certificates specified" , GCP_ERROR_INFO ());
390+ if (cainfo_) {
391+ SetCurlStringOption (handle, CURLOPT_CAINFO, cainfo_->c_str ());
392+ }
393+ if (capath_) {
394+ SetCurlStringOption (handle, CURLOPT_CAPATH, capath_->c_str ());
346395 }
347- return o.get <experimental::CAInMemoryOption>();
348396}
349397
350398GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
0 commit comments