| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "remoting/host/security_key/gnubby_extension_session.h" | 5 #include "remoting/host/security_key/security_key_extension_session.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "remoting/base/logging.h" | 13 #include "remoting/base/logging.h" |
| 14 #include "remoting/host/client_session_details.h" | 14 #include "remoting/host/client_session_details.h" |
| 15 #include "remoting/host/security_key/gnubby_auth_handler.h" | 15 #include "remoting/host/security_key/security_key_auth_handler.h" |
| 16 #include "remoting/proto/control.pb.h" | 16 #include "remoting/proto/control.pb.h" |
| 17 #include "remoting/protocol/client_stub.h" | 17 #include "remoting/protocol/client_stub.h" |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 // Used as the type attribute of all Security Key protocol::ExtensionMessages. | 21 // Used as the type attribute of all Security Key protocol::ExtensionMessages. |
| 22 const char kExtensionMessageType[] = "gnubby-auth"; | 22 const char kExtensionMessageType[] = "gnubby-auth"; |
| 23 | 23 |
| 24 // Gnubby extension message data members. | 24 // SecurityKey extension message data members. |
| 25 const char kConnectionId[] = "connectionId"; | 25 const char kConnectionId[] = "connectionId"; |
| 26 const char kControlMessage[] = "control"; | 26 const char kControlMessage[] = "control"; |
| 27 const char kControlOption[] = "option"; | 27 const char kControlOption[] = "option"; |
| 28 const char kDataMessage[] = "data"; | 28 const char kDataMessage[] = "data"; |
| 29 const char kDataPayload[] = "data"; | 29 const char kDataPayload[] = "data"; |
| 30 const char kErrorMessage[] = "error"; | 30 const char kErrorMessage[] = "error"; |
| 31 const char kGnubbyAuthV1[] = "auth-v1"; | 31 const char kSecurityKeyAuthV1[] = "auth-v1"; |
| 32 const char kMessageType[] = "type"; | 32 const char kMessageType[] = "type"; |
| 33 | 33 |
| 34 // Returns the command code (the first byte of the data) if it exists, or -1 if | 34 // Returns the command code (the first byte of the data) if it exists, or -1 if |
| 35 // the data is empty. | 35 // the data is empty. |
| 36 unsigned int GetCommandCode(const std::string& data) { | 36 unsigned int GetCommandCode(const std::string& data) { |
| 37 return data.empty() ? -1 : static_cast<unsigned int>(data[0]); | 37 return data.empty() ? -1 : static_cast<unsigned int>(data[0]); |
| 38 } | 38 } |
| 39 | 39 |
| 40 // Creates a string of byte data from a ListValue of numbers. Returns true if | 40 // Creates a string of byte data from a ListValue of numbers. Returns true if |
| 41 // all of the list elements are numbers. | 41 // all of the list elements are numbers. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 53 out->push_back(static_cast<char>(value)); | 53 out->push_back(static_cast<char>(value)); |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 return true; | 56 return true; |
| 57 } | 57 } |
| 58 | 58 |
| 59 } // namespace | 59 } // namespace |
| 60 | 60 |
| 61 namespace remoting { | 61 namespace remoting { |
| 62 | 62 |
| 63 GnubbyExtensionSession::GnubbyExtensionSession( | 63 SecurityKeyExtensionSession::SecurityKeyExtensionSession( |
| 64 ClientSessionDetails* client_session_details, | 64 ClientSessionDetails* client_session_details, |
| 65 protocol::ClientStub* client_stub) | 65 protocol::ClientStub* client_stub) |
| 66 : client_stub_(client_stub) { | 66 : client_stub_(client_stub) { |
| 67 DCHECK(client_stub_); | 67 DCHECK(client_stub_); |
| 68 | 68 |
| 69 gnubby_auth_handler_ = remoting::GnubbyAuthHandler::Create( | 69 security_key_auth_handler_ = remoting::SecurityKeyAuthHandler::Create( |
| 70 client_session_details, | 70 client_session_details, |
| 71 base::Bind(&GnubbyExtensionSession::SendMessageToClient, | 71 base::Bind(&SecurityKeyExtensionSession::SendMessageToClient, |
| 72 base::Unretained(this))); | 72 base::Unretained(this))); |
| 73 } | 73 } |
| 74 | 74 |
| 75 GnubbyExtensionSession::~GnubbyExtensionSession() {} | 75 SecurityKeyExtensionSession::~SecurityKeyExtensionSession() {} |
| 76 | 76 |
| 77 // Returns true if the |message| is a Security Key ExtensionMessage. | 77 // Returns true if the |message| is a Security Key ExtensionMessage. |
| 78 // This is done so the host does not pass |message| to other HostExtensions. | 78 // This is done so the host does not pass |message| to other HostExtensions. |
| 79 // TODO(joedow): Use |client_session_details| to disconnect the session if we | 79 // TODO(joedow): Use |client_session_details| to disconnect the session if we |
| 80 // receive an invalid extension message. | 80 // receive an invalid extension message. |
| 81 bool GnubbyExtensionSession::OnExtensionMessage( | 81 bool SecurityKeyExtensionSession::OnExtensionMessage( |
| 82 ClientSessionDetails* client_session_details, | 82 ClientSessionDetails* client_session_details, |
| 83 protocol::ClientStub* client_stub, | 83 protocol::ClientStub* client_stub, |
| 84 const protocol::ExtensionMessage& message) { | 84 const protocol::ExtensionMessage& message) { |
| 85 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
| 86 | 86 |
| 87 if (message.type() != kExtensionMessageType) { | 87 if (message.type() != kExtensionMessageType) { |
| 88 return false; | 88 return false; |
| 89 } | 89 } |
| 90 | 90 |
| 91 std::unique_ptr<base::Value> value = base::JSONReader::Read(message.data()); | 91 std::unique_ptr<base::Value> value = base::JSONReader::Read(message.data()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 107 ProcessDataMessage(client_message); | 107 ProcessDataMessage(client_message); |
| 108 } else if (type == kErrorMessage) { | 108 } else if (type == kErrorMessage) { |
| 109 ProcessErrorMessage(client_message); | 109 ProcessErrorMessage(client_message); |
| 110 } else { | 110 } else { |
| 111 VLOG(2) << "Unknown gnubby-auth message type: " << type; | 111 VLOG(2) << "Unknown gnubby-auth message type: " << type; |
| 112 } | 112 } |
| 113 | 113 |
| 114 return true; | 114 return true; |
| 115 } | 115 } |
| 116 | 116 |
| 117 void GnubbyExtensionSession::ProcessControlMessage( | 117 void SecurityKeyExtensionSession::ProcessControlMessage( |
| 118 base::DictionaryValue* message_data) const { | 118 base::DictionaryValue* message_data) const { |
| 119 std::string option; | 119 std::string option; |
| 120 if (!message_data->GetString(kControlOption, &option)) { | 120 if (!message_data->GetString(kControlOption, &option)) { |
| 121 LOG(WARNING) << "Could not extract control option from message."; | 121 LOG(WARNING) << "Could not extract control option from message."; |
| 122 return; | 122 return; |
| 123 } | 123 } |
| 124 | 124 |
| 125 if (option == kGnubbyAuthV1) { | 125 if (option == kSecurityKeyAuthV1) { |
| 126 gnubby_auth_handler_->CreateGnubbyConnection(); | 126 security_key_auth_handler_->CreateSecurityKeyConnection(); |
| 127 } else { | 127 } else { |
| 128 VLOG(2) << "Invalid gnubby-auth control option: " << option; | 128 VLOG(2) << "Invalid gnubby-auth control option: " << option; |
| 129 } | 129 } |
| 130 } | 130 } |
| 131 | 131 |
| 132 void GnubbyExtensionSession::ProcessDataMessage( | 132 void SecurityKeyExtensionSession::ProcessDataMessage( |
| 133 base::DictionaryValue* message_data) const { | 133 base::DictionaryValue* message_data) const { |
| 134 int connection_id; | 134 int connection_id; |
| 135 if (!message_data->GetInteger(kConnectionId, &connection_id)) { | 135 if (!message_data->GetInteger(kConnectionId, &connection_id)) { |
| 136 LOG(WARNING) << "Could not extract connection id from message."; | 136 LOG(WARNING) << "Could not extract connection id from message."; |
| 137 return; | 137 return; |
| 138 } | 138 } |
| 139 | 139 |
| 140 if (!gnubby_auth_handler_->IsValidConnectionId(connection_id)) { | 140 if (!security_key_auth_handler_->IsValidConnectionId(connection_id)) { |
| 141 LOG(WARNING) << "Unknown gnubby-auth data connection: '" << connection_id | 141 LOG(WARNING) << "Unknown gnubby-auth data connection: '" << connection_id |
| 142 << "'"; | 142 << "'"; |
| 143 return; | 143 return; |
| 144 } | 144 } |
| 145 | 145 |
| 146 base::ListValue* bytes; | 146 base::ListValue* bytes; |
| 147 std::string response; | 147 std::string response; |
| 148 if (message_data->GetList(kDataPayload, &bytes) && | 148 if (message_data->GetList(kDataPayload, &bytes) && |
| 149 ConvertListValueToString(bytes, &response)) { | 149 ConvertListValueToString(bytes, &response)) { |
| 150 HOST_LOG << "Sending gnubby response: " << GetCommandCode(response); | 150 HOST_LOG << "Sending security key response: " << GetCommandCode(response); |
| 151 gnubby_auth_handler_->SendClientResponse(connection_id, response); | 151 security_key_auth_handler_->SendClientResponse(connection_id, response); |
| 152 } else { | 152 } else { |
| 153 LOG(WARNING) << "Could not extract response data from message."; | 153 LOG(WARNING) << "Could not extract response data from message."; |
| 154 gnubby_auth_handler_->SendErrorAndCloseConnection(connection_id); | 154 security_key_auth_handler_->SendErrorAndCloseConnection(connection_id); |
| 155 return; | 155 return; |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 | 158 |
| 159 void GnubbyExtensionSession::ProcessErrorMessage( | 159 void SecurityKeyExtensionSession::ProcessErrorMessage( |
| 160 base::DictionaryValue* message_data) const { | 160 base::DictionaryValue* message_data) const { |
| 161 int connection_id; | 161 int connection_id; |
| 162 if (!message_data->GetInteger(kConnectionId, &connection_id)) { | 162 if (!message_data->GetInteger(kConnectionId, &connection_id)) { |
| 163 LOG(WARNING) << "Could not extract connection id from message."; | 163 LOG(WARNING) << "Could not extract connection id from message."; |
| 164 return; | 164 return; |
| 165 } | 165 } |
| 166 | 166 |
| 167 if (gnubby_auth_handler_->IsValidConnectionId(connection_id)) { | 167 if (security_key_auth_handler_->IsValidConnectionId(connection_id)) { |
| 168 HOST_LOG << "Sending gnubby error"; | 168 HOST_LOG << "Sending security key error"; |
| 169 gnubby_auth_handler_->SendErrorAndCloseConnection(connection_id); | 169 security_key_auth_handler_->SendErrorAndCloseConnection(connection_id); |
| 170 } else { | 170 } else { |
| 171 LOG(WARNING) << "Unknown gnubby-auth data connection: '" << connection_id | 171 LOG(WARNING) << "Unknown gnubby-auth data connection: '" << connection_id |
| 172 << "'"; | 172 << "'"; |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 void GnubbyExtensionSession::SendMessageToClient( | 176 void SecurityKeyExtensionSession::SendMessageToClient( |
| 177 int connection_id, | 177 int connection_id, |
| 178 const std::string& data) const { | 178 const std::string& data) const { |
| 179 DCHECK(thread_checker_.CalledOnValidThread()); | 179 DCHECK(thread_checker_.CalledOnValidThread()); |
| 180 DCHECK(client_stub_); | 180 DCHECK(client_stub_); |
| 181 | 181 |
| 182 base::DictionaryValue request; | 182 base::DictionaryValue request; |
| 183 request.SetString(kMessageType, kDataMessage); | 183 request.SetString(kMessageType, kDataMessage); |
| 184 request.SetInteger(kConnectionId, connection_id); | 184 request.SetInteger(kConnectionId, connection_id); |
| 185 | 185 |
| 186 std::unique_ptr<base::ListValue> bytes(new base::ListValue()); | 186 std::unique_ptr<base::ListValue> bytes(new base::ListValue()); |
| 187 for (std::string::const_iterator i = data.begin(); i != data.end(); ++i) { | 187 for (std::string::const_iterator i = data.begin(); i != data.end(); ++i) { |
| 188 bytes->AppendInteger(static_cast<unsigned char>(*i)); | 188 bytes->AppendInteger(static_cast<unsigned char>(*i)); |
| 189 } | 189 } |
| 190 request.Set(kDataPayload, bytes.release()); | 190 request.Set(kDataPayload, bytes.release()); |
| 191 | 191 |
| 192 std::string request_json; | 192 std::string request_json; |
| 193 CHECK(base::JSONWriter::Write(request, &request_json)); | 193 CHECK(base::JSONWriter::Write(request, &request_json)); |
| 194 | 194 |
| 195 protocol::ExtensionMessage message; | 195 protocol::ExtensionMessage message; |
| 196 message.set_type(kExtensionMessageType); | 196 message.set_type(kExtensionMessageType); |
| 197 message.set_data(request_json); | 197 message.set_data(request_json); |
| 198 | 198 |
| 199 client_stub_->DeliverHostMessage(message); | 199 client_stub_->DeliverHostMessage(message); |
| 200 } | 200 } |
| 201 | 201 |
| 202 void GnubbyExtensionSession::SetGnubbyAuthHandlerForTesting( | 202 void SecurityKeyExtensionSession::SetSecurityKeyAuthHandlerForTesting( |
| 203 std::unique_ptr<GnubbyAuthHandler> gnubby_auth_handler) { | 203 std::unique_ptr<SecurityKeyAuthHandler> security_key_auth_handler) { |
| 204 DCHECK(gnubby_auth_handler); | 204 DCHECK(security_key_auth_handler); |
| 205 | 205 |
| 206 gnubby_auth_handler_ = std::move(gnubby_auth_handler); | 206 security_key_auth_handler_ = std::move(security_key_auth_handler); |
| 207 gnubby_auth_handler_->SetSendMessageCallback(base::Bind( | 207 security_key_auth_handler_->SetSendMessageCallback( |
| 208 &GnubbyExtensionSession::SendMessageToClient, base::Unretained(this))); | 208 base::Bind(&SecurityKeyExtensionSession::SendMessageToClient, |
| 209 base::Unretained(this))); |
| 209 } | 210 } |
| 210 | 211 |
| 211 } // namespace remoting | 212 } // namespace remoting |
| OLD | NEW |