From 42d7c0218dc58679cebee0a2cd18dcb00a85dfbc Mon Sep 17 00:00:00 2001 From: "stoyan@chromium.org" Date: Fri, 20 Nov 2009 22:44:58 +0000 Subject: Launch COM server IE as low integrity process on Vista. Review URL: http://codereview.chromium.org/402089 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32699 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome_frame/test/chrome_frame_test_utils.cc | 88 ++++++++++++++++++++++++++++ chrome_frame/test/chrome_frame_test_utils.h | 15 ++++- chrome_frame/test/chrome_frame_unittests.cc | 53 +++++++++-------- 3 files changed, 130 insertions(+), 26 deletions(-) (limited to 'chrome_frame/test') diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc index cb59615..2cce441 100644 --- a/chrome_frame/test/chrome_frame_test_utils.cc +++ b/chrome_frame/test/chrome_frame_test_utils.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "base/message_loop.h" #include "base/registry.h" // to find IE and firefox @@ -533,4 +534,91 @@ HWND GetChromeRendererWindow() { return chrome_window; } + +LowIntegrityToken::LowIntegrityToken() : impersonated_(false) { +} + +LowIntegrityToken::~LowIntegrityToken() { + RevertToSelf(); +} + +BOOL LowIntegrityToken::RevertToSelf() { + BOOL ok = TRUE; + if (impersonated_) { + DCHECK(IsImpersonated()); + ok = ::RevertToSelf(); + if (ok) + impersonated_ = false; + } + + return ok; +} + +BOOL LowIntegrityToken::Impersonate() { + DCHECK(!impersonated_); + DCHECK(!IsImpersonated()); + HANDLE process_token_handle = NULL; + BOOL ok = ::OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, + &process_token_handle); + if (!ok) { + DLOG(ERROR) << "::OpenProcessToken failed: " << GetLastError(); + return ok; + } + + ScopedHandle process_token(process_token_handle); + // Create impersonation low integrity token. + HANDLE impersonation_token_handle = NULL; + ok = ::DuplicateTokenEx(process_token, + TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, NULL, + SecurityImpersonation, TokenImpersonation, &impersonation_token_handle); + if (!ok) { + DLOG(ERROR) << "::DuplicateTokenEx failed: " << GetLastError(); + return ok; + } + + // TODO: sandbox/src/restricted_token_utils.cc has SetTokenIntegrityLevel + // function already. + ScopedHandle impersonation_token(impersonation_token_handle); + PSID integrity_sid = NULL; + TOKEN_MANDATORY_LABEL tml = {0}; + ok = ::ConvertStringSidToSid(SDDL_ML_LOW, &integrity_sid); + if (!ok) { + DLOG(ERROR) << "::ConvertStringSidToSid failed: " << GetLastError(); + return ok; + } + + tml.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED; + tml.Label.Sid = integrity_sid; + ok = ::SetTokenInformation(impersonation_token, TokenIntegrityLevel, + &tml, sizeof(tml) + ::GetLengthSid(integrity_sid)); + ::LocalFree(integrity_sid); + if (!ok) { + DLOG(ERROR) << "::SetTokenInformation failed: " << GetLastError(); + return ok; + } + + // Switch current thread to low integrity. + ok = ::ImpersonateLoggedOnUser(impersonation_token); + if (ok) { + impersonated_ = true; + } else { + DLOG(ERROR) << "::ImpersonateLoggedOnUser failed: " << GetLastError(); + } + + return ok; +} + +bool LowIntegrityToken::IsImpersonated() { + HANDLE token = NULL; + if (!::OpenThreadToken(::GetCurrentThread(), 0, false, &token) && + ::GetLastError() != ERROR_NO_TOKEN) { + return true; + } + + if (token) + ::CloseHandle(token); + + return false; +} + } // namespace chrome_frame_test diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h index 26da481..2947539 100644 --- a/chrome_frame/test/chrome_frame_test_utils.h +++ b/chrome_frame/test/chrome_frame_test_utils.h @@ -77,6 +77,19 @@ void SendInputToWindow(HWND window, const std::string& input_string); // window. void SetKeyboardFocusToWindow(HWND window, int x, int y); +// Temporarily impersonate the current thread to low integrity for the lifetime +// of the object. Destructor will automatically revert integrity level. +class LowIntegrityToken { + public: + LowIntegrityToken(); + ~LowIntegrityToken(); + BOOL Impersonate(); + BOOL RevertToSelf(); + protected: + static bool IsImpersonated(); + bool impersonated_; +}; + } // namespace chrome_frame_test -#endif // CHROME_FRAME_CHROMETAB_UNITTESTS_CF_TEST_UTILS_H_ +#endif // CHROME_FRAME_TEST_CHROME_FRAME_TEST_UTILS_H_ diff --git a/chrome_frame/test/chrome_frame_unittests.cc b/chrome_frame/test/chrome_frame_unittests.cc index 1f2340d..225eda8 100644 --- a/chrome_frame/test/chrome_frame_unittests.cc +++ b/chrome_frame/test/chrome_frame_unittests.cc @@ -15,7 +15,7 @@ #include "base/file_util.h" #include "base/scoped_bstr_win.h" #include "base/scoped_variant_win.h" -#include "base/sys_info.h" +#include "base/win_util.h" #include "gmock/gmock.h" #include "net/url_request/url_request_unittest.h" #include "chrome_frame/test/chrome_frame_unittests.h" @@ -1193,15 +1193,27 @@ HRESULT LaunchIEAsComServer(IWebBrowser2** web_browser) { if (!web_browser) return E_INVALIDARG; - ScopedComPtr web_browser2; - HRESULT hr = CoCreateInstance( - CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, - reinterpret_cast(web_browser2.Receive())); - - if (SUCCEEDED(hr)) { - *web_browser = web_browser2.Detach(); + HRESULT hr = S_OK; + chrome_frame_test::LowIntegrityToken token; + if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) { + // Create medium integrity browser that will launch IE broker. + ScopedComPtr medium_integrity_browser; + hr = medium_integrity_browser.CreateInstance(CLSID_InternetExplorer, NULL, + CLSCTX_LOCAL_SERVER); + if (FAILED(hr)) + return hr; + medium_integrity_browser->Quit(); + // Broker remains alive. + if (!token.Impersonate()) { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } } + hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL, + CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING, IID_IWebBrowser2, + reinterpret_cast(web_browser)); + // ~LowIntegrityToken() will switch integrity back to medium. return hr; } @@ -1245,24 +1257,15 @@ HRESULT WebBrowserEventSink::OnMessageInternal(const VARIANT* param) { HRESULT WebBrowserEventSink::LaunchIEAndNavigate( const std::wstring& navigate_url) { - int major_version = 0; - int minor_version = 0; - int bugfix_version = 0; - - base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, - &bugfix_version); - if (major_version > 5) { - DLOG(INFO) << __FUNCTION__ << " Not running test on Windows version: " - << major_version; - return S_FALSE; + HRESULT hr = LaunchIEAsComServer(web_browser2_.Receive()); + EXPECT_EQ(S_OK, hr); + if (hr == S_OK) { + web_browser2_->put_Visible(VARIANT_TRUE); + hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); + EXPECT_TRUE(hr == S_OK); + hr = Navigate(navigate_url); } - - EXPECT_TRUE(S_OK == LaunchIEAsComServer(web_browser2_.Receive())); - web_browser2_->put_Visible(VARIANT_TRUE); - - HRESULT hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2); - EXPECT_TRUE(hr == S_OK); - return Navigate(navigate_url); + return hr; } HRESULT WebBrowserEventSink::Navigate(const std::wstring& navigate_url) { -- cgit v1.1