Set libcurl options based on protocol (HTTP or HTTPS)

Today update_engine only supports HTTPS protocol. So we lock down libcurl
to use only HTTPS, set options to validate the peer certificate,
set other SSL options, etc. Moving forward, we want to support payload
downloads via HTTP also. So, this CL sets the old options only if the URL
we're using is HTTPS. If it is HTTP, we just need to lock down the protocol
to HTTP.

BUG=chromium-os:36809
TEST=Existing unit tests pass.
TEST=Manually tested downloading using HTTP and HTTPS URLs on my ZGB.

Change-Id: I5948beb3bb84914dd3a3801f516c2eb15c857c6b
Reviewed-on: https://gerrit.chromium.org/gerrit/39142
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Commit-Ready: Jay Srinivasan <jaysri@chromium.org>
Tested-by: Jay Srinivasan <jaysri@chromium.org>
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index 7c40cba..4f66a54 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -168,39 +168,59 @@
   CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_MAXREDIRS, kMaxRedirects),
            CURLE_OK);
 
-  // Security lock-down in official builds: makes sure that peer certificate
-  // verification is enabled, restricts the set of trusted certificates,
-  // restricts protocols to HTTPS, restricts ciphers to HIGH.
+  // If we are running in test mode or dev mode (the call to IsOfficialBuild is
+  // a misnomer that needs to be fixed), then lock down the appropriate curl
+  // options for HTTP or HTTPS depending on the url.
   if (!is_test_mode_ && IsOfficialBuild()) {
-    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYPEER, 1),
-             CURLE_OK);
-    CHECK_EQ(curl_easy_setopt(curl_handle_,
-                              CURLOPT_CAPATH,
-                              kCACertificatesPath),
-             CURLE_OK);
-    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS),
-             CURLE_OK);
-    CHECK_EQ(curl_easy_setopt(curl_handle_,
-                              CURLOPT_REDIR_PROTOCOLS,
-                              CURLPROTO_HTTPS),
-             CURLE_OK);
-    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CIPHER_LIST,
-                              "HIGH:!ADH"),
-             CURLE_OK);
-    if (check_certificate_ != CertificateChecker::kNone) {
-      CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CTX_DATA,
-                                &check_certificate_),
-               CURLE_OK);
-      CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CTX_FUNCTION,
-                                CertificateChecker::ProcessSSLContext),
-               CURLE_OK);
-    }
+    if (url_to_use.find("http://") == 0)
+      SetCurlOptionsForHttp();
+    else
+      SetCurlOptionsForHttps();
+  } else {
+    LOG(INFO) << "Not setting http(s) curl options for test/dev mode";
   }
 
   CHECK_EQ(curl_multi_add_handle(curl_multi_handle_, curl_handle_), CURLM_OK);
   transfer_in_progress_ = true;
 }
 
+// Lock down only the protocol in case of HTTP.
+void LibcurlHttpFetcher::SetCurlOptionsForHttp() {
+  LOG(INFO) << "Setting up curl options for HTTP";
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, CURLPROTO_HTTP),
+           CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_REDIR_PROTOCOLS,
+                            CURLPROTO_HTTP),
+           CURLE_OK);
+}
+
+// Security lock-down in official builds: makes sure that peer certificate
+// verification is enabled, restricts the set of trusted certificates,
+// restricts protocols to HTTPS, restricts ciphers to HIGH.
+void LibcurlHttpFetcher::SetCurlOptionsForHttps() {
+  LOG(INFO) << "Setting up curl options for HTTPS";
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYPEER, 1),
+           CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_CAPATH, kCACertificatesPath),
+           CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS),
+           CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_REDIR_PROTOCOLS,
+                            CURLPROTO_HTTPS),
+           CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CIPHER_LIST, "HIGH:!ADH"),
+           CURLE_OK);
+  if (check_certificate_ != CertificateChecker::kNone) {
+    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CTX_DATA,
+                              &check_certificate_),
+             CURLE_OK);
+    CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_CTX_FUNCTION,
+                              CertificateChecker::ProcessSSLContext),
+             CURLE_OK);
+  }
+}
+
+
 // Begins the transfer, which must not have already been started.
 void LibcurlHttpFetcher::BeginTransfer(const std::string& url) {
   CHECK(!transfer_in_progress_);
diff --git a/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
index 981d096..7dba810 100644
--- a/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -191,6 +191,12 @@
   // Returns whether or not the current build is official.
   bool IsOfficialBuild() const;
 
+  // Sets the curl options for HTTP URL.
+  void SetCurlOptionsForHttp();
+
+  // Sets the curl options for HTTPS URL.
+  void SetCurlOptionsForHttps();
+
   // Handles for the libcurl library
   CURLM *curl_multi_handle_;
   CURL *curl_handle_;