xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/curl/examples/example3.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Sandboxed version of simplessl.c
16 // HTTPS GET request
17 
18 #include <cstdlib>
19 
20 #include "../curl_util.h"    // NOLINT(build/include)
21 #include "../sandbox.h"      // NOLINT(build/include)
22 #include "curl_sapi.sapi.h"  // NOLINT(build/include)
23 #include "absl/strings/str_cat.h"
24 #include "sandboxed_api/util/status_macros.h"
25 
26 namespace {
27 
28 class CurlSapiSandboxEx3 : public curl::CurlSapiSandbox {
29  public:
CurlSapiSandboxEx3(std::string ssl_certificate,std::string ssl_key,std::string ca_certificates)30   CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key,
31                      std::string ca_certificates)
32       : ssl_certificate(std::move(ssl_certificate)),
33         ssl_key(std::move(ssl_key)),
34         ca_certificates(std::move(ca_certificates)) {}
35 
36  private:
ModifyPolicy(sandbox2::PolicyBuilder *)37   std::unique_ptr<sandbox2::Policy> ModifyPolicy(
38       sandbox2::PolicyBuilder*) override {
39     // Add the syscalls and files missing in CurlSandbox to a new PolicyBuilder
40     auto policy_builder = std::make_unique<sandbox2::PolicyBuilder>();
41     (*policy_builder)
42         .AllowGetPIDs()
43         .AllowGetRandom()
44         .AllowHandleSignals()
45         .AddFile(ssl_certificate)
46         .AddFile(ssl_key)
47         .AddFile(ca_certificates);
48     // Provide the new PolicyBuilder to ModifyPolicy in CurlSandbox
49     return curl::CurlSapiSandbox::ModifyPolicy(policy_builder.get());
50   }
51 
52   std::string ssl_certificate;
53   std::string ssl_key;
54   std::string ca_certificates;
55 };
56 
Example3(const std::string & ssl_certificate,const std::string & ssl_key,const std::string & ssl_key_password,const std::string & ca_certificates)57 absl::Status Example3(const std::string& ssl_certificate,
58                       const std::string& ssl_key,
59                       const std::string& ssl_key_password,
60                       const std::string& ca_certificates) {
61   // Initialize sandbox2 and sapi
62   CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
63   SAPI_RETURN_IF_ERROR(sandbox.Init());
64   curl::CurlApi api(&sandbox);
65 
66   int curl_code;
67 
68   // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
69   SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
70   if (curl_code != 0) {
71     return absl::UnavailableError(absl::StrCat(
72         "curl_global_init failed: ", curl::StrError(&api, curl_code)));
73   }
74 
75   // Initialize curl easy handle
76   curl::CURL* curl_handle;
77   SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
78   sapi::v::RemotePtr curl(curl_handle);
79   if (!curl_handle) {
80     return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
81   }
82 
83   // Specify URL to get (using HTTPS)
84   sapi::v::ConstCStr url("https://example.com");
85   SAPI_ASSIGN_OR_RETURN(
86       curl_code,
87       api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
88   if (curl_code != 0) {
89     return absl::UnavailableError(absl::StrCat(
90         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
91   }
92 
93   // Set the SSL certificate type to "PEM"
94   sapi::v::ConstCStr ssl_cert_type("PEM");
95   SAPI_ASSIGN_OR_RETURN(
96       curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE,
97                                           ssl_cert_type.PtrBefore()));
98   if (curl_code != 0) {
99     return absl::UnavailableError(absl::StrCat(
100         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
101   }
102 
103   // Set the certificate for client authentication
104   sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str());
105   SAPI_ASSIGN_OR_RETURN(
106       curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT,
107                                           sapi_ssl_certificate.PtrBefore()));
108   if (curl_code != 0) {
109     return absl::UnavailableError(absl::StrCat(
110         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
111   }
112 
113   // Set the private key for client authentication
114   sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str());
115   SAPI_ASSIGN_OR_RETURN(curl_code,
116                         api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY,
117                                                  sapi_ssl_key.PtrBefore()));
118   if (curl_code != 0) {
119     return absl::UnavailableError(absl::StrCat(
120         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
121   }
122 
123   // Set the password used to protect the private key
124   sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str());
125   SAPI_ASSIGN_OR_RETURN(
126       curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD,
127                                           sapi_ssl_key_password.PtrBefore()));
128   if (curl_code != 0) {
129     return absl::UnavailableError(absl::StrCat(
130         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
131   }
132 
133   // Set the file with the certificates vaildating the server
134   sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str());
135   SAPI_ASSIGN_OR_RETURN(
136       curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO,
137                                           sapi_ca_certificates.PtrBefore()));
138   if (curl_code != 0) {
139     return absl::UnavailableError(absl::StrCat(
140         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
141   }
142 
143   // Verify the authenticity of the server
144   SAPI_ASSIGN_OR_RETURN(
145       curl_code,
146       api.curl_easy_setopt_long(&curl, curl::CURLOPT_SSL_VERIFYPEER, 1L));
147   if (curl_code != 0) {
148     return absl::UnavailableError(absl::StrCat(
149         "curl_easy_setopt_long failed: ", curl::StrError(&api, curl_code)));
150   }
151 
152   // Perform the request
153   SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
154   if (curl_code != 0) {
155     return absl::UnavailableError(absl::StrCat(
156         "curl_easy_perform failed: ", curl::StrError(&api, curl_code)));
157   }
158 
159   // Cleanup curl easy handle
160   SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&curl));
161 
162   // Cleanup curl
163   SAPI_RETURN_IF_ERROR(api.curl_global_cleanup());
164 
165   return absl::OkStatus();
166 }
167 
168 }  // namespace
169 
main(int argc,char * argv[])170 int main(int argc, char* argv[]) {
171   gflags::ParseCommandLineFlags(&argc, &argv, true);
172   sapi::InitLogging(argv[0]);
173 
174   // Get input parameters (should be absolute paths)
175   if (argc != 5) {
176     LOG(ERROR) << "wrong number of arguments (4 expected)";
177     return EXIT_FAILURE;
178   }
179 
180   if (absl::Status status = Example3(argv[1], argv[2], argv[3], argv[4]);
181       !status.ok()) {
182     LOG(ERROR) << "Example3 failed: " << status.ToString();
183     return EXIT_FAILURE;
184   }
185 
186   return EXIT_SUCCESS;
187 }
188