Index: net/cup_request.cc |
diff --git a/net/cup_request.cc b/net/cup_request.cc |
deleted file mode 100644 |
index 87db7f665220d424fb8d231d2dbf987e1209b267..0000000000000000000000000000000000000000 |
--- a/net/cup_request.cc |
+++ /dev/null |
@@ -1,742 +0,0 @@ |
-// Copyright 2008-2010 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
-// |
-// TODO(omaha): to minimize conversions from UNICODE to UTF-8 consider an |
-// API that takes the request body as UTF-8 and it stores it as UTF-8. |
- |
-#include "omaha/net/cup_request.h" |
- |
-#include <atlconv.h> |
-#include <atlstr.h> |
-#include <vector> |
-#include "omaha/base/const_addresses.h" |
-#include "omaha/base/debug.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/encrypt.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/path.h" |
-#include "omaha/base/safe_format.h" |
-#include "omaha/base/security/b64.h" |
-#include "omaha/base/security/hmac.h" |
-#include "omaha/base/security/rsa.h" |
-#include "omaha/base/security/sha.h" |
-#include "omaha/base/string.h" |
-#include "omaha/base/utils.h" |
-#include "omaha/net/cup_utils.h" |
-#include "omaha/net/http_client.h" |
-#include "omaha/net/net_utils.h" |
-#include "omaha/net/network_config.h" |
- |
-using omaha::encrypt::EncryptData; |
-using omaha::encrypt::DecryptData; |
- |
-namespace omaha { |
- |
-namespace detail { |
- |
-class CupRequestImpl { |
- public: |
- explicit CupRequestImpl(HttpRequestInterface* http_request); |
- ~CupRequestImpl(); |
- |
- HRESULT Close(); |
- HRESULT Send(); |
- HRESULT Cancel(); |
- HRESULT Pause(); |
- HRESULT Resume(); |
- std::vector<uint8> GetResponse() const; |
- HRESULT QueryHeadersString(uint32 info_level, |
- const TCHAR* name, |
- CString* value) const; |
- CString GetResponseHeaders() const; |
- int GetHttpStatusCode() const; |
- CString ToString() const; |
- void SetEntropy(const void* data, size_t data_length); |
- |
- void set_session_handle(HINTERNET session_handle); |
- void set_url(const CString& url); |
- void set_request_buffer(const void* buffer, size_t buffer_length); |
- void set_proxy_configuration(const ProxyConfig& proxy_config); |
- void set_filename(const CString& filename); |
- void set_low_priority(bool low_priority); |
- void set_callback(NetworkRequestCallback* callback); |
- void set_additional_headers(const CString& additional_headers); |
- void set_preserve_protocol(bool preserve_protocol); |
- CString user_agent() const; |
- void set_user_agent(const CString& user_agent); |
- void set_proxy_auth_config(const ProxyAuthConfig& proxy_auth_config); |
- |
- private: |
- HRESULT DoSend(); |
- HRESULT BuildRequest(); |
- HRESULT BuildChallengeHash(); |
- HRESULT BuildClientProof(); |
- HRESULT InitializeEntropy(); |
- HRESULT AuthenticateResponse(); |
- |
- // Loads the {sk, c} credentials from persistent storage. |
- HRESULT LoadCredentials(std::vector<uint8>* sk, CStringA* c); |
- |
- // Saves the {sk, c} credentials. The key is encrypted before saving it. |
- HRESULT SaveCredentials(const std::vector<uint8>& sk, const CStringA& c); |
- |
- // Replaces the https protocol scheme with http if changing protocol is |
- // allowed. |
- HRESULT BuildInnerRequestUrl(const CString& url, CString* inner_url); |
- |
- // The transient state of the request, so that we can start always with a |
- // clean slate even though the same instance is being reuse across requests. |
- struct TransientCupState { |
- std::vector<uint8> entropy; |
- std::vector<uint8> r; // Random bytes (r). |
- std::vector<uint8> sk; // Cached shared key (sk) |
- std::vector<uint8> new_sk; // Current shared_key (sk'). |
- std::vector<uint8> hw; // Challenge hash (hw). |
- std::vector<uint8> hm; // Response hash (hm). |
- |
- CStringA cp; // Client proof (cp). |
- CStringA sp; // Server proof (sp). |
- CStringA vw; // Versioned challenge (v|w). |
- std::vector<uint8> response; // The received response. |
- CStringA c; // Cached client cookie (c) |
- CStringA new_cookie; // The cookie returned by the server (c'). |
- |
- // The url of the request. It includes the original url plus the versioned |
- // challenge (v|w). |
- CStringA request_url; |
- }; |
- scoped_ptr<TransientCupState> cup_; |
- |
- CStringA url_; // The original url. |
- CString additional_headers_; |
- bool preserve_protocol_; // Should not change request scheme if |
- // true. |
- const void* request_buffer_; // Contains the request body for POST. |
- size_t request_buffer_length_; // Length of the request body. |
- std::vector<uint8> entropy_; // Optional entropy pass by the caller, |
- // mostly for testing purpose. |
- |
- // {sk, c} credentials. They are persisted in the registry when the object is |
- // destroyed. The vast majority of network code runs impersonated. Writing |
- // through the credentials is likely to fail. However, due to how the |
- // CUP object is being used by the upper layers of the network code, a |
- // write back policy is possible. |
- std::vector<uint8> persisted_sk_; |
- CStringA persisted_c_; |
- |
- scoped_ptr<RSA> rsa_; |
- RSA::PublicKey public_key_; // Server public key (pk[v]). |
- scoped_ptr<HttpRequestInterface> http_request_; // Inner http request. |
- |
- static const RSA::PublicKeyInstance kCupProductionPublicKey; |
- static const RSA::PublicKeyInstance kCupTestPublicKey; |
- |
- DISALLOW_EVIL_CONSTRUCTORS(CupRequestImpl); |
-}; |
- |
-const RSA::PublicKeyInstance CupRequestImpl::kCupProductionPublicKey = |
-#include "omaha/net/cup_pubkey.3.h" |
-; // NOLINT |
- |
-const RSA::PublicKeyInstance CupRequestImpl::kCupTestPublicKey = |
-#include "omaha/net/cup_pubkey.2.h" |
-; // NOLINT |
- |
-CupRequestImpl::CupRequestImpl(HttpRequestInterface* http_request) |
- : preserve_protocol_(false), |
- request_buffer_(NULL), |
- request_buffer_length_(0), |
- public_key_(NULL) { |
- ASSERT1(http_request); |
- bool is_using_cup_test_keys = NetworkConfig::IsUsingCupTestKeys(); |
- public_key_ = is_using_cup_test_keys ? kCupTestPublicKey : |
- kCupProductionPublicKey; |
- |
- // Try to retrieve the credentials if we have any. If we have succeeded, then |
- // we must have a {sk, c} pair. If we have failed, then we will generate |
- // a fresh set of credentials later on. |
- HRESULT hr = LoadCredentials(&persisted_sk_, &persisted_c_); |
- if (FAILED(hr)) { |
- ASSERT1(persisted_sk_.empty()); |
- ASSERT1(persisted_c_.IsEmpty()); |
- } |
- |
- rsa_.reset(new RSA(public_key_)); |
- http_request_.reset(http_request); |
- |
- // Decorate the user agent by appending the "CUP" suffix. This overrides |
- // the user agent of the inner http request. |
- CString user_agent(http_request_->user_agent()); |
- user_agent += _T(";cup"); |
- http_request_->set_user_agent(user_agent); |
-} |
- |
-CupRequestImpl::~CupRequestImpl() { |
- Close(); |
-} |
- |
-HRESULT CupRequestImpl::Close() { |
- cup_.reset(); |
- |
- // TODO(omaha): optimize so that if the credentials did not change then |
- // there would be not need to write back. |
- if (!persisted_sk_.empty() && !persisted_c_.IsEmpty()) { |
- VERIFY1(SUCCEEDED(SaveCredentials(persisted_sk_, persisted_c_))); |
- } |
- return http_request_->Close(); |
-} |
- |
-HRESULT CupRequestImpl::Send() { |
- // Start with a fresh CUP state. This is important as the client may |
- // reuse the same CUP request for subsequent requests. |
- cup_.reset(new TransientCupState); |
- |
- // First, build a request, send it, and then authenticate the response. |
- HRESULT hr = BuildRequest(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- hr = DoSend(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- hr = AuthenticateResponse(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::BuildRequest() { |
- HRESULT hr(InitializeEntropy()); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- // Start with some random bytes. |
- cup_->r = cup_utils::RsaPad(rsa_->size(), |
- &cup_->entropy.front(), cup_->entropy.size()); |
- |
- // Derive a new shared key (sk') as the hash of the random bytes. |
- // TODO(omaha): consider protecting the key using ::CryptProtectmemory when |
- // not being used. |
- cup_->new_sk = cup_utils::Hash(cup_->r); |
- |
- // Compute the challenge (w) by encrypting in place (r) with the server |
- // public key pk[v]. |
- size_t encrypted_size = rsa_->raw(&cup_->r.front(), cup_->r.size()); |
- ASSERT1(encrypted_size == cup_->r.size()); |
- |
- // Compute the versioned challenge (v|w) as |
- // decimal-v:base64-encoded-rsa-wrapper. |
- SafeCStringAFormat(&cup_->vw, "%d:%s", |
- rsa_->version(), |
- cup_utils::B64Encode(&cup_->r.front(), cup_->r.size())); |
- |
- // Compute the url of the CUP request. |
- // Append a query string or append to the existing query string if any. |
- const char* format_string = url_.Find('?') != -1 ? "%1&w=%2" : "%1?w=%2"; |
- cup_->request_url.FormatMessage(format_string, url_, cup_->vw); |
- |
- // Compute the challenge hash (hw) as HASH(HASH(v|w)|HASH(req)) |
- hr = BuildChallengeHash(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- // Compute the client proof as SYMsign[sk](0|hw|HASH(c)) if we have a |
- // {sk, c} pair or as SYMsign[sk'](3|hw) if we do not. |
- hr = BuildClientProof(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- NET_LOG(L4, (_T("[hw: %s]"), BytesToHex(cup_->hw))); |
- |
- // This is what the client sends up along with the request: a versioned |
- // challenge, a client proof, and a client cookie if it has one. |
- |
- NET_LOG(L4, (_T("[request: %s]"), CA2T(cup_->request_url))); |
- NET_LOG(L4, (_T("[ifmatch: %s]"), CA2T(cup_->cp))); |
- NET_LOG(L4, (_T("[cookie: %s]"), CA2T(cup_->c))); |
- |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::BuildChallengeHash() { |
- // The hash of the request if carried through all the cryptographic proofs. |
- // The challenge hash hw is computed as: |
- // HASH(HASH(v|w)|HASH(request_url)|HASH(body)). |
- // For simplicity, the protocol scheme and the port are dropped before |
- // hashing. The hash is computed over the CUP request url, which includes |
- // the versioned hash. |
- scoped_ptr<HttpClient> http_client(CreateHttpClient()); |
- if (!http_client.get()) { |
- return OMAHA_NET_E_CUP_NO_HTTP_CLIENT; |
- } |
- HRESULT hr = http_client->Initialize(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- ASSERT1(!cup_->request_url.IsEmpty()); |
- CString url(cup_->request_url); |
- CString scheme, server, url_path, query_string; |
- hr = http_client->CrackUrl(url, |
- 0, |
- &scheme, |
- &server, |
- NULL, |
- &url_path, |
- &query_string); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- ASSERT1(!scheme.IsEmpty()); |
- ASSERT1(!server.IsEmpty()); |
- ASSERT1(!url_path.IsEmpty()); |
- url.FormatMessage(_T("//%1%2%3"), server, url_path, query_string); |
- |
- CStringA req(url); |
- |
- // Compute hw as HASH(HASH(v|w)|HASH(request_url)|HASH(body)). |
- ASSERT1(!cup_->vw.IsEmpty()); |
- ASSERT1(!url.IsEmpty()); |
- cup_->hw = cup_utils::HashBuffers(cup_->vw.GetString(), cup_->vw.GetLength(), |
- req.GetString(), req.GetLength(), |
- request_buffer_, request_buffer_length_); |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::BuildClientProof() { |
- // Use persisted {sk, c} or start with empty credentials otherwise. |
- ASSERT1(cup_->sk.empty()); |
- ASSERT1(cup_->c.IsEmpty()); |
- if (!persisted_sk_.empty() && !persisted_c_.IsEmpty()) { |
- cup_->sk = persisted_sk_; |
- cup_->c = persisted_c_; |
- } |
- |
- std::vector<uint8> hcp; // hmac of the client proof. |
- if (!cup_->sk.empty() && !cup_->c.IsEmpty()) { |
- // Use the cached shared key (sk) and the cookie (c) if we have them. |
- ASSERT1(cup_->sk.size() == SHA_DIGEST_SIZE); |
- NET_LOG(L4, (_T("[using sk: %s]"), BytesToHex(cup_->sk))); |
- |
- // Compute 'cp' as SYMsign[sk](0|HASH(w)|HASH(c)) |
- std::vector<uint8> hc = cup_utils::Hash(cup_->c); |
- hcp = cup_utils::SymSign(cup_->sk, 0, &cup_->hw, &hc, NULL); |
- } else { |
- // There is no saved shared key. Use current shared key (new_sk). |
- ASSERT1(cup_->new_sk.size() == SHA_DIGEST_SIZE); |
- NET_LOG(L4, (_T("[using sk': %s]"), BytesToHex(cup_->new_sk))); |
- |
- // Compute 'cp' as SYMsign[sk'](3|HASH(w)) |
- hcp = cup_utils::SymSign(cup_->new_sk, 3, &cup_->hw, NULL, NULL); |
- } |
- |
- NET_LOG(L4, (_T("[client proof hmac: %s]"), BytesToHex(hcp))); |
- cup_->cp = cup_utils::B64Encode(hcp); |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::AuthenticateResponse() { |
- // This is what the server has sent down along with the response: |
- // a server proof, and optionally a new cookie for the client. |
- NET_LOG(L4, (_T("[etag: %s]"), CA2T(cup_->sp))); |
- NET_LOG(L4, (_T("[svr cookie: %s]"), CA2T(cup_->new_cookie))); |
- |
- if (cup_->sp.IsEmpty()) { |
- // We can't authenticate anything without the server proof. |
- return OMAHA_NET_E_CUP_NO_SERVER_PROOF; |
- } |
- |
- // Compute the hash of the response (hm). |
- cup_->hm = cup_utils::Hash(cup_->response); |
- NET_LOG(L4, (_T("[hm: %s]"), BytesToHex(cup_->hm))); |
- |
- // Verify the response and the challenge w are authenticated by the |
- // client shared key. The validation has at least one subtle aspect: the |
- // client must try two signatures. First, it tries to authenticate using |
- // the new sk and the new cookie. If the response does not authenticate but |
- // the client has an old key, it should try authenticating with the old key. |
- // This second step is important in the case of an attacker or server |
- // misconfiguration where the server is signing with the old key but still |
- // sending a cookie. |
- std::vector<uint8> hmac; |
- if (!cup_->new_cookie.IsEmpty() && !cup_->new_sk.empty()) { |
- // The server has sent down a new cookie because the client proof or the |
- // client cookie were not good or missing. Try to authenticate using the |
- // new shared key and the new cookie {sk', c'}. |
- std::vector<uint8> hnew_c = cup_utils::Hash(cup_->new_cookie); // HASH(c') |
- |
- // Compute the server proof (sp) as SYMsign[sk'](1|hw|hm|hc'). |
- hmac = cup_utils::SymSign(cup_->new_sk, 1, &cup_->hw, &cup_->hm, &hnew_c); |
- CStringA expected_sp = cup_utils::B64Encode(hmac); |
- |
- if (expected_sp == cup_->sp) { |
- // Copy the credentials to write them back when this object is destroyed. |
- persisted_sk_ = cup_->new_sk; |
- persisted_c_ = cup_->new_cookie; |
- return S_OK; |
- } |
- } |
- |
- if (!cup_->sk.empty()) { |
- // The server has accepted our client proof (cp) and consequently the sk. |
- |
- // Compute the server proof as SYMsign[sk](2|hw|hm). |
- hmac = cup_utils::SymSign(cup_->sk, 2, &cup_->hw, &cup_->hm, NULL); |
- CStringA expected_sp = cup_utils::B64Encode(hmac); |
- |
- if (expected_sp == cup_->sp) { |
- return S_OK; |
- } |
- } |
- |
- NET_LOG(L4, (_T("[expected server proof: %s]"), BytesToHex(hmac))); |
- |
- // The server proof does not authenticate. We reject this response. |
- return OMAHA_NET_E_CUP_NOT_TRUSTED; |
-} |
- |
-HRESULT CupRequestImpl::LoadCredentials(std::vector<uint8>* sk, CStringA* c) { |
- ASSERT1(sk); |
- ASSERT1(c); |
- NetworkConfig* network_config = NULL; |
- NetworkConfigManager& network_manager = NetworkConfigManager::Instance(); |
- HRESULT hr = network_manager.GetUserNetworkConfig(&network_config); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- CupCredentials cup_credentials; |
- hr = network_config->GetCupCredentials(&cup_credentials); |
- if (SUCCEEDED(hr)) { |
- sk->swap(cup_credentials.sk); |
- *c = cup_credentials.c; |
- } |
- return hr; |
-} |
- |
-HRESULT CupRequestImpl::SaveCredentials(const std::vector<uint8>& sk, |
- const CStringA& c) { |
- NetworkConfig* network_config = NULL; |
- NetworkConfigManager& network_manager = NetworkConfigManager::Instance(); |
- HRESULT hr = network_manager.GetUserNetworkConfig(&network_config); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- CupCredentials cup_credentials; |
- cup_credentials.sk = sk; |
- cup_credentials.c = c; |
- return network_config->SetCupCredentials(&cup_credentials); |
-} |
- |
-HRESULT CupRequestImpl::DoSend() { |
- // The url of the inner request includes the versioned challenge. |
- // It replaces the protocol from https to http since CUP over https is |
- // not supported. |
- CString inner_request_url; |
- HRESULT hr = BuildInnerRequestUrl(CString(cup_->request_url), |
- &inner_request_url); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- http_request_->set_url(inner_request_url); |
- |
- // Prepare additional headers to send. |
- CString additional_headers(additional_headers_); |
- |
- // The client proof (cp) is sent as the "If-Match" header. |
- ASSERT1(!cup_->cp.IsEmpty()); |
- CStringA if_match_header; |
- SafeCStringAFormat(&if_match_header, "\"%s\"", cup_->cp); |
- additional_headers += HttpClient::BuildRequestHeader(_T("If-Match"), |
- CA2T(if_match_header)); |
- |
- // Send the client cookie (c) if we have one. |
- if (!cup_->c.IsEmpty()) { |
- additional_headers += HttpClient::BuildRequestHeader(_T("Cookie"), |
- CA2T(cup_->c)); |
- } |
- http_request_->set_additional_headers(additional_headers); |
- |
- NET_LOG(L5, (_T("[CUP request][%s]"), |
- BufferToPrintableString(request_buffer_, |
- request_buffer_length_))); |
- hr = http_request_->Send(); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- http_request_->GetResponse().swap(cup_->response); |
- int status_code(http_request_->GetHttpStatusCode()); |
- if (status_code != HTTP_STATUS_OK && |
- status_code != HTTP_STATUS_PARTIAL_CONTENT) { |
- return HRESULTFromHttpStatusCode(status_code); |
- } |
- NET_LOG(L5, (_T("[CUP response][%s]"), |
- VectorToPrintableString(cup_->response))); |
- |
- // Get the server proof (sp). |
- CString etag_header; |
- http_request_->QueryHeadersString(WINHTTP_QUERY_ETAG, NULL, &etag_header); |
- UnenclosePath(&etag_header); // Remove the quotes. |
- cup_->sp = CT2A(etag_header); |
- |
- // Get the client cookie c'. The cookie may or may not be there. If the |
- // server has accepted both client proof (sp) then no |
- // new cookie is sent down. This is an indication for the client to |
- // use its {sk, c} pair. |
- CString set_cookie_header; |
- http_request_->QueryHeadersString(WINHTTP_QUERY_SET_COOKIE, |
- NULL, &set_cookie_header); |
- |
- // Parse the cookie header to extract c=xxx cookie. |
- cup_->new_cookie = CT2A(cup_utils::ParseCupCookie(set_cookie_header)); |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::Cancel() { |
- return http_request_->Cancel(); |
-} |
- |
-HRESULT CupRequestImpl::Pause() { |
- return http_request_->Pause(); |
-} |
- |
-HRESULT CupRequestImpl::Resume() { |
- return http_request_->Resume(); |
-} |
- |
-std::vector<uint8> CupRequestImpl::GetResponse() const { |
- return http_request_->GetResponse(); |
-} |
- |
-HRESULT CupRequestImpl::QueryHeadersString(uint32 info_level, |
- const TCHAR* name, |
- CString* value) const { |
- return http_request_->QueryHeadersString(info_level, name, value); |
-} |
- |
-CString CupRequestImpl::GetResponseHeaders() const { |
- return http_request_->GetResponseHeaders(); |
-} |
- |
-int CupRequestImpl::GetHttpStatusCode() const { |
- return http_request_->GetHttpStatusCode(); |
-} |
- |
-CString CupRequestImpl::ToString() const { |
- return CString("CUP:") + http_request_->ToString(); |
-} |
- |
-void CupRequestImpl::set_session_handle(HINTERNET session_handle) { |
- http_request_->set_session_handle(session_handle); |
-} |
- |
-void CupRequestImpl::set_url(const CString& url) { |
- url_ = CT2A(url, CP_UTF8); |
-} |
- |
-void CupRequestImpl::set_request_buffer(const void* buffer, |
- size_t buffer_length) { |
- request_buffer_ = buffer; |
- request_buffer_length_ = buffer_length; |
- http_request_->set_request_buffer(request_buffer_, request_buffer_length_); |
-} |
- |
-void CupRequestImpl::set_proxy_configuration(const ProxyConfig& proxy_config) { |
- http_request_->set_proxy_configuration(proxy_config); |
-} |
- |
-void CupRequestImpl::set_filename(const CString& filename) { |
- http_request_->set_filename(filename); |
-} |
- |
-void CupRequestImpl::set_low_priority(bool low_priority) { |
- http_request_->set_low_priority(low_priority); |
-} |
- |
-void CupRequestImpl::set_callback(NetworkRequestCallback* callback) { |
- http_request_->set_callback(callback); |
-} |
- |
-void CupRequestImpl::set_additional_headers(const CString& additional_headers) { |
- additional_headers_ = additional_headers; |
-} |
- |
-void CupRequestImpl::set_preserve_protocol(bool preserve_protocol) { |
- preserve_protocol_ = preserve_protocol; |
-} |
- |
-CString CupRequestImpl::user_agent() const { |
- return http_request_->user_agent(); |
-} |
- |
-void CupRequestImpl::set_user_agent(const CString& user_agent) { |
- http_request_->set_user_agent(user_agent); |
-} |
- |
-void CupRequestImpl::set_proxy_auth_config(const ProxyAuthConfig& config) { |
- http_request_->set_proxy_auth_config(config); |
-} |
- |
-void CupRequestImpl::SetEntropy(const void* data, size_t data_length) { |
- ASSERT(false, (_T("Do not call from production code"))); |
- ASSERT1(data); |
- const uint8* first(static_cast<const uint8*>(data)); |
- const uint8* last(first + data_length); |
- std::vector<uint8> new_entropy(first, last); |
- entropy_.swap(new_entropy); |
-} |
- |
-HRESULT CupRequestImpl::InitializeEntropy() { |
- if (entropy_.empty()) { |
- cup_->entropy.resize(rsa_->size() - SHA_DIGEST_SIZE); |
- if (!GenRandom(&cup_->entropy.front(), cup_->entropy.size())) { |
- return OMAHA_NET_E_CUP_NO_ENTROPY; |
- } |
- } else { |
- cup_->entropy = entropy_; |
- } |
- return S_OK; |
-} |
- |
-HRESULT CupRequestImpl::BuildInnerRequestUrl(const CString& url, |
- CString* inner_url) { |
- ASSERT1(inner_url); |
- if (!String_StartsWith(url, kHttpsProtoScheme, true)) { |
- *inner_url = url; |
- return S_OK; |
- } |
- |
- if (preserve_protocol_) { |
- // Request must be sent through https. So return error here so we can |
- // fall back to the next request type in the chain without CUP. |
- return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); |
- } |
- |
- *inner_url = url.Mid(_tcslen(kHttpsProtoScheme)); |
- inner_url->Insert(0, kHttpProtoScheme); |
- return S_OK; |
-} |
- |
-} // namespace detail |
- |
- |
-CupRequest::CupRequest(HttpRequestInterface* http_request) { |
- ASSERT1(http_request); |
- impl_.reset(new detail::CupRequestImpl(http_request)); |
-} |
- |
-CupRequest::~CupRequest() { |
-} |
- |
-HRESULT CupRequest::Close() { |
- return impl_->Close(); |
-} |
- |
-HRESULT CupRequest::Send() { |
- return impl_->Send(); |
-} |
- |
-HRESULT CupRequest::Cancel() { |
- return impl_->Cancel(); |
-} |
- |
-HRESULT CupRequest::Pause() { |
- return impl_->Pause(); |
-} |
- |
-HRESULT CupRequest::Resume() { |
- return impl_->Resume(); |
-} |
- |
-std::vector<uint8> CupRequest::GetResponse() const { |
- return impl_->GetResponse(); |
-} |
- |
-int CupRequest::GetHttpStatusCode() const { |
- return impl_->GetHttpStatusCode(); |
-} |
- |
-HRESULT CupRequest::QueryHeadersString(uint32 info_level, |
- const TCHAR* name, |
- CString* value) const { |
- return impl_->QueryHeadersString(info_level, name, value); |
-} |
- |
-CString CupRequest::GetResponseHeaders() const { |
- return impl_->GetResponseHeaders(); |
-} |
- |
-CString CupRequest::ToString() const { |
- return impl_->ToString(); |
-} |
- |
-void CupRequest::set_session_handle(HINTERNET session_handle) { |
- return impl_->set_session_handle(session_handle); |
-} |
- |
-void CupRequest::set_url(const CString& url) { |
- impl_->set_url(url); |
-} |
- |
-void CupRequest::set_request_buffer(const void* buffer, size_t buffer_length) { |
- impl_->set_request_buffer(buffer, buffer_length); |
-} |
- |
-void CupRequest::set_proxy_configuration(const ProxyConfig& proxy_config) { |
- impl_->set_proxy_configuration(proxy_config); |
-} |
- |
-void CupRequest::set_filename(const CString& filename) { |
- impl_->set_filename(filename); |
-} |
- |
-void CupRequest::set_low_priority(bool low_priority) { |
- impl_->set_low_priority(low_priority); |
-} |
- |
-void CupRequest::set_callback(NetworkRequestCallback* callback) { |
- impl_->set_callback(callback); |
-} |
- |
-void CupRequest::set_additional_headers(const CString& additional_headers) { |
- impl_->set_additional_headers(additional_headers); |
-} |
- |
-void CupRequest::set_preserve_protocol(bool preserve_protocol) { |
- impl_->set_preserve_protocol(preserve_protocol); |
-} |
- |
-CString CupRequest::user_agent() const { |
- return impl_->user_agent(); |
-} |
- |
-void CupRequest::set_user_agent(const CString& user_agent) { |
- impl_->set_user_agent(user_agent); |
-} |
- |
-void CupRequest::set_proxy_auth_config(const ProxyAuthConfig& config) { |
- impl_->set_proxy_auth_config(config); |
-} |
- |
-void CupRequest::SetEntropy(const void* data, size_t data_length) { |
- return impl_->SetEntropy(data, data_length); |
-} |
- |
-} // namespace omaha |
- |