OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/host/security_key/security_key_ipc_client.h" | |
6 | |
7 #include <memory> | |
8 #include <string> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/macros.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "ipc/ipc_channel.h" | |
15 #include "remoting/host/security_key/fake_ipc_security_key_auth_handler.h" | |
16 #include "remoting/host/security_key/fake_security_key_ipc_server.h" | |
17 #include "remoting/host/security_key/security_key_ipc_constants.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 namespace { | |
21 const int kTestConnectionId = 1; | |
22 const char kNonexistentIpcChannelName[] = "Nonexistent_IPC_Channel"; | |
23 const char kValidIpcChannelName[] = "Security_Key_Ipc_Client_Test_Channel."; | |
24 const int kLargeMessageSizeBytes = 256 * 1024; | |
25 } // namespace | |
26 | |
27 namespace remoting { | |
28 | |
29 class SecurityKeyIpcClientTest : public testing::Test { | |
30 public: | |
31 SecurityKeyIpcClientTest(); | |
32 ~SecurityKeyIpcClientTest() override; | |
33 | |
34 // Passed to the object used for testing to be called back to signal | |
35 // completion of an IPC channel state change or reception of an IPC message. | |
36 void OperationComplete(bool failed); | |
37 | |
38 // Used as a callback given to the object under test, expected to be called | |
39 // back when a security key request is received by it. | |
40 void SendMessageToClient(int connection_id, const std::string& data); | |
41 | |
42 // Used as a callback given to the object under test, expected to be called | |
43 // back when a security key response is sent. | |
44 void ClientMessageReceived(const std::string& response_payload); | |
45 | |
46 protected: | |
47 // testing::Test interface. | |
48 void SetUp() override; | |
49 | |
50 // Waits until the current |run_loop_| instance is signaled, then resets it. | |
51 void WaitForOperationComplete(); | |
52 | |
53 // Sets up an active IPC connection between |security_key_ipc_client_| | |
54 // and |fake_ipc_server_|. |expect_success| defines whether the operation | |
55 // is expected to succeed or fail. | |
56 void EstablishConnection(bool expect_success); | |
57 | |
58 // Sends a security key request from |security_key_ipc_client_| and | |
59 // a response from |fake_ipc_server_| and verifies the payloads for both. | |
60 void SendRequestAndResponse(const std::string& request_data, | |
61 const std::string& response_data); | |
62 | |
63 // Creates a unique IPC channel name to use for testing. | |
64 std::string GenerateUniqueTestChannelName(); | |
65 | |
66 // IPC tests require a valid MessageLoop to run. | |
67 base::MessageLoopForIO message_loop_; | |
68 | |
69 // Used to allow |message_loop_| to run during tests. The instance is reset | |
70 // after each stage of the tests has been completed. | |
71 std::unique_ptr<base::RunLoop> run_loop_; | |
72 | |
73 // The object under test. | |
74 SecurityKeyIpcClient security_key_ipc_client_; | |
75 | |
76 // Provides a connection details message to |security_key_ipc_client_| | |
77 // for testing. | |
78 FakeIpcSecurityKeyAuthHandler fake_security_key_auth_handler_; | |
79 | |
80 // Used to send/receive security key IPC messages for testing. | |
81 FakeSecurityKeyIpcServer fake_ipc_server_; | |
82 | |
83 // Stores the current session ID on supported platforms. | |
84 uint32_t session_id_ = 0; | |
85 | |
86 // Tracks the success/failure of the last async operation. | |
87 bool operation_failed_ = false; | |
88 | |
89 // Used to validate the object under test uses the correct ID when | |
90 // communicating over the IPC channel. | |
91 int last_connection_id_received_ = -1; | |
92 | |
93 // Stores the contents of the last IPC message received for validation. | |
94 std::string last_message_received_; | |
95 | |
96 private: | |
97 DISALLOW_COPY_AND_ASSIGN(SecurityKeyIpcClientTest); | |
98 }; | |
99 | |
100 SecurityKeyIpcClientTest::SecurityKeyIpcClientTest() | |
101 : run_loop_(new base::RunLoop()), | |
102 fake_ipc_server_( | |
103 kTestConnectionId, | |
104 /*peer_session_id=*/UINT32_MAX, | |
105 /*initial_connect_timeout=*/base::TimeDelta::FromMilliseconds(500), | |
106 base::Bind(&SecurityKeyIpcClientTest::SendMessageToClient, | |
107 base::Unretained(this)), | |
108 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
109 base::Unretained(this), | |
110 /*failed=*/false)) {} | |
111 | |
112 SecurityKeyIpcClientTest::~SecurityKeyIpcClientTest() {} | |
113 | |
114 void SecurityKeyIpcClientTest::SetUp() { | |
115 #if defined(OS_WIN) | |
116 DWORD session_id = 0; | |
117 // If we are on Windows, then we need to set the correct session ID or the | |
118 // IPC connection will not be created successfully. | |
119 ASSERT_TRUE(ProcessIdToSessionId(GetCurrentProcessId(), &session_id)); | |
120 session_id_ = session_id; | |
121 security_key_ipc_client_.SetExpectedIpcServerSessionIdForTest(session_id_); | |
122 #endif // defined(OS_WIN) | |
123 } | |
124 | |
125 void SecurityKeyIpcClientTest::OperationComplete(bool failed) { | |
126 operation_failed_ |= failed; | |
127 run_loop_->Quit(); | |
128 } | |
129 | |
130 void SecurityKeyIpcClientTest::WaitForOperationComplete() { | |
131 run_loop_->Run(); | |
132 run_loop_.reset(new base::RunLoop()); | |
133 } | |
134 | |
135 void SecurityKeyIpcClientTest::SendMessageToClient(int connection_id, | |
136 const std::string& data) { | |
137 last_connection_id_received_ = connection_id; | |
138 last_message_received_ = data; | |
139 OperationComplete(/*failed=*/false); | |
140 } | |
141 | |
142 void SecurityKeyIpcClientTest::ClientMessageReceived( | |
143 const std::string& response_payload) { | |
144 last_message_received_ = response_payload; | |
145 OperationComplete(/*failed=*/false); | |
146 } | |
147 | |
148 std::string SecurityKeyIpcClientTest::GenerateUniqueTestChannelName() { | |
149 return GetChannelNamePathPrefixForTest() + kValidIpcChannelName + | |
150 IPC::Channel::GenerateUniqueRandomChannelID(); | |
151 } | |
152 | |
153 void SecurityKeyIpcClientTest::EstablishConnection(bool expect_success) { | |
154 // Start up the security key forwarding session IPC channel first, that way | |
155 // we can provide the channel using the fake SecurityKeyAuthHandler later on. | |
156 std::string ipc_session_channel_name = GenerateUniqueTestChannelName(); | |
157 ASSERT_TRUE(fake_ipc_server_.CreateChannel( | |
158 ipc_session_channel_name, | |
159 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
160 ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized(ipc_session_channel_name)); | |
161 fake_security_key_auth_handler_.set_ipc_security_key_channel_name( | |
162 ipc_session_channel_name); | |
163 | |
164 // Set up the channel name for the initial IPC channel. | |
165 std::string ipc_server_channel_name = GenerateUniqueTestChannelName(); | |
166 fake_security_key_auth_handler_.set_ipc_server_channel_name( | |
167 ipc_server_channel_name); | |
168 security_key_ipc_client_.SetInitialIpcChannelNameForTest( | |
169 ipc_server_channel_name); | |
170 | |
171 // Create the initial IPC channel and verify it was set up correctly. | |
172 ASSERT_FALSE(security_key_ipc_client_.WaitForSecurityKeyIpcServerChannel()); | |
173 fake_security_key_auth_handler_.CreateSecurityKeyConnection(); | |
174 ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized(ipc_server_channel_name)); | |
175 ASSERT_TRUE(security_key_ipc_client_.WaitForSecurityKeyIpcServerChannel()); | |
176 | |
177 // Establish the IPC channel so we can begin sending and receiving security | |
178 // key messages. | |
179 security_key_ipc_client_.EstablishIpcConnection( | |
180 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
181 base::Unretained(this), /*failed=*/false), | |
182 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
183 base::Unretained(this), /*failed=*/true)); | |
184 WaitForOperationComplete(); | |
185 ASSERT_NE(operation_failed_, expect_success); | |
186 } | |
187 | |
188 void SecurityKeyIpcClientTest::SendRequestAndResponse( | |
189 const std::string& request_data, | |
190 const std::string& response_data) { | |
191 ASSERT_TRUE(security_key_ipc_client_.SendSecurityKeyRequest( | |
192 request_data, base::Bind(&SecurityKeyIpcClientTest::ClientMessageReceived, | |
193 base::Unretained(this)))); | |
194 WaitForOperationComplete(); | |
195 ASSERT_FALSE(operation_failed_); | |
196 ASSERT_EQ(last_connection_id_received_, kTestConnectionId); | |
197 ASSERT_EQ(last_message_received_, request_data); | |
198 | |
199 ASSERT_TRUE(fake_ipc_server_.SendResponse(response_data)); | |
200 WaitForOperationComplete(); | |
201 ASSERT_FALSE(operation_failed_); | |
202 ASSERT_EQ(last_message_received_, response_data); | |
203 } | |
204 | |
205 TEST_F(SecurityKeyIpcClientTest, GenerateSingleSecurityKeyRequest) { | |
206 EstablishConnection(/*expect_success=*/true); | |
207 | |
208 SendRequestAndResponse("Auth me!", "You've been authed!"); | |
209 | |
210 security_key_ipc_client_.CloseIpcConnection(); | |
211 } | |
212 | |
213 TEST_F(SecurityKeyIpcClientTest, GenerateLargeSecurityKeyRequest) { | |
214 EstablishConnection(/*expect_success=*/true); | |
215 | |
216 SendRequestAndResponse(std::string(kLargeMessageSizeBytes, 'Y'), | |
217 std::string(kLargeMessageSizeBytes, 'Z')); | |
218 | |
219 security_key_ipc_client_.CloseIpcConnection(); | |
220 } | |
221 | |
222 TEST_F(SecurityKeyIpcClientTest, GenerateReallyLargeSecurityKeyRequest) { | |
223 EstablishConnection(/*expect_success=*/true); | |
224 | |
225 SendRequestAndResponse(std::string(kLargeMessageSizeBytes * 2, 'Y'), | |
226 std::string(kLargeMessageSizeBytes * 2, 'Z')); | |
227 | |
228 security_key_ipc_client_.CloseIpcConnection(); | |
229 } | |
230 | |
231 TEST_F(SecurityKeyIpcClientTest, GenerateMultipleSecurityKeyRequest) { | |
232 EstablishConnection(/*expect_success=*/true); | |
233 | |
234 SendRequestAndResponse("Auth me 1!", "You've been authed once!"); | |
235 SendRequestAndResponse("Auth me 2!", "You've been authed twice!"); | |
236 SendRequestAndResponse("Auth me 3!", "You've been authed thrice!"); | |
237 | |
238 security_key_ipc_client_.CloseIpcConnection(); | |
239 } | |
240 | |
241 TEST_F(SecurityKeyIpcClientTest, ServerClosesConnectionAfterRequestTimeout) { | |
242 EstablishConnection(/*expect_success=*/true); | |
243 fake_ipc_server_.CloseChannel(); | |
244 WaitForOperationComplete(); | |
245 ASSERT_FALSE(operation_failed_); | |
246 } | |
247 | |
248 TEST_F(SecurityKeyIpcClientTest, | |
249 SecondSecurityKeyRequestBeforeFirstResponseReceived) { | |
250 EstablishConnection(/*expect_success=*/true); | |
251 | |
252 ASSERT_TRUE(security_key_ipc_client_.SendSecurityKeyRequest( | |
253 "First Request", | |
254 base::Bind(&SecurityKeyIpcClientTest::ClientMessageReceived, | |
255 base::Unretained(this)))); | |
256 WaitForOperationComplete(); | |
257 ASSERT_FALSE(operation_failed_); | |
258 | |
259 ASSERT_FALSE(security_key_ipc_client_.SendSecurityKeyRequest( | |
260 "Second Request", | |
261 base::Bind(&SecurityKeyIpcClientTest::ClientMessageReceived, | |
262 base::Unretained(this)))); | |
263 } | |
264 | |
265 TEST_F(SecurityKeyIpcClientTest, ReceiveSecurityKeyResponseWithEmptyPayload) { | |
266 EstablishConnection(/*expect_success=*/true); | |
267 | |
268 ASSERT_TRUE(security_key_ipc_client_.SendSecurityKeyRequest( | |
269 "Valid request", | |
270 base::Bind(&SecurityKeyIpcClientTest::ClientMessageReceived, | |
271 base::Unretained(this)))); | |
272 WaitForOperationComplete(); | |
273 ASSERT_FALSE(operation_failed_); | |
274 | |
275 ASSERT_TRUE(fake_ipc_server_.SendResponse("")); | |
276 WaitForOperationComplete(); | |
277 ASSERT_TRUE(operation_failed_); | |
278 } | |
279 | |
280 TEST_F(SecurityKeyIpcClientTest, SendRequestBeforeEstablishingConnection) { | |
281 // Sending a request will fail since the IPC connection has not been | |
282 // established. | |
283 ASSERT_FALSE(security_key_ipc_client_.SendSecurityKeyRequest( | |
284 "Too soon!!", base::Bind(&SecurityKeyIpcClientTest::ClientMessageReceived, | |
285 base::Unretained(this)))); | |
286 } | |
287 | |
288 TEST_F(SecurityKeyIpcClientTest, NonExistentMainIpcServerChannel) { | |
289 std::string ipc_server_channel_name(kNonexistentIpcChannelName); | |
290 security_key_ipc_client_.SetInitialIpcChannelNameForTest( | |
291 ipc_server_channel_name); | |
292 | |
293 // Attempt to establish the conection (should fail since the IPC channel does | |
294 // not exist). | |
295 security_key_ipc_client_.EstablishIpcConnection( | |
296 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
297 base::Unretained(this), /*failed=*/false), | |
298 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
299 base::Unretained(this), /*failed=*/true)); | |
300 WaitForOperationComplete(); | |
301 ASSERT_TRUE(operation_failed_); | |
302 } | |
303 | |
304 TEST_F(SecurityKeyIpcClientTest, NonExistentIpcSessionChannel) { | |
305 fake_security_key_auth_handler_.set_ipc_security_key_channel_name( | |
306 kNonexistentIpcChannelName); | |
307 | |
308 // Set up the channel name for the initial IPC channel. | |
309 std::string ipc_server_channel_name = GenerateUniqueTestChannelName(); | |
310 fake_security_key_auth_handler_.set_ipc_server_channel_name( | |
311 ipc_server_channel_name); | |
312 security_key_ipc_client_.SetInitialIpcChannelNameForTest( | |
313 ipc_server_channel_name); | |
314 | |
315 // Create the initial IPC channel and verify it was set up correctly. | |
316 ASSERT_FALSE(security_key_ipc_client_.WaitForSecurityKeyIpcServerChannel()); | |
317 fake_security_key_auth_handler_.CreateSecurityKeyConnection(); | |
318 ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized(ipc_server_channel_name)); | |
319 ASSERT_TRUE(security_key_ipc_client_.WaitForSecurityKeyIpcServerChannel()); | |
320 | |
321 // Attempt to establish the conection (should fail since the IPC channel does | |
322 // not exist). | |
323 security_key_ipc_client_.EstablishIpcConnection( | |
324 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
325 base::Unretained(this), /*failed=*/false), | |
326 base::Bind(&SecurityKeyIpcClientTest::OperationComplete, | |
327 base::Unretained(this), /*failed=*/true)); | |
328 WaitForOperationComplete(); | |
329 ASSERT_TRUE(operation_failed_); | |
330 } | |
331 | |
332 #if defined(OS_WIN) | |
333 TEST_F(SecurityKeyIpcClientTest, SecurityKeyIpcServerRunningInWrongSession) { | |
334 // Set the expected session Id to a different session than we are running in. | |
335 security_key_ipc_client_.SetExpectedIpcServerSessionIdForTest(session_id_ + | |
336 1); | |
337 | |
338 // Attempting to establish a connection should fail here since the IPC Server | |
339 // is 'running' in a different session than expected. | |
340 EstablishConnection(/*expect_success=*/false); | |
341 } | |
342 #endif // defined(OS_WIN) | |
343 | |
344 } // namespace remoting | |
OLD | NEW |