Index: net/proxy_auth.cc |
diff --git a/net/proxy_auth.cc b/net/proxy_auth.cc |
deleted file mode 100644 |
index 96f40a512c66b396af8c37c3c2d6c401000fce59..0000000000000000000000000000000000000000 |
--- a/net/proxy_auth.cc |
+++ /dev/null |
@@ -1,419 +0,0 @@ |
-// Copyright 2008-2009 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. |
-// ======================================================================== |
-#include "omaha/net/proxy_auth.h" |
-#include <atlcom.h> |
-#include <pstore.h> |
-#include <wincred.h> |
-#include <wincrypt.h> |
-#include "omaha/base/commontypes.h" |
-#include "omaha/base/encrypt.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/smart_handle.h" |
-#include "omaha/base/string.h" |
-#include "omaha/base/system_info.h" |
-#include "omaha/goopdate/cred_dialog.h" |
-#include "omaha/third_party/smartany/scoped_any.h" |
- |
-using omaha::encrypt::EncryptData; |
-using omaha::encrypt::DecryptData; |
- |
-namespace omaha { |
- |
-static const GUID kPreIE7CredTypeGuid = { 0x5e7e8100, 0x9138, 0x11d1, |
- { 0x94, 0x5a, 0x00, 0xc0, 0x4f, 0xc3, 0x08, 0xff } }; |
-static const GUID kPreIE7CredSubtypeGuid = { 0 }; |
- |
-#define kIE7CredKey "abe2869f-9b47-4cd9-a358-c22904dba7f7" |
- |
-bool ProxyAuth::IsPromptAllowed() { |
- __mutexScope(lock_); |
- return prompt_cancelled_ < cancel_prompt_threshold_; |
-} |
- |
-void ProxyAuth::PromptCancelled() { |
- __mutexScope(lock_); |
- prompt_cancelled_++; |
-} |
- |
-CString ProxyAuth::ExtractProxy(const CString& proxy_settings, |
- bool isHttps) { |
- if (proxy_settings.IsEmpty()) { |
- NET_LOG(L3, (_T("[ProxyAuth::ExtractProxy][Empty settings"))); |
- return proxy_settings; |
- } |
- |
- int equals_index = String_FindChar(proxy_settings, L'='); |
- if (equals_index >= 0) { |
- const wchar_t* prefix = L"http="; |
- if (isHttps) |
- prefix = L"https="; |
- |
- int prefix_index = String_FindString(proxy_settings, prefix); |
- if (prefix_index == -1) { |
- // fallback to whatever we've got after an equals sign |
- prefix = L"="; |
- prefix_index = equals_index; |
- } |
- |
- int first = prefix_index + lstrlen(prefix); |
- int length = String_FindChar(proxy_settings, L' '); |
- if (length == -1) { |
- return proxy_settings.Mid(first); |
- } else { |
- return proxy_settings.Mid(first, length); |
- } |
- } |
- |
- return proxy_settings; |
-} |
- |
-void ProxyAuth::ConfigureProxyAuth(bool is_machine, |
- uint32 cancel_prompt_threshold) { |
- ASSERT1(cancel_prompt_threshold); |
- |
- proxy_prompt_is_machine_ = is_machine; |
- cancel_prompt_threshold_ = cancel_prompt_threshold; |
-} |
- |
-bool ProxyAuth::PromptUser(const CString& server, |
- const ProxyAuthConfig& proxy_auth_config) { |
- NET_LOG(L3, (_T("[ProxyAuth::PromptUser][%s][%s]"), |
- server, proxy_auth_config.ToString())); |
- |
- CString user; |
- CString pass; |
- |
- HRESULT hr = LaunchCredentialDialog( |
- proxy_prompt_is_machine_, |
- proxy_auth_config.parent_hwnd, |
- server, |
- proxy_auth_config.prompt_caption, |
- &user, |
- &pass); |
- |
- if (SUCCEEDED(hr)) { |
- AddCred(server, user, pass); |
- } else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { |
- PromptCancelled(); |
- } |
- |
- SecureZeroMemory(user.GetBuffer(), user.GetAllocLength() * sizeof(TCHAR)); |
- SecureZeroMemory(pass.GetBuffer(), pass.GetAllocLength() * sizeof(TCHAR)); |
- |
- return SUCCEEDED(hr); |
-} |
- |
-bool ProxyAuth::GetProxyCredentials(bool allow_ui, bool force_ui, |
- const CString& proxy_server, |
- const ProxyAuthConfig& proxy_auth_config, |
- CString* username, CString* password, |
- uint32* auth_scheme) { |
- NET_LOG(L3, (_T("[ProxyAuth::GetProxyCredentials][%d][%s]"), |
- allow_ui, proxy_auth_config.ToString())); |
- |
- CString server(proxy_server); |
- if (server.IsEmpty()) { |
- server = kDefaultProxyServer; |
- } |
- |
- __mutexScope(lock_); |
- int i = -1; |
- if (!force_ui) |
- i = servers_.Find(server); |
- |
- if (i == -1) { |
- if (ReadFromIE7(server) || ReadFromPreIE7(server) || |
- (allow_ui && proxy_auth_config.parent_hwnd && IsPromptAllowed() && |
- PromptUser(server, proxy_auth_config))) { |
- i = servers_.GetSize() - 1; |
- } |
- } |
- |
- if (i >= 0) { |
- ASSERT1(!usernames_[i].IsEmpty() && !passwords_[i].empty()); |
- std::vector<uint8> decrypted_password; |
- HRESULT hr = DecryptData(NULL, |
- 0, |
- &passwords_[i].front(), |
- passwords_[i].size(), |
- &decrypted_password); |
- if (FAILED(hr)) { |
- NET_LOG(LE, (_T("[DecryptData failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- *username = usernames_[i]; |
- *password = reinterpret_cast<TCHAR*>(&decrypted_password.front()); |
- *auth_scheme = auth_schemes_[i]; |
- } |
- |
- NET_LOG(L3, (_T("[ProxyAuth::GetProxyCredentials][%d][%s][%s][%d]"), |
- i, proxy_server, *username, *auth_scheme)); |
- return i >= 0; |
-} |
- |
-static bool ParseCredsFromRawBuffer(const BYTE* buffer, const DWORD bytes, |
- CString* username, CString* password) { |
- ASSERT1(bytes > 0); |
- if (bytes <= 0) |
- return false; |
- |
- const char* ascii_buffer = reinterpret_cast<const char*>(buffer); |
- const unsigned ascii_length = |
- static_cast<const unsigned>(strlen(ascii_buffer)); |
- |
- // The buffer could be ascii or wide characters, so we detect which one it |
- // is and copy the ascii characters to a wide string if necessary |
- const wchar_t* user_pass = NULL; |
- CString temp; |
- if (ascii_length == bytes - 1) { |
- temp = AnsiToWideString(ascii_buffer, ascii_length); |
- user_pass = temp.GetString(); |
- } else { |
- user_pass = reinterpret_cast<const wchar_t*>(buffer); |
- } |
- |
- int colon_pos = String_FindChar(user_pass, L':'); |
- if (colon_pos >= 0) { |
- username->SetString(user_pass, colon_pos); |
- password->SetString(user_pass + colon_pos + 1); |
- } |
- |
- return colon_pos >= 0; |
-} |
- |
-void ProxyAuth::AddCred(const CString& server, const CString& username, |
- const CString& password) { |
- std::vector<uint8> encrypted_password; |
- HRESULT hr = EncryptData(NULL, |
- 0, |
- password, |
- (password.GetLength() + 1) * sizeof(TCHAR), |
- &encrypted_password); |
- if (FAILED(hr)) { |
- NET_LOG(LE, (_T("[EncryptData failed][0x%x]"), hr)); |
- return; |
- } |
- |
- __mutexScope(lock_); |
- int i = servers_.Find(server); |
- if (i == -1) { |
- servers_.Add(server); |
- usernames_.Add(username); |
- passwords_.Add(encrypted_password); |
- auth_schemes_.Add(UNKNOWN_AUTH_SCHEME); |
- } else { |
- usernames_[i] = username; |
- passwords_[i] = encrypted_password; |
- auth_schemes_[i] = UNKNOWN_AUTH_SCHEME; |
- } |
- |
- NET_LOG(L3, (_T("[ProxyAuth::AddCred][%s][%s]"), server, username)); |
-} |
- |
-HRESULT ProxyAuth::SetProxyAuthScheme(const CString& proxy_server, |
- uint32 scheme) { |
- CString server(proxy_server); |
- if (server.IsEmpty()) { |
- server = kDefaultProxyServer; |
- } |
- |
- __mutexScope(lock_); |
- int i = servers_.Find(server); |
- if (i == -1) { |
- NET_LOG(LE, (_T("[ProxyAuth::SetProxyAuthScheme][%s not found]"), server)); |
- return E_INVALIDARG; |
- } |
- |
- auth_schemes_[i] = scheme; |
- NET_LOG(L3, (_T("[ProxyAuth::SetProxyAuthScheme][%s][%s][%d]"), |
- server, usernames_[i], scheme)); |
- return S_OK; |
-} |
- |
-// This approach (the key in particular) comes from a securityfocus posting: |
-// http://www.securityfocus.com/archive/1/458115/30/0/threaded |
-bool ProxyAuth::ReadFromIE7(const CString& server) { |
- scoped_library crypt_lib(::LoadLibrary(L"crypt32.dll")); |
- ASSERT1(crypt_lib); |
- if (!crypt_lib) |
- return false; |
- |
- typedef BOOL (__stdcall *CryptUnprotectData_type)(DATA_BLOB*, LPWSTR*, |
- DATA_BLOB*, PVOID, CRYPTPROTECT_PROMPTSTRUCT*, DWORD, DATA_BLOB*); |
- CryptUnprotectData_type CryptUnprotectData_fn = |
- reinterpret_cast<CryptUnprotectData_type>( |
- GetProcAddress(get(crypt_lib), "CryptUnprotectData")); |
- ASSERT1(CryptUnprotectData_fn); |
- if (!CryptUnprotectData_fn) |
- return false; |
- |
- // Load CredEnumerate and CredFree dynamically because they don't exist on |
- // Win2K and so loading the GoogleDesktopCommon.dll otherwise. |
- scoped_library advapi_lib(::LoadLibrary(L"advapi32.dll")); |
- ASSERT1(advapi_lib); |
- if (!advapi_lib) |
- return false; |
- |
- typedef BOOL (__stdcall *CredEnumerateW_type)(LPCWSTR, DWORD, DWORD*, |
- PCREDENTIAL**); |
- CredEnumerateW_type CredEnumerateW_fn = |
- reinterpret_cast<CredEnumerateW_type>( |
- GetProcAddress(get(advapi_lib), "CredEnumerateW")); |
- ASSERT1(CredEnumerateW_fn || SystemInfo::IsRunningOnW2K()); |
- if (!CredEnumerateW_fn) |
- return false; |
- |
- typedef VOID (__stdcall *CredFree_type)(PVOID); |
- CredFree_type CredFree_fn = reinterpret_cast<CredFree_type>( |
- GetProcAddress(get(advapi_lib), "CredFree")); |
- ASSERT1(CredFree_fn || SystemInfo::IsRunningOnW2K()); |
- if (!CredFree_fn) |
- return false; |
- |
- // Done with dynamically loading methods. CredEnumerate (and CredFree if |
- // we didn't return) will have failed to load on Win2K |
- |
- DATA_BLOB optional_entropy; |
- |
- char key[ARRAYSIZE(kIE7CredKey)] = kIE7CredKey; |
- int16 temp[ARRAYSIZE(key)]; |
- for (int i = 0; i < ARRAYSIZE(key); ++i) |
- temp[i] = static_cast<int16>(key[i] * 4); |
- |
- optional_entropy.pbData = reinterpret_cast<BYTE*>(&temp); |
- optional_entropy.cbData = sizeof(temp); |
- |
- CString target(NOTRANSL(L"Microsoft_WinInet_")); |
- target += server; |
- target += L"*"; |
- |
- DWORD count = 0; |
- CREDENTIAL** credentials = NULL; |
- CString username; |
- CString password; |
- |
- bool found = false; |
- if (CredEnumerateW_fn(target, 0, &count, &credentials)) { |
- for (unsigned i = 0; i < count; ++i) { |
- if (credentials[i]->Type == CRED_TYPE_GENERIC) { |
- DATA_BLOB data_in; |
- DATA_BLOB data_out = { 0 }; |
- data_in.pbData = static_cast<BYTE*>(credentials[i]->CredentialBlob); |
- data_in.cbData = credentials[i]->CredentialBlobSize; |
- |
- if (CryptUnprotectData_fn(&data_in, NULL, &optional_entropy, NULL, NULL, |
- 0, &data_out)) { |
- found = ParseCredsFromRawBuffer(data_out.pbData, data_out.cbData, |
- &username, &password); |
- LocalFree(data_out.pbData); |
- if (found) { |
- AddCred(server, username, password); |
- break; |
- } |
- } |
- } |
- } |
- CredFree_fn(credentials); |
- } |
- |
- return found; |
-} |
- |
-bool ProxyAuth::ReadFromPreIE7(const CString& server) { |
- scoped_library pstore_lib(::LoadLibrary(L"pstorec.dll")); |
- ASSERT1(pstore_lib); |
- if (!pstore_lib) |
- return false; |
- |
- typedef HRESULT (__stdcall *PStoreCreateInstance_type)(IPStore**, |
- PST_PROVIDERID*, void*, DWORD); |
- PStoreCreateInstance_type PStoreCreateInstance_fn = |
- reinterpret_cast<PStoreCreateInstance_type>( |
- GetProcAddress(get(pstore_lib), "PStoreCreateInstance")); |
- ASSERT1(PStoreCreateInstance_fn); |
- if (!PStoreCreateInstance_fn) |
- return false; |
- |
- CString username; |
- CString password; |
- bool found = false; |
- |
- scoped_co_init initializer(COINIT_APARTMENTTHREADED); |
- HRESULT hr = E_FAIL; |
- |
- // The best reference I found about these iterators, especially how to free |
- // the item_name returned by this iterator was a microsoft patent application: |
- // http://www.patentstorm.us/patents/6272631-description.html |
- CComPtr<IPStore> pstore; |
- VERIFY1(SUCCEEDED(hr = PStoreCreateInstance_fn(&pstore, NULL, NULL, 0))); |
- if (SUCCEEDED(hr)) { |
- CComPtr<IEnumPStoreTypes> enum_types; |
- VERIFY1(SUCCEEDED(hr = pstore->EnumTypes(PST_KEY_CURRENT_USER, 0, |
- &enum_types))); |
- if (SUCCEEDED(hr)) { |
- GUID type_guid = { 0 }; |
- // Get the types one at a time |
- while (enum_types->Next(1, &type_guid, NULL) == S_OK) { |
- if (type_guid != kPreIE7CredTypeGuid) |
- continue; |
- |
- CComPtr<IEnumPStoreTypes> enum_subtypes; |
- VERIFY1(SUCCEEDED(hr = pstore->EnumSubtypes(PST_KEY_CURRENT_USER, |
- &type_guid, 0, &enum_subtypes))); |
- if (SUCCEEDED(hr)) { |
- GUID subtype_guid = { 0 }; |
- // Get the subtypes one at a time |
- while (enum_subtypes->Next(1, &subtype_guid, NULL) == S_OK) { |
- if (subtype_guid != kPreIE7CredSubtypeGuid) |
- continue; |
- |
- CComPtr<IEnumPStoreItems> enum_items; |
- VERIFY1(SUCCEEDED(hr = pstore->EnumItems(PST_KEY_CURRENT_USER, |
- &type_guid, &subtype_guid, 0, &enum_items))); |
- if (SUCCEEDED(hr)) { |
- wchar_t* item_name = NULL; |
- // Get the items one at a time |
- while (enum_items->Next(1, &item_name, NULL) == S_OK) { |
- DWORD data_length = 0; |
- byte* data = NULL; |
- |
- VERIFY1(SUCCEEDED(hr = pstore->ReadItem(PST_KEY_CURRENT_USER, |
- &type_guid, &subtype_guid, item_name, &data_length, &data, |
- NULL, 0))); |
- if (SUCCEEDED(hr)) { |
- found = ParseCredsFromRawBuffer(data, data_length, |
- &username, &password); |
- CoTaskMemFree(data); |
- } |
- |
- CoTaskMemFree(item_name); |
- if (found) { |
- AddCred(server, username, password); |
- break; |
- } |
- } // end enum_items loop |
- } |
- } // end enum_subtypes loop |
- } |
- } // end enum_types loop |
- } |
- } |
- |
- return found; |
-} |
- |
-} // namespace omaha |
- |