openvpn_management_server_unittest.cc revision 3273da7039841d15fc160cc69c036e3124803744
1// Copyright (c) 2012 The Chromium OS 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 "shill/openvpn_management_server.h"
6
7#include <netinet/in.h>
8
9#include <chromeos/dbus/service_constants.h>
10#include <gtest/gtest.h>
11
12#include "shill/glib.h"
13#include "shill/key_value_store.h"
14#include "shill/mock_event_dispatcher.h"
15#include "shill/mock_openvpn_driver.h"
16#include "shill/mock_sockets.h"
17
18using base::Bind;
19using base::Unretained;
20using std::string;
21using std::vector;
22using testing::_;
23using testing::Assign;
24using testing::InSequence;
25using testing::Return;
26using testing::ReturnNew;
27
28namespace shill {
29
30namespace {
31MATCHER_P(VoidStringEq, value, "") {
32  return value == reinterpret_cast<const char *>(arg);
33}
34}  // namespace {}
35
36class OpenVPNManagementServerTest : public testing::Test {
37 public:
38  OpenVPNManagementServerTest()
39      : server_(&driver_, &glib_) {}
40
41  virtual ~OpenVPNManagementServerTest() {}
42
43 protected:
44  static const int kConnectedSocket;
45
46  void SetSockets() { server_.sockets_ = &sockets_; }
47  void SetDispatcher() { server_.dispatcher_ = &dispatcher_; }
48  void ExpectNotStarted() { EXPECT_FALSE(server_.IsStarted()); }
49
50  void SetConnectedSocket() {
51    server_.connected_socket_ = kConnectedSocket;
52    SetSockets();
53  }
54
55  void ExpectSend(const string &value) {
56    EXPECT_CALL(sockets_,
57                Send(kConnectedSocket, VoidStringEq(value), value.size(), 0))
58        .WillOnce(Return(value.size()));
59  }
60
61  void ExpectStaticChallengeResponse() {
62    driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
63    driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
64    driver_.args()->SetString(flimflam::kOpenVPNOTPProperty, "123456");
65    SetConnectedSocket();
66    ExpectSend("username \"Auth\" jojo\n");
67    ExpectSend("password \"Auth\" \"SCRV1:eW95bw==:MTIzNDU2\"\n");
68  }
69
70  void ExpectAuthenticationResponse() {
71    driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
72    driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
73    SetConnectedSocket();
74    ExpectSend("username \"Auth\" jojo\n");
75    ExpectSend("password \"Auth\" \"yoyo\"\n");
76  }
77
78  void ExpectPINResponse() {
79    driver_.args()->SetString(flimflam::kOpenVPNPinProperty, "987654");
80    SetConnectedSocket();
81    ExpectSend("password \"User-Specific TPM Token FOO\" \"987654\"\n");
82  }
83
84  void ExpectHoldRelease() {
85    SetConnectedSocket();
86    ExpectSend("hold release\n");
87  }
88
89  void ExpectRestart() {
90    SetConnectedSocket();
91    ExpectSend("signal SIGUSR1\n");
92  }
93
94  InputData CreateInputDataFromString(const string &str) {
95    InputData data(
96        reinterpret_cast<unsigned char *>(const_cast<char *>(str.data())),
97        str.size());
98    return data;
99  }
100
101  void SendSignal(const string &signal) {
102    server_.SendSignal(signal);
103  }
104
105  void OnInput(InputData *data) {
106    server_.OnInput(data);
107  }
108
109  void ProcessMessage(const string &message) {
110    server_.ProcessMessage(message);
111  }
112
113  bool ProcessSuccessMessage(const string &message) {
114    return server_.ProcessSuccessMessage(message);
115  }
116
117  bool ProcessStateMessage(const string &message) {
118    return server_.ProcessStateMessage(message);
119  }
120
121  bool GetHoldWaiting() { return server_.hold_waiting_; }
122
123  GLib glib_;
124  MockOpenVPNDriver driver_;
125  OpenVPNManagementServer server_;
126  MockSockets sockets_;
127  MockEventDispatcher dispatcher_;
128};
129
130// static
131const int OpenVPNManagementServerTest::kConnectedSocket = 555;
132
133TEST_F(OpenVPNManagementServerTest, StartStarted) {
134  SetSockets();
135  EXPECT_TRUE(server_.Start(NULL, NULL, NULL));
136}
137
138TEST_F(OpenVPNManagementServerTest, StartSocketFail) {
139  EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
140      .WillOnce(Return(-1));
141  EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
142  ExpectNotStarted();
143}
144
145TEST_F(OpenVPNManagementServerTest, StartGetSockNameFail) {
146  const int kSocket = 123;
147  EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
148      .WillOnce(Return(kSocket));
149  EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
150  EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
151  EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(-1));
152  EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
153  EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
154  ExpectNotStarted();
155}
156
157TEST_F(OpenVPNManagementServerTest, Start) {
158  const int kSocket = 123;
159  EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
160      .WillOnce(Return(kSocket));
161  EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
162  EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
163  EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(0));
164  EXPECT_CALL(dispatcher_,
165              CreateReadyHandler(kSocket, IOHandler::kModeInput, _))
166      .WillOnce(ReturnNew<IOHandler>());
167  vector<string> options;
168  EXPECT_TRUE(server_.Start(&dispatcher_, &sockets_, &options));
169  EXPECT_EQ(&sockets_, server_.sockets_);
170  EXPECT_EQ(kSocket, server_.socket_);
171  EXPECT_TRUE(server_.ready_handler_.get());
172  EXPECT_EQ(&dispatcher_, server_.dispatcher_);
173  EXPECT_FALSE(options.empty());
174}
175
176TEST_F(OpenVPNManagementServerTest, Stop) {
177  SetSockets();
178  server_.input_handler_.reset(new IOHandler());
179  const int kConnectedSocket = 234;
180  server_.connected_socket_ = kConnectedSocket;
181  EXPECT_CALL(sockets_, Close(kConnectedSocket)).WillOnce(Return(0));
182  SetDispatcher();
183  server_.ready_handler_.reset(new IOHandler());
184  const int kSocket = 345;
185  server_.socket_ = kSocket;
186  EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
187  server_.Stop();
188  EXPECT_FALSE(server_.input_handler_.get());
189  EXPECT_EQ(-1, server_.connected_socket_);
190  EXPECT_FALSE(server_.dispatcher_);
191  EXPECT_FALSE(server_.ready_handler_.get());
192  EXPECT_EQ(-1, server_.socket_);
193  ExpectNotStarted();
194}
195
196TEST_F(OpenVPNManagementServerTest, OnReadyAcceptFail) {
197  const int kSocket = 333;
198  SetSockets();
199  EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL)).WillOnce(Return(-1));
200  server_.OnReady(kSocket);
201  EXPECT_EQ(-1, server_.connected_socket_);
202}
203
204TEST_F(OpenVPNManagementServerTest, OnReady) {
205  const int kSocket = 111;
206  SetConnectedSocket();
207  SetDispatcher();
208  EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL))
209      .WillOnce(Return(kConnectedSocket));
210  server_.ready_handler_.reset(new IOHandler());
211  EXPECT_CALL(dispatcher_, CreateInputHandler(kConnectedSocket, _, _))
212      .WillOnce(ReturnNew<IOHandler>());
213  ExpectSend("state on\n");
214  server_.OnReady(kSocket);
215  EXPECT_EQ(kConnectedSocket, server_.connected_socket_);
216  EXPECT_FALSE(server_.ready_handler_.get());
217  EXPECT_TRUE(server_.input_handler_.get());
218}
219
220TEST_F(OpenVPNManagementServerTest, OnInput) {
221  {
222    string s;
223    InputData data = CreateInputDataFromString(s);
224    OnInput(&data);
225  }
226  {
227    string s = "foo\n"
228        ">INFO:...\n"
229        ">PASSWORD:Need 'Auth' SC:user/password/otp\n"
230        ">PASSWORD:Need 'User-Specific TPM Token FOO' ...\n"
231        ">PASSWORD:Verification Failed: .\n"
232        ">STATE:123,RECONNECTING,detail,...,...\n"
233        ">HOLD:Waiting for hold release\n"
234        "SUCCESS: Hold released.";
235    InputData data = CreateInputDataFromString(s);
236    ExpectStaticChallengeResponse();
237    ExpectPINResponse();
238    EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
239    EXPECT_CALL(driver_, OnReconnecting(_));
240    EXPECT_FALSE(GetHoldWaiting());
241    OnInput(&data);
242    EXPECT_TRUE(GetHoldWaiting());
243  }
244}
245
246TEST_F(OpenVPNManagementServerTest, OnInputStop) {
247  string s =
248      ">PASSWORD:Verification Failed: .\n"
249      ">STATE:123,RECONNECTING,detail,...,...";
250  InputData data = CreateInputDataFromString(s);
251  SetSockets();
252  // Stops the server after the first message is processed.
253  EXPECT_CALL(driver_, Cleanup(Service::kStateFailure))
254      .WillOnce(Assign(&server_.sockets_, reinterpret_cast<Sockets *>(NULL)));
255  // The second message should not be processed.
256  EXPECT_CALL(driver_, OnReconnecting(_)).Times(0);
257  OnInput(&data);
258}
259
260TEST_F(OpenVPNManagementServerTest, ProcessMessage) {
261  ProcessMessage("foo");
262  ProcessMessage(">INFO:");
263
264  EXPECT_CALL(driver_, OnReconnecting(_));
265  ProcessMessage(">STATE:123,RECONNECTING,detail,...,...");
266}
267
268TEST_F(OpenVPNManagementServerTest, ProcessSuccessMessage) {
269  EXPECT_FALSE(ProcessSuccessMessage("foo"));
270  EXPECT_TRUE(ProcessSuccessMessage("SUCCESS: foo"));
271}
272
273TEST_F(OpenVPNManagementServerTest, ProcessInfoMessage) {
274  EXPECT_FALSE(server_.ProcessInfoMessage("foo"));
275  EXPECT_TRUE(server_.ProcessInfoMessage(">INFO:foo"));
276}
277
278TEST_F(OpenVPNManagementServerTest, ProcessStateMessage) {
279  EXPECT_FALSE(ProcessStateMessage("foo"));
280  EXPECT_TRUE(ProcessStateMessage(">STATE:123,WAIT,detail,...,..."));
281  {
282    InSequence seq;
283    EXPECT_CALL(driver_,
284                OnReconnecting(OpenVPNDriver::kReconnectReasonUnknown));
285    EXPECT_CALL(driver_,
286                OnReconnecting(OpenVPNDriver::kReconnectReasonTLSError));
287  }
288  EXPECT_TRUE(ProcessStateMessage(">STATE:123,RECONNECTING,detail,...,..."));
289  EXPECT_TRUE(ProcessStateMessage(">STATE:123,RECONNECTING,tls-error,...,..."));
290}
291
292TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC) {
293  ExpectStaticChallengeResponse();
294  EXPECT_TRUE(
295      server_.ProcessNeedPasswordMessage(
296          ">PASSWORD:Need 'Auth' SC:user/password/otp"));
297  EXPECT_FALSE(driver_.args()->ContainsString(flimflam::kOpenVPNOTPProperty));
298}
299
300TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuth) {
301  ExpectAuthenticationResponse();
302  EXPECT_TRUE(
303      server_.ProcessNeedPasswordMessage(
304          ">PASSWORD:Need 'Auth' username/password"));
305}
306
307TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken) {
308  ExpectPINResponse();
309  EXPECT_TRUE(
310      server_.ProcessNeedPasswordMessage(
311          ">PASSWORD:Need 'User-Specific TPM Token FOO' ..."));
312}
313
314TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown) {
315  EXPECT_FALSE(server_.ProcessNeedPasswordMessage("foo"));
316}
317
318TEST_F(OpenVPNManagementServerTest, ParseNeedPasswordTag) {
319  EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag(""));
320  EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag(" "));
321  EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag("'"));
322  EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag("''"));
323  EXPECT_EQ("bar",
324            OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'zoo"));
325  EXPECT_EQ("bar", OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'"));
326  EXPECT_EQ("bar", OpenVPNManagementServer::ParseNeedPasswordTag("'bar'zoo"));
327  EXPECT_EQ("bar",
328            OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'zoo'moo"));
329}
330
331TEST_F(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds) {
332  EXPECT_CALL(driver_, Cleanup(Service::kStateFailure)).Times(3);
333  server_.PerformStaticChallenge("Auth");
334  driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
335  server_.PerformStaticChallenge("Auth");
336  driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
337  server_.PerformStaticChallenge("Auth");
338}
339
340TEST_F(OpenVPNManagementServerTest, PerformStaticChallenge) {
341  ExpectStaticChallengeResponse();
342  server_.PerformStaticChallenge("Auth");
343  EXPECT_FALSE(driver_.args()->ContainsString(flimflam::kOpenVPNOTPProperty));
344}
345
346TEST_F(OpenVPNManagementServerTest, PerformAuthenticationNoCreds) {
347  EXPECT_CALL(driver_, Cleanup(Service::kStateFailure)).Times(2);
348  server_.PerformAuthentication("Auth");
349  driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
350  server_.PerformAuthentication("Auth");
351}
352
353TEST_F(OpenVPNManagementServerTest, PerformAuthentication) {
354  ExpectAuthenticationResponse();
355  server_.PerformAuthentication("Auth");
356}
357
358TEST_F(OpenVPNManagementServerTest, ProcessHoldMessage) {
359  EXPECT_FALSE(server_.hold_release_);
360  EXPECT_FALSE(server_.hold_waiting_);
361
362  EXPECT_FALSE(server_.ProcessHoldMessage("foo"));
363
364  EXPECT_TRUE(server_.ProcessHoldMessage(">HOLD:Waiting for hold release"));
365  EXPECT_FALSE(server_.hold_release_);
366  EXPECT_TRUE(server_.hold_waiting_);
367
368  ExpectHoldRelease();
369  server_.hold_release_ = true;
370  server_.hold_waiting_ = false;
371  EXPECT_TRUE(server_.ProcessHoldMessage(">HOLD:Waiting for hold release"));
372  EXPECT_TRUE(server_.hold_release_);
373  EXPECT_FALSE(server_.hold_waiting_);
374}
375
376TEST_F(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN) {
377  EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
378  server_.SupplyTPMToken("User-Specific TPM Token FOO");
379}
380
381TEST_F(OpenVPNManagementServerTest, SupplyTPMToken) {
382  ExpectPINResponse();
383  server_.SupplyTPMToken("User-Specific TPM Token FOO");
384}
385
386TEST_F(OpenVPNManagementServerTest, Send) {
387  const char kMessage[] = "foo\n";
388  SetConnectedSocket();
389  ExpectSend(kMessage);
390  server_.Send(kMessage);
391}
392
393TEST_F(OpenVPNManagementServerTest, SendState) {
394  SetConnectedSocket();
395  ExpectSend("state off\n");
396  server_.SendState("off");
397}
398
399TEST_F(OpenVPNManagementServerTest, SendUsername) {
400  SetConnectedSocket();
401  ExpectSend("username \"Auth\" joesmith\n");
402  server_.SendUsername("Auth", "joesmith");
403}
404
405TEST_F(OpenVPNManagementServerTest, SendPassword) {
406  SetConnectedSocket();
407  ExpectSend("password \"Auth\" \"foo\\\"bar\"\n");
408  server_.SendPassword("Auth", "foo\"bar");
409}
410
411TEST_F(OpenVPNManagementServerTest, ProcessFailedPasswordMessage) {
412  EXPECT_FALSE(server_.ProcessFailedPasswordMessage("foo"));
413  EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
414  EXPECT_TRUE(
415      server_.ProcessFailedPasswordMessage(">PASSWORD:Verification Failed: ."));
416}
417
418TEST_F(OpenVPNManagementServerTest, SendSignal) {
419  SetConnectedSocket();
420  ExpectSend("signal SIGUSR2\n");
421  SendSignal("SIGUSR2");
422}
423
424TEST_F(OpenVPNManagementServerTest, Restart) {
425  ExpectRestart();
426  server_.Restart();
427}
428
429TEST_F(OpenVPNManagementServerTest, SendHoldRelease) {
430  ExpectHoldRelease();
431  server_.SendHoldRelease();
432}
433
434TEST_F(OpenVPNManagementServerTest, Hold) {
435  EXPECT_FALSE(server_.hold_release_);
436  EXPECT_FALSE(server_.hold_waiting_);
437
438  server_.ReleaseHold();
439  EXPECT_TRUE(server_.hold_release_);
440  EXPECT_FALSE(server_.hold_waiting_);
441
442  server_.Hold();
443  EXPECT_FALSE(server_.hold_release_);
444  EXPECT_FALSE(server_.hold_waiting_);
445
446  server_.hold_waiting_ = true;
447  ExpectHoldRelease();
448  server_.ReleaseHold();
449  EXPECT_TRUE(server_.hold_release_);
450  EXPECT_FALSE(server_.hold_waiting_);
451}
452
453TEST_F(OpenVPNManagementServerTest, EscapeToQuote) {
454  EXPECT_EQ("", OpenVPNManagementServer::EscapeToQuote(""));
455  EXPECT_EQ("foo './", OpenVPNManagementServer::EscapeToQuote("foo './"));
456  EXPECT_EQ("\\\\", OpenVPNManagementServer::EscapeToQuote("\\"));
457  EXPECT_EQ("\\\"", OpenVPNManagementServer::EscapeToQuote("\""));
458  EXPECT_EQ("\\\\\\\"foo\\\\bar\\\"",
459            OpenVPNManagementServer::EscapeToQuote("\\\"foo\\bar\""));
460}
461
462}  // namespace shill
463