Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // chrome_tab.cc : Implementation of DLL Exports. | 5 // chrome_tab.cc : Implementation of DLL Exports. |
| 6 #include "base/at_exit.h" | 6 #include "base/at_exit.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/file_version_info.h" | 9 #include "base/file_version_info.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/registry.h" | 12 #include "base/registry.h" |
| 13 #include "base/string_piece.h" | 13 #include "base/string_piece.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
| 16 #include "base/win_util.h" | |
| 16 #include "chrome/common/chrome_constants.h" | 17 #include "chrome/common/chrome_constants.h" |
| 17 #include "grit/chrome_frame_resources.h" | 18 #include "grit/chrome_frame_resources.h" |
| 18 #include "chrome_frame/bho.h" | 19 #include "chrome_frame/bho.h" |
| 19 #include "chrome_frame/chrome_frame_automation.h" | 20 #include "chrome_frame/chrome_frame_automation.h" |
| 20 #include "chrome_frame/chrome_launcher.h" | 21 #include "chrome_frame/chrome_launcher.h" |
| 21 #include "chrome_frame/crash_report.h" | 22 #include "chrome_frame/crash_report.h" |
| 22 #include "chrome_frame/resource.h" | 23 #include "chrome_frame/resource.h" |
| 23 #include "chrome_frame/utils.h" | 24 #include "chrome_frame/utils.h" |
| 24 | 25 |
| 25 // Include without path to make GYP build see it. | 26 // Include without path to make GYP build see it. |
| 26 #include "chrome_tab.h" // NOLINT | 27 #include "chrome_tab.h" // NOLINT |
| 28 #include <atlsecurity.h> | |
| 27 | 29 |
| 28 static const wchar_t kBhoRegistryPath[] = | 30 static const wchar_t kBhoRegistryPath[] = |
| 29 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" | 31 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" |
| 30 L"\\Browser Helper Objects"; | 32 L"\\Browser Helper Objects"; |
| 31 | 33 |
| 34 const wchar_t kInternetSettings[] = | |
| 35 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; | |
| 36 | |
| 32 const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; | 37 const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; |
| 33 | 38 |
| 34 class ChromeTabModule | 39 class ChromeTabModule |
| 35 : public AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > { | 40 : public AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > { |
| 36 public: | 41 public: |
| 37 typedef AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > ParentClass; | 42 typedef AtlPerUserModule<CAtlDllModuleT<ChromeTabModule> > ParentClass; |
| 38 | 43 |
| 39 DECLARE_LIBID(LIBID_ChromeTabLib) | 44 DECLARE_LIBID(LIBID_ChromeTabLib) |
| 40 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CHROMETAB, | 45 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CHROMETAB, |
| 41 "{FD9B1B31-F4D8-436A-8F4F-D3C2E36733D3}") | 46 "{FD9B1B31-F4D8-436A-8F4F-D3C2E36733D3}") |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 DCHECK(SUCCEEDED(hr)); | 104 DCHECK(SUCCEEDED(hr)); |
| 100 } | 105 } |
| 101 | 106 |
| 102 return hr; | 107 return hr; |
| 103 } | 108 } |
| 104 }; | 109 }; |
| 105 | 110 |
| 106 ChromeTabModule _AtlModule; | 111 ChromeTabModule _AtlModule; |
| 107 | 112 |
| 108 base::AtExitManager* g_exit_manager = NULL; | 113 base::AtExitManager* g_exit_manager = NULL; |
| 114 bool RegisterSecuredMimeHandler(bool enable); // forward | |
| 109 | 115 |
| 110 // DLL Entry Point | 116 // DLL Entry Point |
| 111 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, | 117 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, |
| 112 DWORD reason, | 118 DWORD reason, |
| 113 LPVOID reserved) { | 119 LPVOID reserved) { |
| 114 UNREFERENCED_PARAMETER(instance); | 120 UNREFERENCED_PARAMETER(instance); |
| 115 if (reason == DLL_PROCESS_ATTACH) { | 121 if (reason == DLL_PROCESS_ATTACH) { |
| 116 #ifndef NDEBUG | 122 #ifndef NDEBUG |
| 117 // Silence traces from the ATL registrar to reduce the log noise. | 123 // Silence traces from the ATL registrar to reduce the log noise. |
| 118 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0, | 124 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 if (ieframe_module) { | 174 if (ieframe_module) { |
| 169 typedef HRESULT (__stdcall *IERefreshPolicy)(); | 175 typedef HRESULT (__stdcall *IERefreshPolicy)(); |
| 170 IERefreshPolicy ie_refresh_policy = reinterpret_cast<IERefreshPolicy>( | 176 IERefreshPolicy ie_refresh_policy = reinterpret_cast<IERefreshPolicy>( |
| 171 GetProcAddress(ieframe_module, kIERefreshPolicy)); | 177 GetProcAddress(ieframe_module, kIERefreshPolicy)); |
| 172 | 178 |
| 173 if (ie_refresh_policy) { | 179 if (ie_refresh_policy) { |
| 174 hr = ie_refresh_policy(); | 180 hr = ie_refresh_policy(); |
| 175 } else { | 181 } else { |
| 176 hr = HRESULT_FROM_WIN32(GetLastError()); | 182 hr = HRESULT_FROM_WIN32(GetLastError()); |
| 177 } | 183 } |
| 178 | 184 |
| 179 FreeLibrary(ieframe_module); | 185 FreeLibrary(ieframe_module); |
| 180 } else { | 186 } else { |
| 181 hr = HRESULT_FROM_WIN32(GetLastError()); | 187 hr = HRESULT_FROM_WIN32(GetLastError()); |
| 182 } | 188 } |
| 183 | 189 |
| 184 return hr; | 190 return hr; |
| 185 } | 191 } |
| 186 | 192 |
| 187 HRESULT RegisterChromeTabBHO() { | 193 HRESULT RegisterChromeTabBHO() { |
| 188 RegKey ie_bho_key; | 194 RegKey ie_bho_key; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 // Muck with the Omaha configuration so that we don't get updated by non-CF | 271 // Muck with the Omaha configuration so that we don't get updated by non-CF |
| 266 // Google Chrome builds. | 272 // Google Chrome builds. |
| 267 UtilUpdateOmahaConfig(true); | 273 UtilUpdateOmahaConfig(true); |
| 268 #endif | 274 #endif |
| 269 | 275 |
| 270 if (SUCCEEDED(hr)) { | 276 if (SUCCEEDED(hr)) { |
| 271 // Best effort attempt to register the BHO. At this point we silently | 277 // Best effort attempt to register the BHO. At this point we silently |
| 272 // ignore any errors during registration. There are some traces emitted | 278 // ignore any errors during registration. There are some traces emitted |
| 273 // to the debug log. | 279 // to the debug log. |
| 274 RegisterChromeTabBHO(); | 280 RegisterChromeTabBHO(); |
| 281 if (!RegisterSecuredMimeHandler(true)) | |
| 282 hr = E_FAIL; | |
| 275 } | 283 } |
| 276 | 284 |
| 277 return hr; | 285 return hr; |
| 278 } | 286 } |
| 279 | 287 |
| 280 // DllUnregisterServer - Removes entries from the system registry | 288 // DllUnregisterServer - Removes entries from the system registry |
| 281 STDAPI DllUnregisterServer() { | 289 STDAPI DllUnregisterServer() { |
| 282 HRESULT hr = _AtlModule.DllUnregisterServer(TRUE); | 290 HRESULT hr = _AtlModule.DllUnregisterServer(TRUE); |
| 283 | 291 |
| 284 #ifdef GOOGLE_CHROME_BUILD | 292 #ifdef GOOGLE_CHROME_BUILD |
| 285 // Undo any prior mucking with the Omaha config. | 293 // Undo any prior mucking with the Omaha config. |
| 286 UtilUpdateOmahaConfig(false); | 294 UtilUpdateOmahaConfig(false); |
| 287 #endif | 295 #endif |
| 288 | 296 |
| 289 if (SUCCEEDED(hr)) { | 297 if (SUCCEEDED(hr)) { |
| 290 // Best effort attempt to unregister the BHO. At this point we silently | 298 // Best effort attempt to unregister the BHO. At this point we silently |
| 291 // ignore any errors during unregistration. There are some traces emitted | 299 // ignore any errors during unregistration. There are some traces emitted |
| 292 // to the debug log. | 300 // to the debug log. |
| 293 UnregisterChromeTabBHO(); | 301 UnregisterChromeTabBHO(); |
| 302 if (!RegisterSecuredMimeHandler(false)) | |
| 303 hr = E_FAIL; | |
| 294 } | 304 } |
| 295 return hr; | 305 return hr; |
| 296 } | 306 } |
| 297 | 307 |
| 298 STDAPI RegisterNPAPIPlugin() { | 308 STDAPI RegisterNPAPIPlugin() { |
| 299 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, | 309 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, |
| 300 TRUE); | 310 TRUE); |
| 301 return hr; | 311 return hr; |
| 302 } | 312 } |
| 303 | 313 |
| 304 STDAPI UnregisterNPAPIPlugin() { | 314 STDAPI UnregisterNPAPIPlugin() { |
| 305 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, | 315 HRESULT hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, |
| 306 FALSE); | 316 FALSE); |
| 307 return hr; | 317 return hr; |
| 308 } | 318 } |
| 319 | |
| 320 class SecurityDescBackup { | |
| 321 public: | |
| 322 explicit SecurityDescBackup(const std::wstring& backup_key) | |
| 323 : backup_key_name_(backup_key) {} | |
| 324 ~SecurityDescBackup() {} | |
| 325 | |
| 326 // Save given security descriptor to the backup key. | |
| 327 bool SaveSecurity(const CSecurityDesc& sd) { | |
| 328 CString str; | |
| 329 if (!sd.ToString(&str)) | |
| 330 return false; | |
| 331 | |
| 332 RegKey backup_key(HKEY_LOCAL_MACHINE, backup_key_name_.c_str(), | |
| 333 KEY_READ | KEY_WRITE); | |
| 334 if (backup_key.Valid()) { | |
| 335 return backup_key.WriteValue(NULL, str.GetString()); | |
| 336 } | |
| 337 | |
| 338 return false; | |
| 339 } | |
| 340 | |
| 341 // Restore security descriptor from backup key to given key name. | |
| 342 bool RestoreSecurity(const wchar_t* key_name) { | |
| 343 std::wstring sddl; | |
| 344 if (!ReadBackupKey(&sddl)) | |
| 345 return false; | |
| 346 | |
| 347 // Create security descriptor from string. | |
| 348 CSecurityDesc sd; | |
| 349 if (!sd.FromString(sddl.c_str())) | |
| 350 return false; | |
| 351 | |
| 352 bool result = true; | |
| 353 // Restore DACL and Owner of the key from saved security descriptor. | |
| 354 CDacl dacl; | |
| 355 CSid owner; | |
| 356 sd.GetDacl(&dacl); | |
| 357 sd.GetOwner(&owner); | |
| 358 | |
| 359 DWORD error = ::SetNamedSecurityInfo(const_cast<wchar_t*>(key_name), | |
| 360 SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, | |
| 361 const_cast<SID*>(owner.GetPSID()), NULL, | |
| 362 const_cast<ACL*>(dacl.GetPACL()), NULL); | |
| 363 | |
| 364 DeleteBackupKey(); | |
| 365 return (error == ERROR_SUCCESS); | |
| 366 } | |
| 367 | |
| 368 private: | |
| 369 // Read SDDL string from backup key | |
| 370 bool ReadBackupKey(std::wstring* sddl) { | |
| 371 RegKey backup_key(HKEY_LOCAL_MACHINE, backup_key_name_.c_str(), KEY_READ); | |
| 372 if (!backup_key.Valid()) | |
| 373 return false; | |
| 374 | |
| 375 // If the key exists, something bad happened. | |
|
amit
2009/10/06 23:20:55
I think we expect the key to be valid here, right?
| |
| 376 DWORD len = 0; | |
| 377 DWORD reg_type = REG_NONE; | |
| 378 if (!backup_key.ReadValue(NULL, NULL, &len, ®_type)) | |
| 379 return false; | |
| 380 | |
| 381 if (reg_type != REG_SZ) | |
| 382 return false; | |
| 383 | |
| 384 size_t wchar_count = 1 + len / sizeof(wchar_t); | |
| 385 if (!backup_key.ReadValue(NULL, WriteInto(sddl, wchar_count), &len, | |
| 386 ®_type)) { | |
| 387 return false; | |
| 388 } | |
| 389 | |
| 390 return true; | |
| 391 } | |
| 392 | |
| 393 void DeleteBackupKey() { | |
| 394 ::RegDeleteKey(HKEY_LOCAL_MACHINE, backup_key_name_.c_str()); | |
| 395 } | |
| 396 | |
| 397 std::wstring backup_key_name_; | |
| 398 }; | |
| 399 | |
| 400 struct TokenWithPrivileges { | |
| 401 TokenWithPrivileges() { | |
| 402 token_.GetEffectiveToken(TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY); | |
| 403 token_.GetUser(&user_); | |
| 404 } | |
| 405 | |
| 406 ~TokenWithPrivileges() { | |
| 407 token_.EnableDisablePrivileges(take_ownership_); | |
| 408 token_.EnableDisablePrivileges(restore_); | |
| 409 } | |
| 410 | |
| 411 bool EnablePrivileges() { | |
| 412 if (take_ownership_.GetCount() == 0) | |
| 413 if (!token_.EnablePrivilege(L"SeTakeOwnershipPrivilege", | |
| 414 &take_ownership_)) | |
| 415 return false; | |
| 416 | |
| 417 if (restore_.GetCount() == 0) | |
| 418 if (!token_.EnablePrivilege(L"SeRestorePrivilege", &restore_)) | |
| 419 return false; | |
| 420 | |
| 421 return true; | |
| 422 } | |
| 423 | |
| 424 const CSid& GetUser() const { | |
| 425 return user_; | |
| 426 } | |
| 427 | |
| 428 private: | |
| 429 CAccessToken token_; | |
| 430 CTokenPrivileges take_ownership_; | |
| 431 CTokenPrivileges restore_; | |
| 432 CSid user_; | |
| 433 }; | |
| 434 | |
| 435 static bool SetOrDeleteMimeHandlerKey(bool set) { | |
| 436 std::wstring key_name = kInternetSettings; | |
| 437 key_name.append(L"\\Secure Mime Handlers"); | |
| 438 RegKey key(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ | KEY_WRITE); | |
| 439 if (!key.Valid()) | |
| 440 return false; | |
| 441 | |
| 442 bool result; | |
| 443 if (set) { | |
| 444 result = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1); | |
| 445 result = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1) && result; | |
| 446 } else { | |
| 447 result = key.DeleteValue(L"ChromeTab.ChromeActiveDocument"); | |
| 448 result = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1") && result; | |
| 449 } | |
| 450 | |
| 451 return result; | |
| 452 } | |
| 453 | |
| 454 bool RegisterSecuredMimeHandler(bool enable) { | |
| 455 if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { | |
| 456 return SetOrDeleteMimeHandlerKey(enable); | |
| 457 } | |
| 458 | |
| 459 std::wstring mime_key = kInternetSettings; | |
| 460 mime_key.append(L"\\Secure Mime Handlers"); | |
| 461 std::wstring backup_key = kInternetSettings; | |
| 462 backup_key.append(L"\\__backup_SMH__"); | |
| 463 std::wstring object_name = L"MACHINE\\"; | |
| 464 object_name.append(mime_key); | |
| 465 | |
| 466 TokenWithPrivileges token_; | |
| 467 if (!token_.EnablePrivileges()) | |
| 468 return false; | |
| 469 | |
| 470 // If there is a backup key - something bad happened; try to restore | |
| 471 // security on "Secure Mime Handlers" from the backup. | |
| 472 SecurityDescBackup backup(backup_key); | |
| 473 backup.RestoreSecurity(object_name.c_str()); | |
| 474 | |
| 475 // Read old security descriptor of the Mime key first. | |
| 476 CSecurityDesc sd; | |
| 477 if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) { | |
| 478 return false; | |
| 479 } | |
| 480 | |
| 481 backup.SaveSecurity(sd); | |
| 482 bool result = false; | |
| 483 // set new owner | |
| 484 if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) { | |
| 485 // set new dacl | |
| 486 CDacl new_dacl; | |
| 487 sd.GetDacl(&new_dacl); | |
| 488 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); | |
| 489 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { | |
| 490 result = SetOrDeleteMimeHandlerKey(enable); | |
| 491 } | |
| 492 } | |
| 493 | |
| 494 backup.RestoreSecurity(object_name.c_str()); | |
| 495 return result; | |
| 496 } | |
| OLD | NEW |