|
14 | 14 |
|
15 | 15 | #include "google/cloud/internal/curl_impl.h" |
16 | 16 | #include "google/cloud/common_options.h" |
| 17 | +#include "google/cloud/credentials.h" |
17 | 18 | #include "google/cloud/internal/absl_str_cat_quiet.h" |
18 | 19 | #include "google/cloud/internal/absl_str_join_quiet.h" |
19 | 20 | #include "google/cloud/internal/algorithm.h" |
|
26 | 27 | #include "google/cloud/rest_options.h" |
27 | 28 | #include "absl/strings/match.h" |
28 | 29 | #include "absl/strings/strip.h" |
| 30 | +#include <curl/easy.h> |
29 | 31 | #include <algorithm> |
30 | 32 | #include <sstream> |
31 | 33 | #include <thread> |
@@ -198,6 +200,10 @@ CurlImpl::CurlImpl(CurlHandle handle, |
198 | 200 | proxy_username_ = CurlOptProxyUsername(options); |
199 | 201 | proxy_password_ = CurlOptProxyPassword(options); |
200 | 202 |
|
| 203 | + if (options.has<experimental::ClientSslCertificateOption>()) { |
| 204 | + client_ssl_cert_ = options.get<experimental::ClientSslCertificateOption>(); |
| 205 | + } |
| 206 | + |
201 | 207 | interface_ = CurlOptInterface(options); |
202 | 208 | } |
203 | 209 |
|
@@ -327,6 +333,44 @@ Status CurlImpl::MakeRequest(HttpMethod method, RestContext& context, |
327 | 333 | if (!status.ok()) return OnTransferError(context, std::move(status)); |
328 | 334 | } |
329 | 335 |
|
| 336 | + if (client_ssl_cert_.has_value()) { |
| 337 | +#if CURL_AT_LEAST_VERSION(7, 71, 0) |
| 338 | + status = handle_.SetOption(CURLOPT_SSL_VERIFYPEER, 1L); |
| 339 | + if (!status.ok()) return OnTransferError(context, std::move(status)); |
| 340 | + status = handle_.SetOption(CURLOPT_SSL_VERIFYHOST, 2L); |
| 341 | + if (!status.ok()) return OnTransferError(context, std::move(status)); |
| 342 | + |
| 343 | + status = handle_.SetOption(CURLOPT_SSLCERTTYPE, |
| 344 | + experimental::SslCertificate::ToString( |
| 345 | + client_ssl_cert_->ssl_certificate_type()) |
| 346 | + .c_str()); |
| 347 | + if (!status.ok()) return OnTransferError(context, std::move(status)); |
| 348 | + |
| 349 | + struct curl_blob ssl_cert_blob; |
| 350 | + ssl_cert_blob.data = |
| 351 | + const_cast<char*>(client_ssl_cert_->ssl_certificate().data()); |
| 352 | + ssl_cert_blob.len = client_ssl_cert_->ssl_certificate().length(); |
| 353 | + ssl_cert_blob.flags = CURL_BLOB_COPY; |
| 354 | + status = handle_.SetOption(CURLOPT_SSLCERT_BLOB, &ssl_cert_blob); |
| 355 | + if (!status.ok()) return OnTransferError(context, std::move(status)); |
| 356 | + |
| 357 | + struct curl_blob ssl_key_blob; |
| 358 | + ssl_key_blob.data = |
| 359 | + const_cast<char*>(client_ssl_cert_->ssl_private_key().data()); |
| 360 | + ssl_key_blob.len = client_ssl_cert_->ssl_private_key().length(); |
| 361 | + ssl_key_blob.flags = CURL_BLOB_COPY; |
| 362 | + status = handle_.SetOption(CURLOPT_SSLKEY_BLOB, &ssl_key_blob); |
| 363 | + if (!status.ok()) return OnTransferError(context, std::move(status)); |
| 364 | +#else |
| 365 | + return OnTransferError( |
| 366 | + context, |
| 367 | + internal::InvalidArgumentError( |
| 368 | + "libcurl 7.71.0 or higher required to use ClientSslCertificate", |
| 369 | + GCP_ERROR_INFO().WithMetadata("current_libcurl_version", |
| 370 | + LIBCURL_VERSION))); |
| 371 | +#endif |
| 372 | + } |
| 373 | + |
330 | 374 | if (method == HttpMethod::kGet) { |
331 | 375 | status = handle_.SetOption(CURLOPT_NOPROGRESS, 1L); |
332 | 376 | if (!status.ok()) return OnTransferError(context, std::move(status)); |
|
0 commit comments