Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Unified Diff: recovery/client/google_update_recovery.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « recovery/client/google_update_recovery.h ('k') | recovery/client/google_update_recovery_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: recovery/client/google_update_recovery.cc
diff --git a/recovery/client/google_update_recovery.cc b/recovery/client/google_update_recovery.cc
deleted file mode 100644
index 93a7fa8052bf4491e02aea36e4e888560d32a9de..0000000000000000000000000000000000000000
--- a/recovery/client/google_update_recovery.cc
+++ /dev/null
@@ -1,626 +0,0 @@
-// Copyright 2007-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.
-// ========================================================================
-
-//
-// Implementation of the Google Update recovery mechanism to be included in
-// Google apps.
-
-#include "omaha/recovery/client/google_update_recovery.h"
-#include <shellapi.h>
-#include <wininet.h>
-#include <atlstr.h>
-#include "omaha/base/const_addresses.h"
-#include "omaha/base/signaturevalidator.h"
-#include "omaha/common/const_group_policy.h"
-#include "omaha/third_party/smartany/scoped_any.h"
-
-namespace omaha {
-
-namespace {
-
-const int kRollbackWindowDays = 100;
-
-const TCHAR* const kMachineRepairArgs = _T("/recover /machine");
-const TCHAR* const kUserRepairArgs = _T("/recover");
-
-// TODO(omaha): Add a Code Red lib version that is manually updated when
-// we check in the lib.
-const TCHAR* const kQueryStringFormat =
- _T("?appid=%s&appversion=%s&applang=%s&machine=%u")
- _T("&version=%s&osversion=%s&servicepack=%s");
-
-// Information about where to obtain Omaha info.
-// This must never change in Omaha.
-const TCHAR* const kRegValueProductVersion = _T("pv");
-const TCHAR* const kRelativeGoopdateRegPath = _T("Software\\Google\\Update\\");
-const TCHAR* const kRelativeClientsGoopdateRegPath =
- _T("Software\\Google\\Update\\Clients\\")
- _T("{430FD4D0-B729-4F61-AA34-91526481799D}");
-
-// The UpdateDev registry value to override the Code Red url.
-const TCHAR* const kRegValueNameCodeRedUrl = _T("CodeRedUrl");
-
-// Starts another process via ::CreateProcess.
-HRESULT StartProcess(const TCHAR* process_name, TCHAR* command_line) {
- if (!process_name && !command_line) {
- return E_INVALIDARG;
- }
-
- PROCESS_INFORMATION pi = {0};
- STARTUPINFO si = {sizeof(si), 0};
-
- // Feedback cursor is off while the process is starting.
- si.dwFlags = STARTF_FORCEOFFFEEDBACK;
-
- BOOL success = ::CreateProcess(
- process_name, // Module name
- command_line, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- FALSE, // Set handle inheritance to FALSE
- 0, // No creation flags
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &si, // Pointer to STARTUPINFO structure
- &pi); // Pointer to PROCESS_INFORMATION structure
-
- if (!success) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- ::CloseHandle(pi.hProcess);
- ::CloseHandle(pi.hThread);
-
- return S_OK;
-}
-
-// Check if a string starts with another string. Case-sensitive.
-bool StringStartsWith(const TCHAR *str, const TCHAR *start_str) {
- if (!start_str || !str) {
- return false;
- }
-
- while (0 != *str) {
- // Check for matching characters
- TCHAR c1 = *str;
- TCHAR c2 = *start_str;
-
- // Reached the end of start_str?
- if (0 == c2)
- return true;
-
- if (c1 != c2)
- return false;
-
- ++str;
- ++start_str;
- }
-
- // If str is shorter than start_str, no match. If equal size, match.
- return 0 == *start_str;
-}
-
-// Escape and unescape strings (shlwapi-based implementation).
-// The intended usage for these APIs is escaping strings to make up
-// URLs, for example building query strings.
-//
-// Pass false to the flag segment_only to escape the url. This will not
-// cause the conversion of the # (%23), ? (%3F), and / (%2F) characters.
-
-// Characters that must be encoded include any characters that have no
-// corresponding graphic character in the US-ASCII coded character
-// set (hexadecimal 80-FF, which are not used in the US-ASCII coded character
-// set, and hexadecimal 00-1F and 7F, which are control characters),
-// blank spaces, "%" (which is used to encode other characters),
-// and unsafe characters (<, >, ", #, {, }, |, \, ^, ~, [, ], and ').
-//
-// The input and output strings can't be longer than INTERNET_MAX_URL_LENGTH
-
-HRESULT StringEscape(const CString& str_in,
- bool segment_only,
- CString* escaped_string) {
- if (!escaped_string) {
- return E_INVALIDARG;
- }
-
- DWORD buf_len = INTERNET_MAX_URL_LENGTH + 1;
- HRESULT hr = ::UrlEscape(str_in,
- escaped_string->GetBufferSetLength(buf_len),
- &buf_len,
- segment_only ?
- URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY :
- URL_ESCAPE_PERCENT);
- if (SUCCEEDED(hr)) {
- escaped_string->ReleaseBuffer();
- }
- return hr;
-}
-
-// Gets the temporary files directory for the current user.
-// The directory returned may not exist.
-// The returned path ends with a '\'.
-// Fails if the path is longer than MAX_PATH.
-HRESULT GetTempDir(CString* temp_path) {
- if (!temp_path) {
- return E_INVALIDARG;
- }
-
- temp_path->Empty();
-
- TCHAR buffer[MAX_PATH] = {0};
- DWORD num_chars = ::GetTempPath(MAX_PATH, buffer);
- if (!num_chars) {
- return HRESULT_FROM_WIN32(::GetLastError());
- } else if (num_chars >= MAX_PATH) {
- return E_FAIL;
- }
-
- *temp_path = buffer;
- return S_OK;
-}
-
-// Creates the specified directory.
-HRESULT CreateDir(const CString& dir) {
- if (!::CreateDirectory(dir, NULL)) {
- DWORD error = ::GetLastError();
- if (ERROR_FILE_EXISTS != error && ERROR_ALREADY_EXISTS != error) {
- return HRESULT_FROM_WIN32(error);
- }
- }
- return S_OK;
-}
-
-HRESULT GetAndCreateTempDir(CString* temp_path) {
- if (!temp_path) {
- return E_INVALIDARG;
- }
-
- HRESULT hr = GetTempDir(temp_path);
- if (FAILED(hr)) {
- return hr;
- }
- if (temp_path->IsEmpty()) {
- return E_FAIL;
- }
-
- // Create this dir if it doesn't already exist.
- return CreateDir(*temp_path);
-}
-
-
-// Create a unique temporary file and returns the full path.
-HRESULT CreateUniqueTempFile(const CString& user_temp_dir,
- CString* unique_temp_file_path) {
- if (user_temp_dir.IsEmpty() || !unique_temp_file_path) {
- return E_INVALIDARG;
- }
-
- TCHAR unique_temp_filename[MAX_PATH] = {0};
- if (!::GetTempFileName(user_temp_dir,
- _T("GUR"), // prefix
- 0, // form a unique filename
- unique_temp_filename)) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- *unique_temp_file_path = unique_temp_filename;
- if (unique_temp_file_path->IsEmpty()) {
- return E_FAIL;
- }
-
- return S_OK;
-}
-
-// Obtains the OS version and service pack.
-HRESULT GetOSInfo(CString* os_version, CString* service_pack) {
- if (!os_version || !service_pack) {
- return E_INVALIDARG;
- }
-
- OSVERSIONINFO os_version_info = { 0 };
- os_version_info.dwOSVersionInfoSize = sizeof(os_version_info);
- if (!::GetVersionEx(&os_version_info)) {
- HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
- return hr;
- } else {
- os_version->Format(_T("%d.%d"),
- os_version_info.dwMajorVersion,
- os_version_info.dwMinorVersion);
- *service_pack = os_version_info.szCSDVersion;
- }
- return S_OK;
-}
-
-// Reads the specified string value from the specified registry key.
-// Only supports value types REG_SZ and REG_EXPAND_SZ.
-// REG_EXPAND_SZ strings are not expanded.
-HRESULT GetRegStringValue(bool is_machine_key,
- const CString& relative_key_path,
- const CString& value_name,
- CString* value) {
- if (!value) {
- return E_INVALIDARG;
- }
-
- value->Empty();
- HKEY root_key = is_machine_key ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- HKEY key = NULL;
- LONG res = ::RegOpenKeyEx(root_key, relative_key_path, 0, KEY_READ, &key);
- if (res != ERROR_SUCCESS) {
- return HRESULT_FROM_WIN32(res);
- }
-
- // First get the size of the string buffer.
- DWORD type = 0;
- DWORD byte_count = 0;
- res = ::RegQueryValueEx(key, value_name, NULL, &type, NULL, &byte_count);
- if (ERROR_SUCCESS != res) {
- ::RegCloseKey(key);
- return HRESULT_FROM_WIN32(res);
- }
- if ((type != REG_SZ && type != REG_EXPAND_SZ) || (0 == byte_count)) {
- ::RegCloseKey(key);
- return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
- }
-
- CString local_value;
- // GetBuffer throws when not able to allocate the requested buffer.
- TCHAR* buffer = local_value.GetBuffer(byte_count / sizeof(TCHAR));
- res = ::RegQueryValueEx(key,
- value_name,
- NULL,
- NULL,
- reinterpret_cast<BYTE*>(buffer),
- &byte_count);
- ::RegCloseKey(key);
- if (ERROR_SUCCESS == res) {
- local_value.ReleaseBufferSetLength(byte_count / sizeof(TCHAR));
- *value = local_value;
- }
-
- return HRESULT_FROM_WIN32(res);
-}
-
-// Reads the specified DWORD value from the specified registry key.
-// Only supports value types REG_DWORD.
-// Assumes DWORD is sufficient buffer, which must be true for valid value type.
-HRESULT GetRegDwordValue(bool is_machine_key,
- const CString& relative_key_path,
- const CString& value_name,
- DWORD* value) {
- if (!value) {
- return E_INVALIDARG;
- }
-
- HKEY root_key = is_machine_key ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- HKEY key = NULL;
- LONG res = ::RegOpenKeyEx(root_key, relative_key_path, 0, KEY_READ, &key);
- if (res != ERROR_SUCCESS) {
- return HRESULT_FROM_WIN32(res);
- }
-
- DWORD type = 0;
- DWORD byte_count = sizeof(*value);
- res = ::RegQueryValueEx(key,
- value_name,
- NULL,
- &type,
- reinterpret_cast<BYTE*>(value),
- &byte_count);
- ::RegCloseKey(key);
- if (ERROR_SUCCESS != res) {
- return HRESULT_FROM_WIN32(res);
- }
- if ((type != REG_DWORD) || (0 == byte_count)) {
- return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
- }
-
- return S_OK;
-}
-
-// Obtains information about the current Omaha installation.
-// Attempts to obtain as much information as possible even if errors occur.
-// Therefore, return values of GetRegStringValue are ignored.
-HRESULT GetOmahaInformation(bool is_machine_app,
- CString* omaha_version) {
- if (!omaha_version) {
- return E_INVALIDARG;
- }
-
- if (FAILED(GetRegStringValue(is_machine_app,
- kRelativeClientsGoopdateRegPath,
- kRegValueProductVersion,
- omaha_version))) {
- *omaha_version = _T("0.0.0.0");
- }
-
- return S_OK;
-}
-
-// Builds the query portion of the recovery url.
-// This method obtains values necessary to build the query that are not provided
-// as parameters.
-// Attempts to build with as much information as possible even if errors occur.
-HRESULT BuildUrlQueryPortion(const CString& app_guid,
- const CString& app_version,
- const CString& app_language,
- bool is_machine_app,
- CString* query) {
- if (!query) {
- return E_INVALIDARG;
- }
-
- CString omaha_version;
- GetOmahaInformation(is_machine_app, &omaha_version);
-
- CString os_version;
- CString os_service_pack;
- GetOSInfo(&os_version, &os_service_pack);
-
- // All parameters must be escaped individually before building the query.
- CString app_guid_escaped;
- CString app_version_escaped;
- CString app_language_escaped;
- CString omaha_version_escaped;
- CString os_version_escaped;
- CString os_service_pack_escaped;
- StringEscape(app_guid, true, &app_guid_escaped);
- StringEscape(app_version, true, &app_version_escaped);
- StringEscape(app_language, true, &app_language_escaped);
- StringEscape(omaha_version, true, &omaha_version_escaped);
- StringEscape(os_version, true, &os_version_escaped);
- StringEscape(os_service_pack, true, &os_service_pack_escaped);
-
- query->Format(kQueryStringFormat,
- app_guid_escaped,
- app_version_escaped,
- app_language_escaped,
- is_machine_app ? 1 : 0,
- omaha_version_escaped,
- os_version_escaped,
- os_service_pack_escaped);
-
- return S_OK;
-}
-
-// Returns the full path to save the downloaded file to.
-// The path is based on a unique temporary filename to avoid a conflict
-// between multiple apps downloading to the same location.
-// The path to this file is also returned. The caller is responsible for
-// deleting the temporary file after using the download target path.
-// If it cannot create the unique directory, it attempts to use the user's
-// temporary directory and a constant filename.
-HRESULT GetDownloadTargetPath(CString* download_target_path,
- CString* temp_file_path) {
- if (!download_target_path || !temp_file_path) {
- return E_INVALIDARG;
- }
-
- CString user_temp_dir;
- HRESULT hr = GetAndCreateTempDir(&user_temp_dir);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = CreateUniqueTempFile(user_temp_dir, temp_file_path);
- if (SUCCEEDED(hr) && !temp_file_path->IsEmpty()) {
- *download_target_path = *temp_file_path;
- // Ignore the return value. A .tmp filename is better than none.
- download_target_path->Replace(_T(".tmp"), _T(".exe"));
- } else {
- // Try a static filename in the temp directory as a fallback.
- *download_target_path = user_temp_dir + _T("GoogleUpdateSetup.exe");
- *temp_file_path = _T("");
- }
-
- return S_OK;
-}
-
-HRESULT DownloadRepairFile(const CString& download_target_path,
- const CString& app_guid,
- const CString& app_version,
- const CString& app_language,
- bool is_machine_app,
- DownloadCallback download_callback,
- void* context) {
- CString query;
- BuildUrlQueryPortion(app_guid,
- app_version,
- app_language,
- is_machine_app,
- &query);
-
- CString url;
- HRESULT hr = GetRegStringValue(true,
- _T("SOFTWARE\\Google\\UpdateDev"),
- kRegValueNameCodeRedUrl,
- &url);
- if (FAILED(hr)) {
- url = omaha::kUrlCodeRedCheck;
- }
-
- url += query;
-
- return download_callback(url, download_target_path, context);
-}
-
-// Makes sure the path is enclosed with double quotation marks.
-void EnclosePath(CString* path) {
- if (path) {
- return;
- }
-
- if (!path->IsEmpty() && path->GetAt(0) != _T('"')) {
- path->Insert(0, _T('"'));
- path->AppendChar(_T('"'));
- }
-}
-
-HRESULT RunRepairFile(const CString& file_path, bool is_machine_app) {
- const TCHAR* repair_file_args = is_machine_app ? kMachineRepairArgs :
- kUserRepairArgs;
-
- CString command_line(file_path);
- EnclosePath(&command_line);
- command_line.AppendChar(_T(' '));
- command_line.Append(repair_file_args);
-
- return StartProcess(NULL, command_line.GetBuffer());
-}
-
-} // namespace
-
-// Verifies the file's integrity and that it is signed by Google.
-// We cannot prevent rollback attacks by using a version because the client
-// may not be able to determine the current version if the files and/or
-// registry entries have been deleted/corrupted.
-// Therefore, we check that the file was signed recently.
-HRESULT VerifyFileSignature(const CString& filename) {
- // Use Authenticode/WinVerifyTrust to verify the file.
- // Allow the revocation check to use the network.
- HRESULT hr = VerifySignature(filename, true);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Verify that there is a Google certificate.
- if (!VerifySigneeIsGoogle(filename)) {
- return CERT_E_CN_NO_MATCH;
- }
-
- // Check that the file was signed recently to limit the window for
- // rollback attacks.
- return VerifyFileSignedWithinDays(filename, kRollbackWindowDays);
-}
-
-// Verifies the file contains the special markup resource for repair files.
-HRESULT VerifyRepairFileMarkup(const CString& filename) {
- const TCHAR* kMarkupResourceName = MAKEINTRESOURCE(1);
- const TCHAR* kMarkupResourceType = _T("GOOGLEUPDATEREPAIR");
- const DWORD kMarkupResourceExpectedValue = 1;
-
- scoped_library module(::LoadLibraryEx(filename, 0, LOAD_LIBRARY_AS_DATAFILE));
- if (!module) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- HRSRC resource(::FindResource(get(module),
- kMarkupResourceName,
- kMarkupResourceType));
- if (!resource) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- if (sizeof(kMarkupResourceExpectedValue) !=
- ::SizeofResource(get(module), resource)) {
- return E_UNEXPECTED;
- }
-
- HGLOBAL loaded_resource(::LoadResource(get(module), resource));
- if (!loaded_resource) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- const DWORD* value = static_cast<DWORD*>(::LockResource(loaded_resource));
- if (!value) {
- return E_HANDLE;
- }
-
- if (kMarkupResourceExpectedValue != *value) {
- return E_UNEXPECTED;
- }
-
- return S_OK;
-}
-
-// Verifies the filename is not UNC name, the file exists, has a valid signature
-// chain, is signed by Google, and contains the special markup resource for
-// repair files.
-HRESULT VerifyIsValidRepairFile(const CString& filename) {
- // Make sure file exists.
- if (!::PathFileExists(filename)) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- HRESULT hr = VerifyFileSignature(filename);
- if (FAILED(hr)) {
- return hr;
- }
-
- return VerifyRepairFileMarkup(filename);
-}
-
-} // namespace omaha
-
-// If a repair file is run, the file will not be deleted until reboot. Delete
-// after reboot will only succeed when executed by an admin or LocalSystem.
-// Returns HRESULT_FROM_WIN32(ERROR_ACCESS_DISABLED_BY_POLICY) if automatic
-// update checks are disabled.
-HRESULT FixGoogleUpdate(const TCHAR* app_guid,
- const TCHAR* app_version,
- const TCHAR* app_language,
- bool is_machine_app,
- DownloadCallback download_callback,
- void* context) {
- if (!app_guid || !app_version || !app_language || !download_callback) {
- return E_INVALIDARG;
- }
-
- DWORD update_check_period_override_minutes(UINT_MAX);
- HRESULT hr = omaha::GetRegDwordValue(
- true,
- GOOPDATE_POLICIES_RELATIVE,
- omaha::kRegValueAutoUpdateCheckPeriodOverrideMinutes,
- &update_check_period_override_minutes);
- if (SUCCEEDED(hr) && (0 == update_check_period_override_minutes)) {
- return HRESULT_FROM_WIN32(ERROR_ACCESS_DISABLED_BY_POLICY);
- }
-
- CString download_target_path;
- CString temp_file_path;
- hr = omaha::GetDownloadTargetPath(&download_target_path, &temp_file_path);
- if (FAILED(hr)) {
- return hr;
- }
- if (download_target_path.IsEmpty()) {
- return E_FAIL;
- }
-
- // After calling DownloadRepairFile, don't return until the repair file and
- // temp file have been deleted.
- hr = omaha::DownloadRepairFile(download_target_path,
- app_guid,
- app_version,
- app_language,
- is_machine_app,
- download_callback,
- context);
-
- if (SUCCEEDED(hr)) {
- hr = omaha::VerifyIsValidRepairFile(download_target_path);
- }
-
- if (FAILED(hr)) {
- ::DeleteFile(download_target_path);
- ::DeleteFile(temp_file_path);
- return hr;
- }
-
- hr = omaha::RunRepairFile(download_target_path, is_machine_app);
- ::MoveFileEx(download_target_path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
- ::DeleteFile(temp_file_path);
-
- return hr;
-}
« no previous file with comments | « recovery/client/google_update_recovery.h ('k') | recovery/client/google_update_recovery_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698