Chromium Code Reviews| Index: chrome_frame/chrome_tab.cc |
| =================================================================== |
| --- chrome_frame/chrome_tab.cc (revision 28103) |
| +++ chrome_frame/chrome_tab.cc (working copy) |
| @@ -13,6 +13,7 @@ |
| #include "base/string_piece.h" |
| #include "base/string_util.h" |
| #include "base/sys_string_conversions.h" |
| +#include "base/win_util.h" |
| #include "chrome/common/chrome_constants.h" |
| #include "grit/chrome_frame_resources.h" |
| #include "chrome_frame/bho.h" |
| @@ -24,11 +25,15 @@ |
| // Include without path to make GYP build see it. |
| #include "chrome_tab.h" // NOLINT |
| +#include <atlsecurity.h> |
| static const wchar_t kBhoRegistryPath[] = |
| L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer" |
| L"\\Browser Helper Objects"; |
| +const wchar_t kInternetSettings[] = |
| + L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; |
| + |
| const wchar_t kBhoNoLoadExplorerValue[] = L"NoExplorer"; |
| class ChromeTabModule |
| @@ -106,6 +111,7 @@ |
| ChromeTabModule _AtlModule; |
| base::AtExitManager* g_exit_manager = NULL; |
| +bool RegisterSecuredMimeHandler(bool enable); // forward |
| // DLL Entry Point |
| extern "C" BOOL WINAPI DllMain(HINSTANCE instance, |
| @@ -175,7 +181,7 @@ |
| } else { |
| hr = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| - |
| + |
| FreeLibrary(ieframe_module); |
| } else { |
| hr = HRESULT_FROM_WIN32(GetLastError()); |
| @@ -272,6 +278,8 @@ |
| // ignore any errors during registration. There are some traces emitted |
| // to the debug log. |
| RegisterChromeTabBHO(); |
| + if (!RegisterSecuredMimeHandler(true)) |
| + hr = E_FAIL; |
| } |
| return hr; |
| @@ -291,6 +299,8 @@ |
| // ignore any errors during unregistration. There are some traces emitted |
| // to the debug log. |
| UnregisterChromeTabBHO(); |
| + if (!RegisterSecuredMimeHandler(false)) |
| + hr = E_FAIL; |
| } |
| return hr; |
| } |
| @@ -306,3 +316,181 @@ |
| FALSE); |
| return hr; |
| } |
| + |
| +class SecurityDescBackup { |
| + public: |
| + explicit SecurityDescBackup(const std::wstring& backup_key) |
| + : backup_key_name_(backup_key) {} |
| + ~SecurityDescBackup() {} |
| + |
| + // Save given security descriptor to the backup key. |
| + bool SaveSecurity(const CSecurityDesc& sd) { |
| + CString str; |
| + if (!sd.ToString(&str)) |
| + return false; |
| + |
| + RegKey backup_key(HKEY_LOCAL_MACHINE, backup_key_name_.c_str(), |
| + KEY_READ | KEY_WRITE); |
| + if (backup_key.Valid()) { |
| + return backup_key.WriteValue(NULL, str.GetString()); |
| + } |
| + |
| + return false; |
| + } |
| + |
| + // Restore security descriptor from backup key to given key name. |
| + bool RestoreSecurity(const wchar_t* key_name) { |
| + std::wstring sddl; |
| + if (!ReadBackupKey(&sddl)) |
| + return false; |
| + |
| + // Create security descriptor from string. |
| + CSecurityDesc sd; |
| + if (!sd.FromString(sddl.c_str())) |
| + return false; |
| + |
| + bool result = true; |
| + // Restore DACL and Owner of the key from saved security descriptor. |
| + CDacl dacl; |
| + CSid owner; |
| + sd.GetDacl(&dacl); |
| + sd.GetOwner(&owner); |
| + |
| + DWORD error = ::SetNamedSecurityInfo(const_cast<wchar_t*>(key_name), |
| + SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, |
| + const_cast<SID*>(owner.GetPSID()), NULL, |
| + const_cast<ACL*>(dacl.GetPACL()), NULL); |
| + |
| + DeleteBackupKey(); |
| + return (error == ERROR_SUCCESS); |
| + } |
| + |
| + private: |
| + // Read SDDL string from backup key |
| + bool ReadBackupKey(std::wstring* sddl) { |
| + RegKey backup_key(HKEY_LOCAL_MACHINE, backup_key_name_.c_str(), KEY_READ); |
| + if (!backup_key.Valid()) |
| + return false; |
| + |
| + // 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?
|
| + DWORD len = 0; |
| + DWORD reg_type = REG_NONE; |
| + if (!backup_key.ReadValue(NULL, NULL, &len, ®_type)) |
| + return false; |
| + |
| + if (reg_type != REG_SZ) |
| + return false; |
| + |
| + size_t wchar_count = 1 + len / sizeof(wchar_t); |
| + if (!backup_key.ReadValue(NULL, WriteInto(sddl, wchar_count), &len, |
| + ®_type)) { |
| + return false; |
| + } |
| + |
| + return true; |
| + } |
| + |
| + void DeleteBackupKey() { |
| + ::RegDeleteKey(HKEY_LOCAL_MACHINE, backup_key_name_.c_str()); |
| + } |
| + |
| + std::wstring backup_key_name_; |
| +}; |
| + |
| +struct TokenWithPrivileges { |
| + TokenWithPrivileges() { |
| + token_.GetEffectiveToken(TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY); |
| + token_.GetUser(&user_); |
| + } |
| + |
| + ~TokenWithPrivileges() { |
| + token_.EnableDisablePrivileges(take_ownership_); |
| + token_.EnableDisablePrivileges(restore_); |
| + } |
| + |
| + bool EnablePrivileges() { |
| + if (take_ownership_.GetCount() == 0) |
| + if (!token_.EnablePrivilege(L"SeTakeOwnershipPrivilege", |
| + &take_ownership_)) |
| + return false; |
| + |
| + if (restore_.GetCount() == 0) |
| + if (!token_.EnablePrivilege(L"SeRestorePrivilege", &restore_)) |
| + return false; |
| + |
| + return true; |
| + } |
| + |
| + const CSid& GetUser() const { |
| + return user_; |
| + } |
| + |
| + private: |
| + CAccessToken token_; |
| + CTokenPrivileges take_ownership_; |
| + CTokenPrivileges restore_; |
| + CSid user_; |
| +}; |
| + |
| +static bool SetOrDeleteMimeHandlerKey(bool set) { |
| + std::wstring key_name = kInternetSettings; |
| + key_name.append(L"\\Secure Mime Handlers"); |
| + RegKey key(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ | KEY_WRITE); |
| + if (!key.Valid()) |
| + return false; |
| + |
| + bool result; |
| + if (set) { |
| + result = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1); |
| + result = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1) && result; |
| + } else { |
| + result = key.DeleteValue(L"ChromeTab.ChromeActiveDocument"); |
| + result = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1") && result; |
| + } |
| + |
| + return result; |
| +} |
| + |
| +bool RegisterSecuredMimeHandler(bool enable) { |
| + if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { |
| + return SetOrDeleteMimeHandlerKey(enable); |
| + } |
| + |
| + std::wstring mime_key = kInternetSettings; |
| + mime_key.append(L"\\Secure Mime Handlers"); |
| + std::wstring backup_key = kInternetSettings; |
| + backup_key.append(L"\\__backup_SMH__"); |
| + std::wstring object_name = L"MACHINE\\"; |
| + object_name.append(mime_key); |
| + |
| + TokenWithPrivileges token_; |
| + if (!token_.EnablePrivileges()) |
| + return false; |
| + |
| + // If there is a backup key - something bad happened; try to restore |
| + // security on "Secure Mime Handlers" from the backup. |
| + SecurityDescBackup backup(backup_key); |
| + backup.RestoreSecurity(object_name.c_str()); |
| + |
| + // Read old security descriptor of the Mime key first. |
| + CSecurityDesc sd; |
| + if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) { |
| + return false; |
| + } |
| + |
| + backup.SaveSecurity(sd); |
| + bool result = false; |
| + // set new owner |
| + if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) { |
| + // set new dacl |
| + CDacl new_dacl; |
| + sd.GetDacl(&new_dacl); |
| + new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); |
| + if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { |
| + result = SetOrDeleteMimeHandlerKey(enable); |
| + } |
| + } |
| + |
| + backup.RestoreSecurity(object_name.c_str()); |
| + return result; |
| +} |