OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "components/proximity_auth/webui/proximity_auth_webui_handler.h" | 5 #include "components/proximity_auth/webui/proximity_auth_webui_handler.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/i18n/time_formatting.h" | 10 #include "base/i18n/time_formatting.h" |
9 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
| 12 #include "base/thread_task_runner_handle.h" |
10 #include "base/time/default_clock.h" | 13 #include "base/time/default_clock.h" |
11 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "components/proximity_auth/bluetooth_connection.h" |
| 16 #include "components/proximity_auth/bluetooth_util.h" |
| 17 #include "components/proximity_auth/client_impl.h" |
12 #include "components/proximity_auth/cryptauth/base64url.h" | 18 #include "components/proximity_auth/cryptauth/base64url.h" |
13 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" | 19 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" |
14 #include "components/proximity_auth/cryptauth/cryptauth_gcm_manager_impl.h" | 20 #include "components/proximity_auth/cryptauth/cryptauth_gcm_manager_impl.h" |
15 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" | 21 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" |
| 22 #include "components/proximity_auth/cryptauth/secure_message_delegate.h" |
| 23 #include "components/proximity_auth/device_to_device_authenticator.h" |
16 #include "components/proximity_auth/logging/logging.h" | 24 #include "components/proximity_auth/logging/logging.h" |
| 25 #include "components/proximity_auth/remote_status_update.h" |
| 26 #include "components/proximity_auth/secure_context.h" |
17 #include "components/proximity_auth/webui/cryptauth_enroller_factory_impl.h" | 27 #include "components/proximity_auth/webui/cryptauth_enroller_factory_impl.h" |
18 #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h" | 28 #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h" |
| 29 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/web_ui.h" | 30 #include "content/public/browser/web_ui.h" |
| 31 #include "device/bluetooth/bluetooth_uuid.h" |
20 | 32 |
21 namespace proximity_auth { | 33 namespace proximity_auth { |
22 | 34 |
23 namespace { | 35 namespace { |
24 | 36 |
| 37 // The UUID of the Smart Lock Bluetooth service. |
| 38 const char kBluetoothServiceUUID[] = "704EE561-3782-405A-A14B-2D47A2DDCDDF"; |
| 39 |
25 // Keys in the JSON representation of a log message. | 40 // Keys in the JSON representation of a log message. |
26 const char kLogMessageTextKey[] = "text"; | 41 const char kLogMessageTextKey[] = "text"; |
27 const char kLogMessageTimeKey[] = "time"; | 42 const char kLogMessageTimeKey[] = "time"; |
28 const char kLogMessageFileKey[] = "file"; | 43 const char kLogMessageFileKey[] = "file"; |
29 const char kLogMessageLineKey[] = "line"; | 44 const char kLogMessageLineKey[] = "line"; |
30 const char kLogMessageSeverityKey[] = "severity"; | 45 const char kLogMessageSeverityKey[] = "severity"; |
31 | 46 |
32 // Keys in the JSON representation of a SyncState object for enrollment or | 47 // Keys in the JSON representation of a SyncState object for enrollment or |
33 // device sync. | 48 // device sync. |
34 const char kSyncStateLastSuccessTime[] = "lastSuccessTime"; | 49 const char kSyncStateLastSuccessTime[] = "lastSuccessTime"; |
(...skipping 13 matching lines...) Expand all Loading... |
48 dictionary->SetString(kLogMessageFileKey, log_message.file); | 63 dictionary->SetString(kLogMessageFileKey, log_message.file); |
49 dictionary->SetInteger(kLogMessageLineKey, log_message.line); | 64 dictionary->SetInteger(kLogMessageLineKey, log_message.line); |
50 dictionary->SetInteger(kLogMessageSeverityKey, | 65 dictionary->SetInteger(kLogMessageSeverityKey, |
51 static_cast<int>(log_message.severity)); | 66 static_cast<int>(log_message.severity)); |
52 return dictionary.Pass(); | 67 return dictionary.Pass(); |
53 } | 68 } |
54 | 69 |
55 // Keys in the JSON representation of an ExternalDeviceInfo proto. | 70 // Keys in the JSON representation of an ExternalDeviceInfo proto. |
56 const char kExternalDevicePublicKey[] = "publicKey"; | 71 const char kExternalDevicePublicKey[] = "publicKey"; |
57 const char kExternalDeviceFriendlyName[] = "friendlyDeviceName"; | 72 const char kExternalDeviceFriendlyName[] = "friendlyDeviceName"; |
| 73 const char kExternalDeviceBluetoothAddress[] = "bluetoothAddress"; |
58 const char kExternalDeviceUnlockKey[] = "unlockKey"; | 74 const char kExternalDeviceUnlockKey[] = "unlockKey"; |
59 const char kExternalDeviceConnectionStatus[] = "connectionStatus"; | 75 const char kExternalDeviceConnectionStatus[] = "connectionStatus"; |
| 76 const char kExternalDeviceRemoteState[] = "remoteState"; |
60 | 77 |
61 // The possible values of the |kExternalDeviceConnectionStatus| field. | 78 // The possible values of the |kExternalDeviceConnectionStatus| field. |
| 79 const char kExternalDeviceConnected[] = "connected"; |
62 const char kExternalDeviceDisconnected[] = "disconnected"; | 80 const char kExternalDeviceDisconnected[] = "disconnected"; |
63 | 81 const char kExternalDeviceConnecting[] = "connecting"; |
64 // Converts an ExternalDeviceInfo proto to a JSON dictionary used in JavaScript. | |
65 scoped_ptr<base::DictionaryValue> ExternalDeviceInfoToDictionary( | |
66 const cryptauth::ExternalDeviceInfo& device_info) { | |
67 std::string base64_public_key; | |
68 Base64UrlEncode(device_info.public_key(), &base64_public_key); | |
69 | |
70 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); | |
71 dictionary->SetString(kExternalDevicePublicKey, base64_public_key); | |
72 dictionary->SetString(kExternalDeviceFriendlyName, | |
73 device_info.friendly_device_name()); | |
74 dictionary->SetBoolean(kExternalDeviceUnlockKey, device_info.unlock_key()); | |
75 dictionary->SetString(kExternalDeviceConnectionStatus, | |
76 kExternalDeviceDisconnected); | |
77 return dictionary.Pass(); | |
78 } | |
79 | 82 |
80 // Keys in the JSON representation of an IneligibleDevice proto. | 83 // Keys in the JSON representation of an IneligibleDevice proto. |
81 const char kIneligibleDeviceReasons[] = "ineligibilityReasons"; | 84 const char kIneligibleDeviceReasons[] = "ineligibilityReasons"; |
82 | 85 |
83 // Converts an IneligibleDevice proto to a JSON dictionary used in JavaScript. | |
84 scoped_ptr<base::DictionaryValue> IneligibleDeviceToDictionary( | |
85 const cryptauth::IneligibleDevice& ineligible_device) { | |
86 scoped_ptr<base::ListValue> ineligibility_reasons(new base::ListValue()); | |
87 for (const std::string& reason : ineligible_device.reasons()) { | |
88 ineligibility_reasons->AppendString(reason); | |
89 } | |
90 | |
91 scoped_ptr<base::DictionaryValue> device_dictionary = | |
92 ExternalDeviceInfoToDictionary(ineligible_device.device()); | |
93 device_dictionary->Set(kIneligibleDeviceReasons, | |
94 ineligibility_reasons.Pass()); | |
95 return device_dictionary; | |
96 } | |
97 | |
98 // Creates a SyncState JSON object that can be passed to the WebUI. | 86 // Creates a SyncState JSON object that can be passed to the WebUI. |
99 scoped_ptr<base::DictionaryValue> CreateSyncStateDictionary( | 87 scoped_ptr<base::DictionaryValue> CreateSyncStateDictionary( |
100 double last_success_time, | 88 double last_success_time, |
101 double next_refresh_time, | 89 double next_refresh_time, |
102 bool is_recovering_from_failure, | 90 bool is_recovering_from_failure, |
103 bool is_enrollment_in_progress) { | 91 bool is_enrollment_in_progress) { |
104 scoped_ptr<base::DictionaryValue> sync_state(new base::DictionaryValue()); | 92 scoped_ptr<base::DictionaryValue> sync_state(new base::DictionaryValue()); |
105 sync_state->SetDouble(kSyncStateLastSuccessTime, last_success_time); | 93 sync_state->SetDouble(kSyncStateLastSuccessTime, last_success_time); |
106 sync_state->SetDouble(kSyncStateNextRefreshTime, next_refresh_time); | 94 sync_state->SetDouble(kSyncStateNextRefreshTime, next_refresh_time); |
107 sync_state->SetBoolean(kSyncStateRecoveringFromFailure, | 95 sync_state->SetBoolean(kSyncStateRecoveringFromFailure, |
108 is_recovering_from_failure); | 96 is_recovering_from_failure); |
109 sync_state->SetBoolean(kSyncStateOperationInProgress, | 97 sync_state->SetBoolean(kSyncStateOperationInProgress, |
110 is_enrollment_in_progress); | 98 is_enrollment_in_progress); |
111 return sync_state; | 99 return sync_state; |
112 } | 100 } |
113 | 101 |
114 } // namespace | 102 } // namespace |
115 | 103 |
116 ProximityAuthWebUIHandler::ProximityAuthWebUIHandler( | 104 ProximityAuthWebUIHandler::ProximityAuthWebUIHandler( |
117 ProximityAuthUIDelegate* delegate) | 105 ProximityAuthUIDelegate* delegate) |
118 : delegate_(delegate), weak_ptr_factory_(this) { | 106 : delegate_(delegate), |
| 107 web_contents_initialized_(false), |
| 108 weak_ptr_factory_(this) { |
119 cryptauth_client_factory_ = delegate_->CreateCryptAuthClientFactory(); | 109 cryptauth_client_factory_ = delegate_->CreateCryptAuthClientFactory(); |
120 } | 110 } |
121 | 111 |
122 ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() { | 112 ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() { |
123 LogBuffer::GetInstance()->RemoveObserver(this); | 113 LogBuffer::GetInstance()->RemoveObserver(this); |
124 if (enrollment_manager_) | |
125 enrollment_manager_->RemoveObserver(this); | |
126 } | 114 } |
127 | 115 |
128 void ProximityAuthWebUIHandler::RegisterMessages() { | 116 void ProximityAuthWebUIHandler::RegisterMessages() { |
129 web_ui()->RegisterMessageCallback( | 117 web_ui()->RegisterMessageCallback( |
130 "clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer, | 118 "clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer, |
131 base::Unretained(this))); | 119 base::Unretained(this))); |
132 | 120 |
133 web_ui()->RegisterMessageCallback( | 121 web_ui()->RegisterMessageCallback( |
134 "getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages, | 122 "getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages, |
135 base::Unretained(this))); | 123 base::Unretained(this))); |
136 | 124 |
137 web_ui()->RegisterMessageCallback( | 125 web_ui()->RegisterMessageCallback( |
138 "findEligibleUnlockDevices", | 126 "findEligibleUnlockDevices", |
139 base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices, | 127 base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices, |
140 base::Unretained(this))); | 128 base::Unretained(this))); |
141 | 129 |
142 web_ui()->RegisterMessageCallback( | 130 web_ui()->RegisterMessageCallback( |
143 "getSyncStates", base::Bind(&ProximityAuthWebUIHandler::GetSyncStates, | 131 "getLocalState", base::Bind(&ProximityAuthWebUIHandler::GetLocalState, |
144 base::Unretained(this))); | 132 base::Unretained(this))); |
145 | 133 |
146 web_ui()->RegisterMessageCallback( | 134 web_ui()->RegisterMessageCallback( |
147 "forceEnrollment", base::Bind(&ProximityAuthWebUIHandler::ForceEnrollment, | 135 "forceEnrollment", base::Bind(&ProximityAuthWebUIHandler::ForceEnrollment, |
148 base::Unretained(this))); | 136 base::Unretained(this))); |
149 | 137 |
150 web_ui()->RegisterMessageCallback( | 138 web_ui()->RegisterMessageCallback( |
151 "forceDeviceSync", base::Bind(&ProximityAuthWebUIHandler::ForceDeviceSync, | 139 "forceDeviceSync", base::Bind(&ProximityAuthWebUIHandler::ForceDeviceSync, |
152 base::Unretained(this))); | 140 base::Unretained(this))); |
153 | 141 |
154 LogBuffer::GetInstance()->AddObserver(this); | 142 web_ui()->RegisterMessageCallback( |
| 143 "toggleConnection", |
| 144 base::Bind(&ProximityAuthWebUIHandler::ToggleConnection, |
| 145 base::Unretained(this))); |
155 | 146 |
156 InitGCMManager(); | 147 InitGCMManager(); |
157 InitEnrollmentManager(); | 148 InitEnrollmentManager(); |
158 InitDeviceManager(); | 149 InitDeviceManager(); |
| 150 LogBuffer::GetInstance()->AddObserver(this); |
159 } | 151 } |
160 | 152 |
161 void ProximityAuthWebUIHandler::OnLogMessageAdded( | 153 void ProximityAuthWebUIHandler::OnLogMessageAdded( |
162 const LogBuffer::LogMessage& log_message) { | 154 const LogBuffer::LogMessage& log_message) { |
163 scoped_ptr<base::DictionaryValue> dictionary = | 155 scoped_ptr<base::DictionaryValue> dictionary = |
164 LogMessageToDictionary(log_message); | 156 LogMessageToDictionary(log_message); |
165 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogMessageAdded", | 157 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogMessageAdded", |
166 *dictionary); | 158 *dictionary); |
167 } | 159 } |
168 | 160 |
169 void ProximityAuthWebUIHandler::OnLogBufferCleared() { | 161 void ProximityAuthWebUIHandler::OnLogBufferCleared() { |
170 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared"); | 162 web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared"); |
171 } | 163 } |
172 | 164 |
173 void ProximityAuthWebUIHandler::OnEnrollmentStarted() { | 165 void ProximityAuthWebUIHandler::OnEnrollmentStarted() { |
174 web_ui()->CallJavascriptFunction( | 166 web_ui()->CallJavascriptFunction( |
175 "SyncStateInterface.onEnrollmentStateChanged", | 167 "LocalStateInterface.onEnrollmentStateChanged", |
176 *GetEnrollmentStateDictionary()); | 168 *GetEnrollmentStateDictionary()); |
177 } | 169 } |
178 | 170 |
179 void ProximityAuthWebUIHandler::OnEnrollmentFinished(bool success) { | 171 void ProximityAuthWebUIHandler::OnEnrollmentFinished(bool success) { |
180 scoped_ptr<base::DictionaryValue> enrollment_state = | 172 scoped_ptr<base::DictionaryValue> enrollment_state = |
181 GetEnrollmentStateDictionary(); | 173 GetEnrollmentStateDictionary(); |
182 PA_LOG(INFO) << "Enrollment attempt completed with success=" << success | 174 PA_LOG(INFO) << "Enrollment attempt completed with success=" << success |
183 << ":\n" << *enrollment_state; | 175 << ":\n" << *enrollment_state; |
184 web_ui()->CallJavascriptFunction( | 176 web_ui()->CallJavascriptFunction( |
185 "SyncStateInterface.onEnrollmentStateChanged", *enrollment_state); | 177 "LocalStateInterface.onEnrollmentStateChanged", *enrollment_state); |
186 } | 178 } |
187 | 179 |
188 void ProximityAuthWebUIHandler::OnSyncStarted() { | 180 void ProximityAuthWebUIHandler::OnSyncStarted() { |
189 web_ui()->CallJavascriptFunction( | 181 web_ui()->CallJavascriptFunction( |
190 "SyncStateInterface.onDeviceSyncStateChanged", | 182 "LocalStateInterface.onDeviceSyncStateChanged", |
191 *GetDeviceSyncStateDictionary()); | 183 *GetDeviceSyncStateDictionary()); |
192 } | 184 } |
193 | 185 |
194 void ProximityAuthWebUIHandler::OnSyncFinished( | 186 void ProximityAuthWebUIHandler::OnSyncFinished( |
195 CryptAuthDeviceManager::SyncResult sync_result, | 187 CryptAuthDeviceManager::SyncResult sync_result, |
196 CryptAuthDeviceManager::DeviceChangeResult device_change_result) { | 188 CryptAuthDeviceManager::DeviceChangeResult device_change_result) { |
197 scoped_ptr<base::DictionaryValue> device_sync_state = | 189 scoped_ptr<base::DictionaryValue> device_sync_state = |
198 GetDeviceSyncStateDictionary(); | 190 GetDeviceSyncStateDictionary(); |
199 PA_LOG(INFO) << "Device sync completed with result=" | 191 PA_LOG(INFO) << "Device sync completed with result=" |
200 << static_cast<int>(sync_result) << ":\n" << *device_sync_state; | 192 << static_cast<int>(sync_result) << ":\n" << *device_sync_state; |
201 web_ui()->CallJavascriptFunction( | 193 web_ui()->CallJavascriptFunction( |
202 "SyncStateInterface.onDeviceSyncStateChanged", *device_sync_state); | 194 "LocalStateInterface.onDeviceSyncStateChanged", *device_sync_state); |
| 195 |
| 196 if (device_change_result == |
| 197 CryptAuthDeviceManager::DeviceChangeResult::CHANGED) { |
| 198 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList(); |
| 199 PA_LOG(INFO) << "New unlock keys obtained after device sync:\n" |
| 200 << *unlock_keys; |
| 201 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged", |
| 202 *unlock_keys); |
| 203 } |
203 } | 204 } |
204 | 205 |
205 void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue* args) { | 206 void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue* args) { |
206 base::ListValue json_logs; | 207 base::ListValue json_logs; |
207 for (const auto& log : *LogBuffer::GetInstance()->logs()) { | 208 for (const auto& log : *LogBuffer::GetInstance()->logs()) { |
208 json_logs.Append(LogMessageToDictionary(log).release()); | 209 json_logs.Append(LogMessageToDictionary(log).release()); |
209 } | 210 } |
210 web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages", | 211 web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages", |
211 json_logs); | 212 json_logs); |
212 } | 213 } |
(...skipping 23 matching lines...) Expand all Loading... |
236 enrollment_manager_->ForceEnrollmentNow( | 237 enrollment_manager_->ForceEnrollmentNow( |
237 cryptauth::INVOCATION_REASON_MANUAL); | 238 cryptauth::INVOCATION_REASON_MANUAL); |
238 } | 239 } |
239 } | 240 } |
240 | 241 |
241 void ProximityAuthWebUIHandler::ForceDeviceSync(const base::ListValue* args) { | 242 void ProximityAuthWebUIHandler::ForceDeviceSync(const base::ListValue* args) { |
242 if (device_manager_) | 243 if (device_manager_) |
243 device_manager_->ForceSyncNow(cryptauth::INVOCATION_REASON_MANUAL); | 244 device_manager_->ForceSyncNow(cryptauth::INVOCATION_REASON_MANUAL); |
244 } | 245 } |
245 | 246 |
| 247 void ProximityAuthWebUIHandler::ToggleConnection(const base::ListValue* args) { |
| 248 std::string b64_public_key; |
| 249 std::string public_key; |
| 250 if (!device_manager_ || !args->GetSize() || |
| 251 !args->GetString(0, &b64_public_key) || |
| 252 !Base64UrlDecode(b64_public_key, &public_key)) { |
| 253 return; |
| 254 } |
| 255 |
| 256 Connection* connection = GetConnection(); |
| 257 for (const auto& unlock_key : device_manager_->unlock_keys()) { |
| 258 if (unlock_key.public_key() == public_key) { |
| 259 // Check if there is an existing connection to disconnect from first. |
| 260 if (connection && connection->IsConnected() && |
| 261 connection->remote_device().public_key == public_key) { |
| 262 PA_LOG(INFO) << "Disconnecting from " |
| 263 << unlock_key.friendly_device_name() << "[" |
| 264 << unlock_key.bluetooth_address() << "]"; |
| 265 connection->Disconnect(); |
| 266 return; |
| 267 } |
| 268 |
| 269 // Derive the PSK before connecting to the device. |
| 270 PA_LOG(INFO) << "Connecting to " << unlock_key.friendly_device_name() |
| 271 << "[" << unlock_key.bluetooth_address() << "]"; |
| 272 secure_message_delegate_ = delegate_->CreateSecureMessageDelegate(); |
| 273 secure_message_delegate_->DeriveKey( |
| 274 user_private_key_, unlock_key.public_key(), |
| 275 base::Bind(&ProximityAuthWebUIHandler::OnPSKDerived, |
| 276 weak_ptr_factory_.GetWeakPtr(), unlock_key)); |
| 277 |
| 278 return; |
| 279 } |
| 280 } |
| 281 |
| 282 PA_LOG(ERROR) << "Unlock key (" << b64_public_key << ") not found"; |
| 283 } |
| 284 |
246 void ProximityAuthWebUIHandler::InitGCMManager() { | 285 void ProximityAuthWebUIHandler::InitGCMManager() { |
247 gcm_manager_.reset(new CryptAuthGCMManagerImpl(delegate_->GetGCMDriver(), | 286 gcm_manager_.reset(new CryptAuthGCMManagerImpl(delegate_->GetGCMDriver(), |
248 delegate_->GetPrefService())); | 287 delegate_->GetPrefService())); |
249 } | 288 } |
250 | 289 |
251 void ProximityAuthWebUIHandler::InitEnrollmentManager() { | 290 void ProximityAuthWebUIHandler::InitEnrollmentManager() { |
252 #if defined(OS_CHROMEOS) | 291 #if defined(OS_CHROMEOS) |
253 // TODO(tengs): We initialize a CryptAuthEnrollmentManager here for | 292 // TODO(tengs): We initialize a CryptAuthEnrollmentManager here for |
254 // development and testing purposes until it is ready to be moved into Chrome. | 293 // development and testing purposes until it is ready to be moved into Chrome. |
255 // The public/private key pair has been generated and serialized in a previous | 294 // The public/private key pair has been generated and serialized in a previous |
256 // session. | 295 // session. |
257 std::string user_public_key; | |
258 Base64UrlDecode( | 296 Base64UrlDecode( |
259 "CAESRgohAD1lP_wgQ8XqVVwz4aK_89SqdvAQG5L_NZH5zXxwg5UbEiEAZFMlgCZ9h8OlyE4" | 297 "CAESRgohAD1lP_wgQ8XqVVwz4aK_89SqdvAQG5L_NZH5zXxwg5UbEiEAZFMlgCZ9h8OlyE4" |
260 "QYKY5oiOBu0FmLSKeTAXEq2jnVJI=", | 298 "QYKY5oiOBu0FmLSKeTAXEq2jnVJI=", |
261 &user_public_key); | 299 &user_public_key_); |
262 | 300 |
263 std::string user_private_key; | |
264 Base64UrlDecode( | 301 Base64UrlDecode( |
265 "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP____8AAAABAAAAAAA" | 302 "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP____8AAAABAAAAAAA" |
266 "AAAAAAAAA________________MFsEIP____8AAAABAAAAAAAAAAAAAAAA______________" | 303 "AAAAAAAAA________________MFsEIP____8AAAABAAAAAAAAAAAAAAAA______________" |
267 "_8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw-J9JgSwMVAMSdNgiG5wSTamZ44ROdJ" | 304 "_8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw-J9JgSwMVAMSdNgiG5wSTamZ44ROdJ" |
268 "reBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li_hp_m47n60p8" | 305 "reBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li_hp_m47n60p8" |
269 "D54WK84zV2sxXs7LtkBoN79R9QIhAP____8AAAAA__________-85vqtpxeehPO5ysL8YyV" | 306 "D54WK84zV2sxXs7LtkBoN79R9QIhAP____8AAAAA__________-85vqtpxeehPO5ysL8YyV" |
270 "RAgEBBG0wawIBAQQgKZ4Dsm5xe4p5U2XPGxjrG376ZWWIa9E6r0y1BdjIntyhRANCAAQ9ZT" | 307 "RAgEBBG0wawIBAQQgKZ4Dsm5xe4p5U2XPGxjrG376ZWWIa9E6r0y1BdjIntyhRANCAAQ9ZT" |
271 "_8IEPF6lVcM-Giv_PUqnbwEBuS_zWR-c18cIOVG2RTJYAmfYfDpchOEGCmOaIjgbtBZi0in" | 308 "_8IEPF6lVcM-Giv_PUqnbwEBuS_zWR-c18cIOVG2RTJYAmfYfDpchOEGCmOaIjgbtBZi0in" |
272 "kwFxKto51SS", | 309 "kwFxKto51SS", |
273 &user_private_key); | 310 &user_private_key_); |
274 | 311 |
275 // This serialized DeviceInfo proto was previously captured from a real | 312 // This serialized DeviceInfo proto was previously captured from a real |
276 // CryptAuth enrollment, and is replayed here for testing purposes. | 313 // CryptAuth enrollment, and is replayed here for testing purposes. |
277 std::string serialized_device_info; | 314 std::string serialized_device_info; |
278 Base64UrlDecode( | 315 Base64UrlDecode( |
279 "IkoIARJGCiEAX_ZjLSq73EVcrarX-7l7No7nSP86GEC322ocSZKqUKwSIQDbEDu9KN7AgLM" | 316 "IkoIARJGCiEAX_ZjLSq73EVcrarX-7l7No7nSP86GEC322ocSZKqUKwSIQDbEDu9KN7AgLM" |
280 "v_lzZZNui9zSOgXCeDpLhS2tgrYVXijoEbGlua0IFZW4tVVNKSggBEkYKIQBf9mMtKrvcRV" | 317 "v_lzZZNui9zSOgXCeDpLhS2tgrYVXijoEbGlua0IFZW4tVVNKSggBEkYKIQBf9mMtKrvcRV" |
281 "ytqtf7uXs2judI_zoYQLfbahxJkqpQrBIhANsQO70o3sCAsy_-XNlk26L3NI6BcJ4OkuFLa" | 318 "ytqtf7uXs2judI_zoYQLfbahxJkqpQrBIhANsQO70o3sCAsy_-XNlk26L3NI6BcJ4OkuFLa" |
282 "2CthVeKam9Nb3ppbGxhLzUuMCAoWDExOyBDck9TIHg4Nl82NCA3MTM0LjAuMCkgQXBwbGVX" | 319 "2CthVeKam9Nb3ppbGxhLzUuMCAoWDExOyBDck9TIHg4Nl82NCA3MTM0LjAuMCkgQXBwbGVX" |
283 "ZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzQ1LjAuMjQyMi4wIFN" | 320 "ZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzQ1LjAuMjQyMi4wIFN" |
(...skipping 11 matching lines...) Expand all Loading... |
295 "bF9JVWY4YTJDSmJNbXFqaWpYUFYzaVV5dmJXSVRrR3d1bFRaVUs3RGVZczJtT0h5ZkQ1NWR" | 332 "bF9JVWY4YTJDSmJNbXFqaWpYUFYzaVV5dmJXSVRrR3d1bFRaVUs3RGVZczJtT0h5ZkQ1NWR" |
296 "HRXEtdnJTdVc4VEZ2Z1haa2xhVEZTN0dqM2xCVUktSHd5Z0h6bHZHX2NGLWtzQmw0dXdveG" | 333 "HRXEtdnJTdVc4VEZ2Z1haa2xhVEZTN0dqM2xCVUktSHd5Z0h6bHZHX2NGLWtzQmw0dXdveG" |
297 "VPWE1hRlJ3WGJHVUU1Tm9sLS1mdkRIcGVZVnJR", | 334 "VPWE1hRlJ3WGJHVUU1Tm9sLS1mdkRIcGVZVnJR", |
298 &serialized_device_info); | 335 &serialized_device_info); |
299 cryptauth::GcmDeviceInfo device_info; | 336 cryptauth::GcmDeviceInfo device_info; |
300 device_info.ParseFromString(serialized_device_info); | 337 device_info.ParseFromString(serialized_device_info); |
301 | 338 |
302 enrollment_manager_.reset(new CryptAuthEnrollmentManager( | 339 enrollment_manager_.reset(new CryptAuthEnrollmentManager( |
303 make_scoped_ptr(new base::DefaultClock()), | 340 make_scoped_ptr(new base::DefaultClock()), |
304 make_scoped_ptr(new CryptAuthEnrollerFactoryImpl(delegate_)), | 341 make_scoped_ptr(new CryptAuthEnrollerFactoryImpl(delegate_)), |
305 user_public_key, user_private_key, device_info, gcm_manager_.get(), | 342 user_public_key_, user_private_key_, device_info, gcm_manager_.get(), |
306 delegate_->GetPrefService())); | 343 delegate_->GetPrefService())); |
307 enrollment_manager_->AddObserver(this); | 344 enrollment_manager_->AddObserver(this); |
308 enrollment_manager_->Start(); | 345 enrollment_manager_->Start(); |
309 #endif | 346 #endif |
310 } | 347 } |
311 | 348 |
312 void ProximityAuthWebUIHandler::InitDeviceManager() { | 349 void ProximityAuthWebUIHandler::InitDeviceManager() { |
313 // TODO(tengs): We initialize a CryptAuthDeviceManager here for | 350 // TODO(tengs): We initialize a CryptAuthDeviceManager here for |
314 // development and testing purposes until it is ready to be moved into Chrome. | 351 // development and testing purposes until it is ready to be moved into Chrome. |
315 device_manager_.reset(new CryptAuthDeviceManager( | 352 device_manager_.reset(new CryptAuthDeviceManager( |
(...skipping 23 matching lines...) Expand all Loading... |
339 ineligible_devices.Append(IneligibleDeviceToDictionary(ineligible_device)); | 376 ineligible_devices.Append(IneligibleDeviceToDictionary(ineligible_device)); |
340 } | 377 } |
341 | 378 |
342 PA_LOG(INFO) << "Found " << eligible_devices.GetSize() | 379 PA_LOG(INFO) << "Found " << eligible_devices.GetSize() |
343 << " eligible devices and " << ineligible_devices.GetSize() | 380 << " eligible devices and " << ineligible_devices.GetSize() |
344 << " ineligible devices."; | 381 << " ineligible devices."; |
345 web_ui()->CallJavascriptFunction("CryptAuthInterface.onGotEligibleDevices", | 382 web_ui()->CallJavascriptFunction("CryptAuthInterface.onGotEligibleDevices", |
346 eligible_devices, ineligible_devices); | 383 eligible_devices, ineligible_devices); |
347 } | 384 } |
348 | 385 |
349 void ProximityAuthWebUIHandler::GetSyncStates(const base::ListValue* args) { | 386 void ProximityAuthWebUIHandler::GetLocalState(const base::ListValue* args) { |
350 scoped_ptr<base::DictionaryValue> enrollment_state = | 387 scoped_ptr<base::DictionaryValue> enrollment_state = |
351 GetEnrollmentStateDictionary(); | 388 GetEnrollmentStateDictionary(); |
352 scoped_ptr<base::DictionaryValue> device_sync_state = | 389 scoped_ptr<base::DictionaryValue> device_sync_state = |
353 GetDeviceSyncStateDictionary(); | 390 GetDeviceSyncStateDictionary(); |
354 PA_LOG(INFO) << "Enrollment State: \n" << *enrollment_state | 391 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList(); |
355 << "Device Sync State: \n" << *device_sync_state; | 392 |
356 web_ui()->CallJavascriptFunction("SyncStateInterface.onGotSyncStates", | 393 PA_LOG(INFO) << "==== Got Local State ====\n" |
357 *enrollment_state, *device_sync_state); | 394 << "Enrollment State: \n" << *enrollment_state |
| 395 << "Device Sync State: \n" << *device_sync_state |
| 396 << "Unlock Keys: \n" << *unlock_keys; |
| 397 web_ui()->CallJavascriptFunction("LocalStateInterface.onGotLocalState", |
| 398 *enrollment_state, *device_sync_state, |
| 399 *unlock_keys); |
358 } | 400 } |
359 | 401 |
360 scoped_ptr<base::DictionaryValue> | 402 scoped_ptr<base::DictionaryValue> |
361 ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() { | 403 ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() { |
362 if (!enrollment_manager_) | 404 if (!enrollment_manager_) |
363 return make_scoped_ptr(new base::DictionaryValue()); | 405 return make_scoped_ptr(new base::DictionaryValue()); |
364 | 406 |
365 return CreateSyncStateDictionary( | 407 return CreateSyncStateDictionary( |
366 enrollment_manager_->GetLastEnrollmentTime().ToJsTime(), | 408 enrollment_manager_->GetLastEnrollmentTime().ToJsTime(), |
367 enrollment_manager_->GetTimeToNextAttempt().InMillisecondsF(), | 409 enrollment_manager_->GetTimeToNextAttempt().InMillisecondsF(), |
368 enrollment_manager_->IsRecoveringFromFailure(), | 410 enrollment_manager_->IsRecoveringFromFailure(), |
369 enrollment_manager_->IsEnrollmentInProgress()); | 411 enrollment_manager_->IsEnrollmentInProgress()); |
370 } | 412 } |
371 | 413 |
372 scoped_ptr<base::DictionaryValue> | 414 scoped_ptr<base::DictionaryValue> |
373 ProximityAuthWebUIHandler::GetDeviceSyncStateDictionary() { | 415 ProximityAuthWebUIHandler::GetDeviceSyncStateDictionary() { |
374 if (!device_manager_) | 416 if (!device_manager_) |
375 return make_scoped_ptr(new base::DictionaryValue()); | 417 return make_scoped_ptr(new base::DictionaryValue()); |
376 | 418 |
377 return CreateSyncStateDictionary( | 419 return CreateSyncStateDictionary( |
378 device_manager_->GetLastSyncTime().ToJsTime(), | 420 device_manager_->GetLastSyncTime().ToJsTime(), |
379 device_manager_->GetTimeToNextAttempt().InMillisecondsF(), | 421 device_manager_->GetTimeToNextAttempt().InMillisecondsF(), |
380 device_manager_->IsRecoveringFromFailure(), | 422 device_manager_->IsRecoveringFromFailure(), |
381 device_manager_->IsSyncInProgress()); | 423 device_manager_->IsSyncInProgress()); |
382 } | 424 } |
383 | 425 |
| 426 scoped_ptr<base::ListValue> ProximityAuthWebUIHandler::GetUnlockKeysList() { |
| 427 scoped_ptr<base::ListValue> unlock_keys(new base::ListValue()); |
| 428 if (!device_manager_) |
| 429 return unlock_keys; |
| 430 |
| 431 for (const auto& unlock_key : device_manager_->unlock_keys()) { |
| 432 unlock_keys->Append(ExternalDeviceInfoToDictionary(unlock_key)); |
| 433 } |
| 434 |
| 435 return unlock_keys; |
| 436 } |
| 437 |
| 438 Connection* ProximityAuthWebUIHandler::GetConnection() { |
| 439 Connection* connection = bluetooth_connection_.get(); |
| 440 if (client_) { |
| 441 DCHECK(!connection); |
| 442 connection = client_->connection(); |
| 443 } |
| 444 return connection; |
| 445 } |
| 446 |
| 447 void ProximityAuthWebUIHandler::OnPSKDerived( |
| 448 const cryptauth::ExternalDeviceInfo& unlock_key, |
| 449 const std::string& persistent_symmetric_key) { |
| 450 if (persistent_symmetric_key.empty()) { |
| 451 PA_LOG(ERROR) << "Failed to derive PSK."; |
| 452 return; |
| 453 } |
| 454 |
| 455 RemoteDevice remote_device( |
| 456 unlock_key.friendly_device_name(), unlock_key.public_key(), |
| 457 unlock_key.bluetooth_address(), persistent_symmetric_key); |
| 458 |
| 459 bluetooth_connection_.reset(new BluetoothConnection( |
| 460 remote_device, device::BluetoothUUID(kBluetoothServiceUUID))); |
| 461 bluetooth_connection_->AddObserver(this); |
| 462 |
| 463 // This SeekDeviceByAddress operation is needed to connect to a device if |
| 464 // it is not already known to the local device. |
| 465 bluetooth_util::SeekDeviceByAddress( |
| 466 remote_device.bluetooth_address, |
| 467 base::Bind(&ProximityAuthWebUIHandler::OnSeekedDeviceByAddress, |
| 468 weak_ptr_factory_.GetWeakPtr()), |
| 469 base::Bind(&ProximityAuthWebUIHandler::OnSeekedDeviceByAddressError, |
| 470 weak_ptr_factory_.GetWeakPtr()), |
| 471 content::BrowserThread::GetBlockingPool() |
| 472 ->GetTaskRunnerWithShutdownBehavior( |
| 473 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) |
| 474 .get()); |
| 475 } |
| 476 |
| 477 void ProximityAuthWebUIHandler::OnSeekedDeviceByAddress() { |
| 478 PA_LOG(INFO) << "Found Bluetooth device: " |
| 479 << bluetooth_connection_->remote_device().bluetooth_address; |
| 480 bluetooth_connection_->Connect(); |
| 481 } |
| 482 |
| 483 void ProximityAuthWebUIHandler::OnSeekedDeviceByAddressError( |
| 484 const std::string& error_message) { |
| 485 PA_LOG(WARNING) << "Failed to seek device by address: " |
| 486 << bluetooth_connection_->remote_device().bluetooth_address; |
| 487 } |
| 488 |
| 489 void ProximityAuthWebUIHandler::OnAuthenticationResult( |
| 490 Authenticator::Result result, |
| 491 scoped_ptr<SecureContext> secure_context) { |
| 492 secure_context_ = secure_context.Pass(); |
| 493 |
| 494 // Create the ClientImpl asynchronously. |client_| registers itself as an |
| 495 // observer of |bluetooth_connection_|, so creating it synchronously would |
| 496 // trigger |OnSendComplete()| as an observer call for |client_|. |
| 497 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 498 FROM_HERE, |
| 499 base::Bind(&ProximityAuthWebUIHandler::CreateStatusUpdateClient, |
| 500 weak_ptr_factory_.GetWeakPtr())); |
| 501 } |
| 502 |
| 503 void ProximityAuthWebUIHandler::CreateStatusUpdateClient() { |
| 504 client_.reset( |
| 505 new ClientImpl(bluetooth_connection_.Pass(), secure_context_.Pass())); |
| 506 client_->AddObserver(this); |
| 507 } |
| 508 |
| 509 scoped_ptr<base::DictionaryValue> |
| 510 ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary( |
| 511 const cryptauth::ExternalDeviceInfo& device_info) { |
| 512 std::string base64_public_key; |
| 513 Base64UrlEncode(device_info.public_key(), &base64_public_key); |
| 514 |
| 515 // Set the fields in the ExternalDeviceInfo proto. |
| 516 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); |
| 517 dictionary->SetString(kExternalDevicePublicKey, base64_public_key); |
| 518 dictionary->SetString(kExternalDeviceFriendlyName, |
| 519 device_info.friendly_device_name()); |
| 520 dictionary->SetString(kExternalDeviceBluetoothAddress, |
| 521 device_info.bluetooth_address()); |
| 522 dictionary->SetBoolean(kExternalDeviceUnlockKey, device_info.unlock_key()); |
| 523 dictionary->SetString(kExternalDeviceConnectionStatus, |
| 524 kExternalDeviceDisconnected); |
| 525 |
| 526 if (!device_manager_) |
| 527 return dictionary; |
| 528 |
| 529 // If |device_info| is a known unlock key, then combine the proto data with |
| 530 // the corresponding local device data (e.g. connection status and remote |
| 531 // status updates). |
| 532 std::string public_key = device_info.public_key(); |
| 533 auto iterator = std::find_if( |
| 534 device_manager_->unlock_keys().begin(), |
| 535 device_manager_->unlock_keys().end(), |
| 536 [&public_key](const cryptauth::ExternalDeviceInfo& unlock_key) { |
| 537 return unlock_key.public_key() == public_key; |
| 538 }); |
| 539 |
| 540 if (iterator == device_manager_->unlock_keys().end()) |
| 541 return dictionary; |
| 542 |
| 543 // Fill in the current Bluetooth connection status. |
| 544 Connection* connection = GetConnection(); |
| 545 if (!connection || |
| 546 connection->remote_device().public_key != device_info.public_key()) |
| 547 return dictionary; |
| 548 |
| 549 std::string connection_status = kExternalDeviceDisconnected; |
| 550 if (connection->IsConnected()) { |
| 551 connection_status = kExternalDeviceConnected; |
| 552 } else if (connection->status() == Connection::IN_PROGRESS) { |
| 553 connection_status = kExternalDeviceConnecting; |
| 554 } |
| 555 dictionary->SetString(kExternalDeviceConnectionStatus, connection_status); |
| 556 |
| 557 // Fill the remote status dictionary. |
| 558 if (last_remote_status_update_) { |
| 559 scoped_ptr<base::DictionaryValue> status_dictionary( |
| 560 new base::DictionaryValue()); |
| 561 status_dictionary->SetInteger("userPresent", |
| 562 last_remote_status_update_->user_presence); |
| 563 status_dictionary->SetInteger( |
| 564 "secureScreenLock", |
| 565 last_remote_status_update_->secure_screen_lock_state); |
| 566 status_dictionary->SetInteger( |
| 567 "trustAgent", last_remote_status_update_->trust_agent_state); |
| 568 dictionary->Set(kExternalDeviceRemoteState, status_dictionary.Pass()); |
| 569 } |
| 570 |
| 571 return dictionary; |
| 572 } |
| 573 |
| 574 scoped_ptr<base::DictionaryValue> |
| 575 ProximityAuthWebUIHandler::IneligibleDeviceToDictionary( |
| 576 const cryptauth::IneligibleDevice& ineligible_device) { |
| 577 scoped_ptr<base::ListValue> ineligibility_reasons(new base::ListValue()); |
| 578 for (const std::string& reason : ineligible_device.reasons()) { |
| 579 ineligibility_reasons->AppendString(reason); |
| 580 } |
| 581 |
| 582 scoped_ptr<base::DictionaryValue> device_dictionary = |
| 583 ExternalDeviceInfoToDictionary(ineligible_device.device()); |
| 584 device_dictionary->Set(kIneligibleDeviceReasons, |
| 585 ineligibility_reasons.Pass()); |
| 586 return device_dictionary; |
| 587 } |
| 588 |
| 589 void ProximityAuthWebUIHandler::OnConnectionStatusChanged( |
| 590 Connection* connection, |
| 591 Connection::Status old_status, |
| 592 Connection::Status new_status) { |
| 593 PA_LOG(INFO) << "Connection status changed from " << old_status << " to " |
| 594 << new_status; |
| 595 if (new_status == Connection::CONNECTED) { |
| 596 authenticator_.reset(new DeviceToDeviceAuthenticator( |
| 597 connection, delegate_->GetAccountId(), |
| 598 delegate_->CreateSecureMessageDelegate())); |
| 599 authenticator_->Authenticate( |
| 600 base::Bind(&ProximityAuthWebUIHandler::OnAuthenticationResult, |
| 601 weak_ptr_factory_.GetWeakPtr())); |
| 602 } else if (new_status == Connection::DISCONNECTED) { |
| 603 last_remote_status_update_.reset(); |
| 604 } |
| 605 |
| 606 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList(); |
| 607 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged", |
| 608 *unlock_keys); |
| 609 } |
| 610 |
| 611 void ProximityAuthWebUIHandler::OnMessageReceived(const Connection& connection, |
| 612 const WireMessage& message) { |
| 613 std::string address = connection.remote_device().bluetooth_address; |
| 614 PA_LOG(INFO) << "Message received from " << address; |
| 615 } |
| 616 |
| 617 void ProximityAuthWebUIHandler::OnRemoteStatusUpdate( |
| 618 const RemoteStatusUpdate& status_update) { |
| 619 PA_LOG(INFO) << "Remote status update:" |
| 620 << "\n user_presence: " |
| 621 << static_cast<int>(status_update.user_presence) |
| 622 << "\n secure_screen_lock_state: " |
| 623 << static_cast<int>(status_update.secure_screen_lock_state) |
| 624 << "\n trust_agent_state: " |
| 625 << static_cast<int>(status_update.trust_agent_state); |
| 626 |
| 627 last_remote_status_update_.reset(new RemoteStatusUpdate(status_update)); |
| 628 scoped_ptr<base::ListValue> unlock_keys = GetUnlockKeysList(); |
| 629 web_ui()->CallJavascriptFunction("LocalStateInterface.onUnlockKeysChanged", |
| 630 *unlock_keys); |
| 631 } |
| 632 |
384 } // namespace proximity_auth | 633 } // namespace proximity_auth |
OLD | NEW |