blob: 049470a7f470d43f07993c1e4177f145d49a1161 [file] [log] [blame]
Darin Petkov1c115202012-03-22 15:35:47 +01001// 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
Darin Petkov271fe522012-03-27 13:47:29 +02007#include <netinet/in.h>
8
Darin Petkov683942b2012-03-27 18:00:04 +02009#include <chromeos/dbus/service_constants.h>
Darin Petkov1c115202012-03-22 15:35:47 +010010#include <gtest/gtest.h>
11
Darin Petkov683942b2012-03-27 18:00:04 +020012#include "shill/glib.h"
Darin Petkov1c115202012-03-22 15:35:47 +010013#include "shill/key_value_store.h"
Darin Petkov271fe522012-03-27 13:47:29 +020014#include "shill/mock_event_dispatcher.h"
Darin Petkov1c115202012-03-22 15:35:47 +010015#include "shill/mock_openvpn_driver.h"
Darin Petkov271fe522012-03-27 13:47:29 +020016#include "shill/mock_sockets.h"
17
18using std::string;
Darin Petkov46463022012-03-29 14:57:32 +020019using std::vector;
Darin Petkov271fe522012-03-27 13:47:29 +020020using testing::_;
21using testing::Return;
22using testing::ReturnNew;
Darin Petkov1c115202012-03-22 15:35:47 +010023
24namespace shill {
25
Darin Petkov271fe522012-03-27 13:47:29 +020026namespace {
27MATCHER_P(CallbackEq, callback, "") {
28 return arg.Equals(callback);
29}
30
31MATCHER_P(VoidStringEq, value, "") {
32 return value == reinterpret_cast<const char *>(arg);
33}
34} // namespace {}
35
Darin Petkov1c115202012-03-22 15:35:47 +010036class OpenVPNManagementServerTest : public testing::Test {
37 public:
38 OpenVPNManagementServerTest()
Paul Stewart451aa7f2012-04-11 19:07:58 -070039 : server_(&driver_, &glib_) {}
Darin Petkov1c115202012-03-22 15:35:47 +010040
41 virtual ~OpenVPNManagementServerTest() {}
42
Darin Petkov271fe522012-03-27 13:47:29 +020043 void SetSockets() { server_.sockets_ = &sockets_; }
44 void SetDispatcher() { server_.dispatcher_ = &dispatcher_; }
45 void ExpectNotStarted() { EXPECT_TRUE(server_.sockets_ == NULL); }
46
Darin Petkov683942b2012-03-27 18:00:04 +020047 void SetConnectedSocket() {
48 server_.connected_socket_ = kConnectedSocket;
49 SetSockets();
50 }
51
52 void ExpectSend(const string &value) {
53 EXPECT_CALL(sockets_,
54 Send(kConnectedSocket, VoidStringEq(value), value.size(), 0))
Darin Petkov271fe522012-03-27 13:47:29 +020055 .WillOnce(Return(value.size()));
56 }
57
Darin Petkov683942b2012-03-27 18:00:04 +020058 void ExpectStaticChallengeResponse() {
59 driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
60 driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
61 driver_.args()->SetString(flimflam::kOpenVPNOTPProperty, "123456");
62 SetConnectedSocket();
63 ExpectSend("username \"Auth\" jojo\n");
64 ExpectSend("password \"Auth\" \"SCRV1:eW95bw==:MTIzNDU2\"\n");
65 }
66
Darin Petkove0d5dd12012-04-04 16:10:48 +020067 void ExpectPINResponse() {
68 driver_.args()->SetString(flimflam::kOpenVPNPinProperty, "987654");
69 SetConnectedSocket();
70 ExpectSend("password \"User-Specific TPM Token FOO\" \"987654\"\n");
71 }
72
Darin Petkov271fe522012-03-27 13:47:29 +020073 InputData CreateInputDataFromString(const string &str) {
74 InputData data(
75 reinterpret_cast<unsigned char *>(const_cast<char *>(str.data())),
76 str.size());
77 return data;
78 }
79
Darin Petkov1c115202012-03-22 15:35:47 +010080 protected:
Darin Petkov683942b2012-03-27 18:00:04 +020081 static const int kConnectedSocket;
82
83 GLib glib_;
Darin Petkov1c115202012-03-22 15:35:47 +010084 MockOpenVPNDriver driver_;
85 OpenVPNManagementServer server_;
Darin Petkov271fe522012-03-27 13:47:29 +020086 MockSockets sockets_;
87 MockEventDispatcher dispatcher_;
Darin Petkov1c115202012-03-22 15:35:47 +010088};
89
Darin Petkov683942b2012-03-27 18:00:04 +020090// static
91const int OpenVPNManagementServerTest::kConnectedSocket = 555;
92
Darin Petkov271fe522012-03-27 13:47:29 +020093TEST_F(OpenVPNManagementServerTest, StartStarted) {
94 SetSockets();
Darin Petkov46463022012-03-29 14:57:32 +020095 EXPECT_TRUE(server_.Start(NULL, NULL, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +020096}
97
98TEST_F(OpenVPNManagementServerTest, StartSocketFail) {
99 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
100 .WillOnce(Return(-1));
Darin Petkov46463022012-03-29 14:57:32 +0200101 EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +0200102 ExpectNotStarted();
103}
104
105TEST_F(OpenVPNManagementServerTest, StartGetSockNameFail) {
106 const int kSocket = 123;
107 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
108 .WillOnce(Return(kSocket));
109 EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
110 EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
111 EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(-1));
112 EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
Darin Petkov46463022012-03-29 14:57:32 +0200113 EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +0200114 ExpectNotStarted();
115}
116
Darin Petkov78f63262012-03-26 01:30:24 +0200117TEST_F(OpenVPNManagementServerTest, Start) {
Darin Petkov271fe522012-03-27 13:47:29 +0200118 const int kSocket = 123;
119 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
120 .WillOnce(Return(kSocket));
121 EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
122 EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
123 EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(0));
124 EXPECT_CALL(dispatcher_,
125 CreateReadyHandler(kSocket, IOHandler::kModeInput,
126 CallbackEq(server_.ready_callback_)))
127 .WillOnce(ReturnNew<IOHandler>());
Darin Petkov46463022012-03-29 14:57:32 +0200128 vector<string> options;
129 EXPECT_TRUE(server_.Start(&dispatcher_, &sockets_, &options));
Darin Petkov271fe522012-03-27 13:47:29 +0200130 EXPECT_EQ(&sockets_, server_.sockets_);
131 EXPECT_EQ(kSocket, server_.socket_);
132 EXPECT_TRUE(server_.ready_handler_.get());
133 EXPECT_EQ(&dispatcher_, server_.dispatcher_);
Darin Petkov46463022012-03-29 14:57:32 +0200134 EXPECT_FALSE(options.empty());
Darin Petkov271fe522012-03-27 13:47:29 +0200135}
136
137TEST_F(OpenVPNManagementServerTest, Stop) {
138 SetSockets();
139 server_.input_handler_.reset(new IOHandler());
140 const int kConnectedSocket = 234;
141 server_.connected_socket_ = kConnectedSocket;
142 EXPECT_CALL(sockets_, Close(kConnectedSocket)).WillOnce(Return(0));
143 SetDispatcher();
144 server_.ready_handler_.reset(new IOHandler());
145 const int kSocket = 345;
146 server_.socket_ = kSocket;
147 EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
148 server_.Stop();
149 EXPECT_FALSE(server_.input_handler_.get());
150 EXPECT_EQ(-1, server_.connected_socket_);
151 EXPECT_FALSE(server_.dispatcher_);
152 EXPECT_FALSE(server_.ready_handler_.get());
153 EXPECT_EQ(-1, server_.socket_);
154 ExpectNotStarted();
155}
156
157TEST_F(OpenVPNManagementServerTest, OnReadyAcceptFail) {
158 const int kSocket = 333;
159 SetSockets();
160 EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL)).WillOnce(Return(-1));
161 server_.OnReady(kSocket);
162 EXPECT_EQ(-1, server_.connected_socket_);
163}
164
165TEST_F(OpenVPNManagementServerTest, OnReady) {
166 const int kSocket = 111;
Darin Petkov683942b2012-03-27 18:00:04 +0200167 SetConnectedSocket();
Darin Petkov271fe522012-03-27 13:47:29 +0200168 SetDispatcher();
169 EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL))
170 .WillOnce(Return(kConnectedSocket));
171 server_.ready_handler_.reset(new IOHandler());
172 EXPECT_CALL(dispatcher_,
173 CreateInputHandler(kConnectedSocket,
174 CallbackEq(server_.input_callback_)))
175 .WillOnce(ReturnNew<IOHandler>());
Darin Petkov683942b2012-03-27 18:00:04 +0200176 ExpectSend("state on\n");
Darin Petkov271fe522012-03-27 13:47:29 +0200177 server_.OnReady(kSocket);
178 EXPECT_EQ(kConnectedSocket, server_.connected_socket_);
179 EXPECT_FALSE(server_.ready_handler_.get());
180 EXPECT_TRUE(server_.input_handler_.get());
181}
182
183TEST_F(OpenVPNManagementServerTest, OnInput) {
184 {
185 string s;
186 InputData data = CreateInputDataFromString(s);
187 server_.OnInput(&data);
188 }
189 {
190 string s = "foo\n"
191 ">INFO:...\n"
Darin Petkov683942b2012-03-27 18:00:04 +0200192 ">PASSWORD:Need 'Auth' SC:user/password/otp\n"
Darin Petkove0d5dd12012-04-04 16:10:48 +0200193 ">PASSWORD:Need 'User-Specific TPM Token FOO' ...\n"
Darin Petkov0440b9b2012-04-17 16:11:56 +0200194 ">PASSWORD:Verification Failed: .\n"
Darin Petkov271fe522012-03-27 13:47:29 +0200195 ">STATE:123,RECONNECTING,detail,...,...";
196 InputData data = CreateInputDataFromString(s);
Darin Petkov683942b2012-03-27 18:00:04 +0200197 ExpectStaticChallengeResponse();
Darin Petkove0d5dd12012-04-04 16:10:48 +0200198 ExpectPINResponse();
Darin Petkov0440b9b2012-04-17 16:11:56 +0200199 EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
Darin Petkov271fe522012-03-27 13:47:29 +0200200 EXPECT_CALL(driver_, OnReconnecting());
201 server_.OnInput(&data);
202 }
203}
204
205TEST_F(OpenVPNManagementServerTest, ProcessMessage) {
206 server_.ProcessMessage("foo");
207 server_.ProcessMessage(">INFO:");
208
209 EXPECT_CALL(driver_, OnReconnecting());
210 server_.ProcessMessage(">STATE:123,RECONNECTING,detail,...,...");
211}
212
213TEST_F(OpenVPNManagementServerTest, ProcessInfoMessage) {
214 EXPECT_FALSE(server_.ProcessInfoMessage("foo"));
215 EXPECT_TRUE(server_.ProcessInfoMessage(">INFO:"));
216}
217
218TEST_F(OpenVPNManagementServerTest, ProcessStateMessage) {
219 EXPECT_FALSE(server_.ProcessStateMessage("foo"));
220 EXPECT_TRUE(server_.ProcessStateMessage(">STATE:123,WAIT,detail,...,..."));
221 EXPECT_CALL(driver_, OnReconnecting());
222 EXPECT_TRUE(
223 server_.ProcessStateMessage(">STATE:123,RECONNECTING,detail,...,..."));
224}
225
Darin Petkov683942b2012-03-27 18:00:04 +0200226TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageAuthSC) {
Darin Petkov683942b2012-03-27 18:00:04 +0200227 ExpectStaticChallengeResponse();
228 EXPECT_TRUE(
229 server_.ProcessNeedPasswordMessage(
230 ">PASSWORD:Need 'Auth' SC:user/password/otp"));
231 EXPECT_FALSE(driver_.args()->ContainsString(flimflam::kOpenVPNOTPProperty));
232}
233
Darin Petkove0d5dd12012-04-04 16:10:48 +0200234TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageTPMToken) {
235 ExpectPINResponse();
236 EXPECT_TRUE(
237 server_.ProcessNeedPasswordMessage(
238 ">PASSWORD:Need 'User-Specific TPM Token FOO' ..."));
239}
240
241TEST_F(OpenVPNManagementServerTest, ProcessNeedPasswordMessageUnknown) {
242 EXPECT_FALSE(server_.ProcessNeedPasswordMessage("foo"));
243}
244
245TEST_F(OpenVPNManagementServerTest, ParseNeedPasswordTag) {
246 EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag(""));
247 EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag(" "));
248 EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag("'"));
249 EXPECT_EQ("", OpenVPNManagementServer::ParseNeedPasswordTag("''"));
250 EXPECT_EQ("bar",
251 OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'zoo"));
252 EXPECT_EQ("bar", OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'"));
253 EXPECT_EQ("bar", OpenVPNManagementServer::ParseNeedPasswordTag("'bar'zoo"));
254 EXPECT_EQ("bar",
255 OpenVPNManagementServer::ParseNeedPasswordTag("foo'bar'zoo'moo"));
256}
257
Darin Petkov683942b2012-03-27 18:00:04 +0200258TEST_F(OpenVPNManagementServerTest, PerformStaticChallengeNoCreds) {
Darin Petkov0440b9b2012-04-17 16:11:56 +0200259 EXPECT_CALL(driver_, Cleanup(Service::kStateFailure)).Times(3);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200260 server_.PerformStaticChallenge("Auth");
Darin Petkov683942b2012-03-27 18:00:04 +0200261 driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
Darin Petkove0d5dd12012-04-04 16:10:48 +0200262 server_.PerformStaticChallenge("Auth");
Darin Petkov683942b2012-03-27 18:00:04 +0200263 driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
Darin Petkove0d5dd12012-04-04 16:10:48 +0200264 server_.PerformStaticChallenge("Auth");
Darin Petkov683942b2012-03-27 18:00:04 +0200265}
266
267TEST_F(OpenVPNManagementServerTest, PerformStaticChallenge) {
268 ExpectStaticChallengeResponse();
Darin Petkove0d5dd12012-04-04 16:10:48 +0200269 server_.PerformStaticChallenge("Auth");
Darin Petkov683942b2012-03-27 18:00:04 +0200270 EXPECT_FALSE(driver_.args()->ContainsString(flimflam::kOpenVPNOTPProperty));
271}
272
Darin Petkove0d5dd12012-04-04 16:10:48 +0200273TEST_F(OpenVPNManagementServerTest, SupplyTPMTokenNoPIN) {
Darin Petkov0440b9b2012-04-17 16:11:56 +0200274 EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
Darin Petkove0d5dd12012-04-04 16:10:48 +0200275 server_.SupplyTPMToken("User-Specific TPM Token FOO");
276}
277
278TEST_F(OpenVPNManagementServerTest, SupplyTPMToken) {
279 ExpectPINResponse();
280 server_.SupplyTPMToken("User-Specific TPM Token FOO");
281}
282
Darin Petkov271fe522012-03-27 13:47:29 +0200283TEST_F(OpenVPNManagementServerTest, Send) {
Darin Petkov271fe522012-03-27 13:47:29 +0200284 const char kMessage[] = "foo\n";
Darin Petkov683942b2012-03-27 18:00:04 +0200285 SetConnectedSocket();
286 ExpectSend(kMessage);
Darin Petkov271fe522012-03-27 13:47:29 +0200287 server_.Send(kMessage);
288}
289
290TEST_F(OpenVPNManagementServerTest, SendState) {
Darin Petkov683942b2012-03-27 18:00:04 +0200291 SetConnectedSocket();
292 ExpectSend("state off\n");
Darin Petkov271fe522012-03-27 13:47:29 +0200293 server_.SendState("off");
Darin Petkov1c115202012-03-22 15:35:47 +0100294}
295
Darin Petkov683942b2012-03-27 18:00:04 +0200296TEST_F(OpenVPNManagementServerTest, SendUsername) {
297 SetConnectedSocket();
298 ExpectSend("username \"Auth\" joesmith\n");
299 server_.SendUsername("Auth", "joesmith");
300}
301
302TEST_F(OpenVPNManagementServerTest, SendPassword) {
303 SetConnectedSocket();
304 ExpectSend("password \"Auth\" \"foobar\"\n");
305 server_.SendPassword("Auth", "foobar");
306}
307
Darin Petkov0440b9b2012-04-17 16:11:56 +0200308TEST_F(OpenVPNManagementServerTest, ProcessFailedPasswordMessage) {
309 EXPECT_FALSE(server_.ProcessFailedPasswordMessage("foo"));
310 EXPECT_CALL(driver_, Cleanup(Service::kStateFailure));
311 EXPECT_TRUE(
312 server_.ProcessFailedPasswordMessage(">PASSWORD:Verification Failed: ."));
313}
314
Darin Petkov1c115202012-03-22 15:35:47 +0100315} // namespace shill