1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "remoting/host/pairing_registry_delegate_win.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/json/json_string_value_serializer.h" 8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/logging.h" 9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/values.h" 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/win/registry.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace remoting { 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace { 16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Duplicates a registry key handle (returned by RegCreateXxx/RegOpenXxx). 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// The returned handle cannot be inherited and has the same permissions as 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// the source one. 20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool DuplicateKeyHandle(HKEY source, base::win::RegKey* dest) { 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) HANDLE handle; 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!DuplicateHandle(GetCurrentProcess(), 23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) source, 24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) GetCurrentProcess(), 25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) &handle, 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FALSE, 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DUPLICATE_SAME_ACCESS)) { 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PLOG(ERROR) << "Failed to duplicate a registry key handle"; 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) dest->Set(reinterpret_cast<HKEY>(handle)); 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Reads value |value_name| from |key| as a JSON string and returns it as 38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// |base::Value|. 39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochscoped_ptr<base::DictionaryValue> ReadValue(const base::win::RegKey& key, 40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const wchar_t* value_name) { 41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::wstring value_json; 43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LONG result = key.ReadValue(value_name, &value_json); 44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (result != ERROR_SUCCESS) { 45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SetLastError(result); 46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PLOG(ERROR) << "Cannot read value '" << value_name << "'"; 47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return scoped_ptr<base::DictionaryValue>(); 48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Parse the value. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string value_json_utf8 = base::WideToUTF8(value_json); 52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch JSONStringValueSerializer serializer(&value_json_utf8); 53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int error_code; 54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string error_message; 55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::Value> value(serializer.Deserialize(&error_code, 56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch &error_message)); 57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!value) { 58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Failed to parse '" << value_name << "': " << error_message 59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << " (" << error_code << ")."; 60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return scoped_ptr<base::DictionaryValue>(); 61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (value->GetType() != base::Value::TYPE_DICTIONARY) { 64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Failed to parse '" << value_name << "': not a dictionary."; 65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return scoped_ptr<base::DictionaryValue>(); 66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return scoped_ptr<base::DictionaryValue>( 69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch static_cast<base::DictionaryValue*>(value.release())); 70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Serializes |value| into a JSON string and writes it as value |value_name| 73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// under |key|. 74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool WriteValue(base::win::RegKey& key, 75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const wchar_t* value_name, 76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::DictionaryValue> value) { 77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string value_json_utf8; 78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch JSONStringValueSerializer serializer(&value_json_utf8); 79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!serializer.Serialize(*value)) { 80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Failed to serialize '" << value_name << "'"; 81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring value_json = base::UTF8ToWide(value_json_utf8); 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LONG result = key.WriteValue(value_name, value_json.c_str()); 87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (result != ERROR_SUCCESS) { 88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SetLastError(result); 89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PLOG(ERROR) << "Cannot write value '" << value_name << "'"; 90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return true; 94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing protocol::PairingRegistry; 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistryDelegateWin::PairingRegistryDelegateWin() { 101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistryDelegateWin::~PairingRegistryDelegateWin() { 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PairingRegistryDelegateWin::SetRootKeys(HKEY privileged, 107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) HKEY unprivileged) { 108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(!privileged_.Valid()); 109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(!unprivileged_.Valid()); 110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(unprivileged); 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!DuplicateKeyHandle(unprivileged, &unprivileged_)) 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (privileged) { 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!DuplicateKeyHandle(privileged, &privileged_)) 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<base::ListValue> PairingRegistryDelegateWin::LoadAll() { 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<base::ListValue> pairings(new base::ListValue()); 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Enumerate and parse all values under the unprivileged key. 127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DWORD count = unprivileged_.GetValueCount(); 128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (DWORD index = 0; index < count; ++index) { 129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::wstring value_name; 131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LONG result = unprivileged_.GetValueNameAt(index, &value_name); 132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (result != ERROR_SUCCESS) { 133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SetLastError(result); 134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PLOG(ERROR) << "Cannot get the name of value " << index; 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch continue; 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PairingRegistry::Pairing pairing = Load(base::WideToUTF8(value_name)); 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (pairing.is_valid()) 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pairings->Append(pairing.ToValue().release()); 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return pairings.Pass(); 144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PairingRegistryDelegateWin::DeleteAll() { 147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!privileged_.Valid()) { 148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Cannot delete pairings: the delegate is read-only."; 149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Enumerate and delete the values in the privileged and unprivileged keys 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // separately in case they get out of sync. 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool success = true; 155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DWORD count = unprivileged_.GetValueCount(); 156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch while (count > 0) { 157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::wstring value_name; 159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LONG result = unprivileged_.GetValueNameAt(0, &value_name); 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result == ERROR_SUCCESS) 161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch result = unprivileged_.DeleteValue(value_name.c_str()); 162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch success = success && (result == ERROR_SUCCESS); 164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch count = unprivileged_.GetValueCount(); 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) count = privileged_.GetValueCount(); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (count > 0) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // presubmit: allow wstring 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring value_name; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LONG result = privileged_.GetValueNameAt(0, &value_name); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result == ERROR_SUCCESS) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = privileged_.DeleteValue(value_name.c_str()); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) success = success && (result == ERROR_SUCCESS); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) count = privileged_.GetValueCount(); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return success; 180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PairingRegistry::Pairing PairingRegistryDelegateWin::Load( 183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& client_id) { 184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring value_name = base::UTF8ToWide(client_id); 186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Read unprivileged fields first. 188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::DictionaryValue> pairing = ReadValue(unprivileged_, 189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch value_name.c_str()); 190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!pairing) 191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return PairingRegistry::Pairing(); 192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Read the shared secret. 194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (privileged_.Valid()) { 195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::DictionaryValue> secret = ReadValue(privileged_, 196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch value_name.c_str()); 197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!secret) 198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return PairingRegistry::Pairing(); 199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Merge the two dictionaries. 201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pairing->MergeDictionary(secret.get()); 202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PairingRegistry::Pairing::CreateFromValue(*pairing); 205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PairingRegistryDelegateWin::Save(const PairingRegistry::Pairing& pairing) { 208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!privileged_.Valid()) { 209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) LOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id() 210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) << "': the delegate is read-only."; 211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Convert pairing to JSON. 215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::DictionaryValue> pairing_json = pairing.ToValue(); 216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Extract the shared secret to a separate dictionary. 218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::Value> secret_key; 219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CHECK(pairing_json->Remove(PairingRegistry::kSharedSecretKey, &secret_key)); 220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<base::DictionaryValue> secret_json(new base::DictionaryValue()); 221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch secret_json->Set(PairingRegistry::kSharedSecretKey, secret_key.release()); 222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring value_name = base::UTF8ToWide(pairing.client_id()); 225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Write pairing to the registry. 227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!WriteValue(privileged_, value_name.c_str(), secret_json.Pass()) || 228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch !WriteValue(unprivileged_, value_name.c_str(), pairing_json.Pass())) { 229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PairingRegistryDelegateWin::Delete(const std::string& client_id) { 236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!privileged_.Valid()) { 237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) LOG(ERROR) << "Cannot delete pairing entry '" << client_id 238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) << "': the delegate is read-only."; 239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // presubmit: allow wstring 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::wstring value_name = base::UTF8ToWide(client_id); 244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LONG result = privileged_.DeleteValue(value_name.c_str()); 245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result != ERROR_SUCCESS && 246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result != ERROR_FILE_NOT_FOUND && 247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result != ERROR_PATH_NOT_FOUND) { 248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SetLastError(result); 249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PLOG(ERROR) << "Cannot delete pairing entry '" << client_id << "'"; 250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch result = unprivileged_.DeleteValue(value_name.c_str()); 254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result != ERROR_SUCCESS && 255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result != ERROR_FILE_NOT_FOUND && 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result != ERROR_PATH_NOT_FOUND) { 257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SetLastError(result); 258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PLOG(ERROR) << "Cannot delete pairing entry '" << client_id << "'"; 259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<PairingRegistry::Delegate> CreatePairingRegistryDelegate() { 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<PairingRegistry::Delegate>( 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new PairingRegistryDelegateWin()); 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace remoting 271