blob: acab874e8f8498b2fe17959e34364a8d111e299e [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()
39 : driver_(args_),
Darin Petkov683942b2012-03-27 18:00:04 +020040 server_(&driver_, &glib_) {}
Darin Petkov1c115202012-03-22 15:35:47 +010041
42 virtual ~OpenVPNManagementServerTest() {}
43
Darin Petkov271fe522012-03-27 13:47:29 +020044 void SetSockets() { server_.sockets_ = &sockets_; }
45 void SetDispatcher() { server_.dispatcher_ = &dispatcher_; }
46 void ExpectNotStarted() { EXPECT_TRUE(server_.sockets_ == NULL); }
47
Darin Petkov683942b2012-03-27 18:00:04 +020048 void SetConnectedSocket() {
49 server_.connected_socket_ = kConnectedSocket;
50 SetSockets();
51 }
52
53 void ExpectSend(const string &value) {
54 EXPECT_CALL(sockets_,
55 Send(kConnectedSocket, VoidStringEq(value), value.size(), 0))
Darin Petkov271fe522012-03-27 13:47:29 +020056 .WillOnce(Return(value.size()));
57 }
58
Darin Petkov683942b2012-03-27 18:00:04 +020059 void ExpectStaticChallengeResponse() {
60 driver_.args()->SetString(flimflam::kOpenVPNUserProperty, "jojo");
61 driver_.args()->SetString(flimflam::kOpenVPNPasswordProperty, "yoyo");
62 driver_.args()->SetString(flimflam::kOpenVPNOTPProperty, "123456");
63 SetConnectedSocket();
64 ExpectSend("username \"Auth\" jojo\n");
65 ExpectSend("password \"Auth\" \"SCRV1:eW95bw==:MTIzNDU2\"\n");
66 }
67
Darin Petkove0d5dd12012-04-04 16:10:48 +020068 void ExpectPINResponse() {
69 driver_.args()->SetString(flimflam::kOpenVPNPinProperty, "987654");
70 SetConnectedSocket();
71 ExpectSend("password \"User-Specific TPM Token FOO\" \"987654\"\n");
72 }
73
Darin Petkov271fe522012-03-27 13:47:29 +020074 InputData CreateInputDataFromString(const string &str) {
75 InputData data(
76 reinterpret_cast<unsigned char *>(const_cast<char *>(str.data())),
77 str.size());
78 return data;
79 }
80
Darin Petkov1c115202012-03-22 15:35:47 +010081 protected:
Darin Petkov683942b2012-03-27 18:00:04 +020082 static const int kConnectedSocket;
83
84 GLib glib_;
Darin Petkov1c115202012-03-22 15:35:47 +010085 KeyValueStore args_;
86 MockOpenVPNDriver driver_;
87 OpenVPNManagementServer server_;
Darin Petkov271fe522012-03-27 13:47:29 +020088 MockSockets sockets_;
89 MockEventDispatcher dispatcher_;
Darin Petkov1c115202012-03-22 15:35:47 +010090};
91
Darin Petkov683942b2012-03-27 18:00:04 +020092// static
93const int OpenVPNManagementServerTest::kConnectedSocket = 555;
94
Darin Petkov271fe522012-03-27 13:47:29 +020095TEST_F(OpenVPNManagementServerTest, StartStarted) {
96 SetSockets();
Darin Petkov46463022012-03-29 14:57:32 +020097 EXPECT_TRUE(server_.Start(NULL, NULL, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +020098}
99
100TEST_F(OpenVPNManagementServerTest, StartSocketFail) {
101 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
102 .WillOnce(Return(-1));
Darin Petkov46463022012-03-29 14:57:32 +0200103 EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +0200104 ExpectNotStarted();
105}
106
107TEST_F(OpenVPNManagementServerTest, StartGetSockNameFail) {
108 const int kSocket = 123;
109 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
110 .WillOnce(Return(kSocket));
111 EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
112 EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
113 EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(-1));
114 EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
Darin Petkov46463022012-03-29 14:57:32 +0200115 EXPECT_FALSE(server_.Start(NULL, &sockets_, NULL));
Darin Petkov271fe522012-03-27 13:47:29 +0200116 ExpectNotStarted();
117}
118
Darin Petkov78f63262012-03-26 01:30:24 +0200119TEST_F(OpenVPNManagementServerTest, Start) {
Darin Petkov271fe522012-03-27 13:47:29 +0200120 const int kSocket = 123;
121 EXPECT_CALL(sockets_, Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
122 .WillOnce(Return(kSocket));
123 EXPECT_CALL(sockets_, Bind(kSocket, _, _)).WillOnce(Return(0));
124 EXPECT_CALL(sockets_, Listen(kSocket, 1)).WillOnce(Return(0));
125 EXPECT_CALL(sockets_, GetSockName(kSocket, _, _)).WillOnce(Return(0));
126 EXPECT_CALL(dispatcher_,
127 CreateReadyHandler(kSocket, IOHandler::kModeInput,
128 CallbackEq(server_.ready_callback_)))
129 .WillOnce(ReturnNew<IOHandler>());
Darin Petkov46463022012-03-29 14:57:32 +0200130 vector<string> options;
131 EXPECT_TRUE(server_.Start(&dispatcher_, &sockets_, &options));
Darin Petkov271fe522012-03-27 13:47:29 +0200132 EXPECT_EQ(&sockets_, server_.sockets_);
133 EXPECT_EQ(kSocket, server_.socket_);
134 EXPECT_TRUE(server_.ready_handler_.get());
135 EXPECT_EQ(&dispatcher_, server_.dispatcher_);
Darin Petkov46463022012-03-29 14:57:32 +0200136 EXPECT_FALSE(options.empty());
Darin Petkov271fe522012-03-27 13:47:29 +0200137}
138
139TEST_F(OpenVPNManagementServerTest, Stop) {
140 SetSockets();
141 server_.input_handler_.reset(new IOHandler());
142 const int kConnectedSocket = 234;
143 server_.connected_socket_ = kConnectedSocket;
144 EXPECT_CALL(sockets_, Close(kConnectedSocket)).WillOnce(Return(0));
145 SetDispatcher();
146 server_.ready_handler_.reset(new IOHandler());
147 const int kSocket = 345;
148 server_.socket_ = kSocket;
149 EXPECT_CALL(sockets_, Close(kSocket)).WillOnce(Return(0));
150 server_.Stop();
151 EXPECT_FALSE(server_.input_handler_.get());
152 EXPECT_EQ(-1, server_.connected_socket_);
153 EXPECT_FALSE(server_.dispatcher_);
154 EXPECT_FALSE(server_.ready_handler_.get());
155 EXPECT_EQ(-1, server_.socket_);
156 ExpectNotStarted();
157}
158
159TEST_F(OpenVPNManagementServerTest, OnReadyAcceptFail) {
160 const int kSocket = 333;
161 SetSockets();
162 EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL)).WillOnce(Return(-1));
163 server_.OnReady(kSocket);
164 EXPECT_EQ(-1, server_.connected_socket_);
165}
166
167TEST_F(OpenVPNManagementServerTest, OnReady) {
168 const int kSocket = 111;
Darin Petkov683942b2012-03-27 18:00:04 +0200169 SetConnectedSocket();
Darin Petkov271fe522012-03-27 13:47:29 +0200170 SetDispatcher();
171 EXPECT_CALL(sockets_, Accept(kSocket, NULL, NULL))
172 .WillOnce(Return(kConnectedSocket));
173 server_.ready_handler_.reset(new IOHandler());
174 EXPECT_CALL(dispatcher_,
175 CreateInputHandler(kConnectedSocket,
176 CallbackEq(server_.input_callback_)))
177 .WillOnce(ReturnNew<IOHandler>());
Darin Petkov683942b2012-03-27 18:00:04 +0200178 ExpectSend("state on\n");
Darin Petkov271fe522012-03-27 13:47:29 +0200179 server_.OnReady(kSocket);
180 EXPECT_EQ(kConnectedSocket, server_.connected_socket_);
181 EXPECT_FALSE(server_.ready_handler_.get());
182 EXPECT_TRUE(server_.input_handler_.get());
183}
184
185TEST_F(OpenVPNManagementServerTest, OnInput) {
186 {
187 string s;
188 InputData data = CreateInputDataFromString(s);
189 server_.OnInput(&data);
190 }
191 {
192 string s = "foo\n"
193 ">INFO:...\n"
Darin Petkov683942b2012-03-27 18:00:04 +0200194 ">PASSWORD:Need 'Auth' SC:user/password/otp\n"
Darin Petkove0d5dd12012-04-04 16:10:48 +0200195 ">PASSWORD:Need 'User-Specific TPM Token FOO' ...\n"
Darin Petkov271fe522012-03-27 13:47:29 +0200196 ">STATE:123,RECONNECTING,detail,...,...";
197 InputData data = CreateInputDataFromString(s);
Darin Petkov683942b2012-03-27 18:00:04 +0200198 ExpectStaticChallengeResponse();
Darin Petkove0d5dd12012-04-04 16:10:48 +0200199 ExpectPINResponse();
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) {
259 // Expect no crash due to null sockets_.
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) {
274 // Expect no crash due to null sockets_.
275 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 Petkov1c115202012-03-22 15:35:47 +0100308} // namespace shill