blob: 21d37ad8dddb722229d53bda7c669d12f89b98c4 [file] [log] [blame]
Darin Petkov33af05c2012-02-28 10:10:30 +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_driver.h"
6
Darin Petkova9b1fed2012-02-29 11:49:05 +01007#include <algorithm>
8
Paul Stewart291a4732012-03-14 19:19:02 -07009#include <base/file_path.h>
10#include <base/file_util.h>
11#include <base/string_util.h>
Darin Petkovfe6a9372012-02-28 16:25:06 +010012#include <chromeos/dbus/service_constants.h>
Darin Petkov33af05c2012-02-28 10:10:30 +010013#include <gtest/gtest.h>
14
Paul Stewartebd38562012-03-23 13:06:40 -070015#include "shill/dbus_adaptor.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010016#include "shill/error.h"
Darin Petkov14c29ec2012-03-02 11:34:19 +010017#include "shill/ipconfig.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010018#include "shill/mock_adaptors.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080019#include "shill/mock_device_info.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010020#include "shill/mock_glib.h"
21#include "shill/mock_manager.h"
22#include "shill/mock_metrics.h"
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020023#include "shill/mock_nss.h"
Darin Petkov46463022012-03-29 14:57:32 +020024#include "shill/mock_openvpn_management_server.h"
Darin Petkovf3c71d72012-03-21 12:32:15 +010025#include "shill/mock_store.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010026#include "shill/mock_vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010027#include "shill/mock_vpn_service.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010028#include "shill/nice_mock_control.h"
29#include "shill/rpc_task.h"
Darin Petkov55771b72012-04-25 09:25:19 +020030#include "shill/scope_logger.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010031#include "shill/vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010032#include "shill/vpn_service.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010033
Darin Petkova9b1fed2012-02-29 11:49:05 +010034using std::map;
Darin Petkovfe6a9372012-02-28 16:25:06 +010035using std::string;
36using std::vector;
Paul Stewartca6abd42012-03-01 15:45:29 -080037using testing::_;
Darin Petkovf3c71d72012-03-21 12:32:15 +010038using testing::AnyNumber;
Paul Stewartca6abd42012-03-01 15:45:29 -080039using testing::DoAll;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020040using testing::ElementsAreArray;
Darin Petkovf3c71d72012-03-21 12:32:15 +010041using testing::Ne;
Paul Stewartce4ec192012-03-14 12:53:46 -070042using testing::NiceMock;
Paul Stewartca6abd42012-03-01 15:45:29 -080043using testing::Return;
44using testing::SetArgumentPointee;
Paul Stewartce4ec192012-03-14 12:53:46 -070045using testing::StrictMock;
Darin Petkovfe6a9372012-02-28 16:25:06 +010046
Darin Petkov33af05c2012-02-28 10:10:30 +010047namespace shill {
48
Darin Petkova9b1fed2012-02-29 11:49:05 +010049class OpenVPNDriverTest : public testing::Test,
50 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010051 public:
Darin Petkovfe6a9372012-02-28 16:25:06 +010052 OpenVPNDriverTest()
Darin Petkov0e9735d2012-04-24 12:33:45 +020053 : device_info_(&control_, &dispatcher_, &metrics_, &manager_),
Darin Petkovf20994f2012-03-05 16:12:19 +010054 manager_(&control_, &dispatcher_, &metrics_, &glib_),
Darin Petkov79d74c92012-03-07 17:20:32 +010055 driver_(new OpenVPNDriver(&control_, &dispatcher_, &metrics_, &manager_,
Paul Stewart451aa7f2012-04-11 19:07:58 -070056 &device_info_, &glib_)),
Darin Petkov79d74c92012-03-07 17:20:32 +010057 service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
58 &manager_, driver_)),
59 device_(new MockVPN(&control_, &dispatcher_, &metrics_, &manager_,
Darin Petkov46463022012-03-29 14:57:32 +020060 kInterfaceName, kInterfaceIndex)),
61 management_server_(new NiceMock<MockOpenVPNManagementServer>()) {
62 driver_->management_server_.reset(management_server_);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020063 driver_->nss_ = &nss_;
Darin Petkov46463022012-03-29 14:57:32 +020064 }
Darin Petkovfe6a9372012-02-28 16:25:06 +010065
Darin Petkov33af05c2012-02-28 10:10:30 +010066 virtual ~OpenVPNDriverTest() {}
67
Darin Petkov36a3ace2012-03-06 17:22:14 +010068 virtual void TearDown() {
Darin Petkov79d74c92012-03-07 17:20:32 +010069 driver_->child_watch_tag_ = 0;
70 driver_->pid_ = 0;
71 driver_->device_ = NULL;
72 driver_->service_ = NULL;
Darin Petkov36a3ace2012-03-06 17:22:14 +010073 }
Darin Petkova9b1fed2012-02-29 11:49:05 +010074
Darin Petkov33af05c2012-02-28 10:10:30 +010075 protected:
Darin Petkovfe6a9372012-02-28 16:25:06 +010076 static const char kOption[];
77 static const char kProperty[];
78 static const char kValue[];
79 static const char kOption2[];
80 static const char kProperty2[];
81 static const char kValue2[];
Darin Petkov60596742012-03-05 12:17:17 +010082 static const char kGateway1[];
83 static const char kNetmask1[];
84 static const char kNetwork1[];
85 static const char kGateway2[];
86 static const char kNetmask2[];
87 static const char kNetwork2[];
Darin Petkov79d74c92012-03-07 17:20:32 +010088 static const char kInterfaceName[];
89 static const int kInterfaceIndex;
Darin Petkovfe6a9372012-02-28 16:25:06 +010090
Darin Petkovb451d6e2012-04-23 11:56:41 +020091 void SetArg(const string &arg, const string &value) {
92 driver_->args()->SetString(arg, value);
Darin Petkovfe6a9372012-02-28 16:25:06 +010093 }
94
Darin Petkovf3c71d72012-03-21 12:32:15 +010095 KeyValueStore *GetArgs() {
Darin Petkovb451d6e2012-04-23 11:56:41 +020096 return driver_->args();
Darin Petkovf3c71d72012-03-21 12:32:15 +010097 }
98
Paul Stewartca6abd42012-03-01 15:45:29 -080099 // Used to assert that a flag appears in the options.
100 void ExpectInFlags(const vector<string> &options, const string &flag,
101 const string &value);
102
Darin Petkov36a3ace2012-03-06 17:22:14 +0100103 // Inherited from RPCTaskDelegate.
Darin Petkov209e6292012-04-20 11:33:32 +0200104 virtual void GetLogin(string *user, string *password);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100105 virtual void Notify(const string &reason, const map<string, string> &dict);
Paul Stewartca6abd42012-03-01 15:45:29 -0800106
Darin Petkova9b1fed2012-02-29 11:49:05 +0100107 NiceMockControl control_;
Darin Petkov0e9735d2012-04-24 12:33:45 +0200108 NiceMock<MockDeviceInfo> device_info_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100109 EventDispatcher dispatcher_;
110 MockMetrics metrics_;
111 MockGLib glib_;
112 MockManager manager_;
Darin Petkov46463022012-03-29 14:57:32 +0200113 OpenVPNDriver *driver_; // Owned by |service_|.
Darin Petkov79d74c92012-03-07 17:20:32 +0100114 scoped_refptr<MockVPNService> service_;
115 scoped_refptr<MockVPN> device_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200116 MockNSS nss_;
Darin Petkov46463022012-03-29 14:57:32 +0200117
118 // Owned by |driver_|.
119 NiceMock<MockOpenVPNManagementServer> *management_server_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100120};
121
Darin Petkovfe6a9372012-02-28 16:25:06 +0100122const char OpenVPNDriverTest::kOption[] = "--openvpn-option";
123const char OpenVPNDriverTest::kProperty[] = "OpenVPN.SomeProperty";
124const char OpenVPNDriverTest::kValue[] = "some-property-value";
125const char OpenVPNDriverTest::kOption2[] = "--openvpn-option2";
126const char OpenVPNDriverTest::kProperty2[] = "OpenVPN.SomeProperty2";
127const char OpenVPNDriverTest::kValue2[] = "some-property-value2";
Darin Petkov60596742012-03-05 12:17:17 +0100128const char OpenVPNDriverTest::kGateway1[] = "10.242.2.13";
129const char OpenVPNDriverTest::kNetmask1[] = "255.255.255.255";
130const char OpenVPNDriverTest::kNetwork1[] = "10.242.2.1";
131const char OpenVPNDriverTest::kGateway2[] = "10.242.2.14";
132const char OpenVPNDriverTest::kNetmask2[] = "255.255.0.0";
133const char OpenVPNDriverTest::kNetwork2[] = "192.168.0.0";
Darin Petkov79d74c92012-03-07 17:20:32 +0100134const char OpenVPNDriverTest::kInterfaceName[] = "tun0";
135const int OpenVPNDriverTest::kInterfaceIndex = 123;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100136
Darin Petkov209e6292012-04-20 11:33:32 +0200137void OpenVPNDriverTest::GetLogin(string */*user*/, string */*password*/) {}
138
Darin Petkova9b1fed2012-02-29 11:49:05 +0100139void OpenVPNDriverTest::Notify(const string &/*reason*/,
140 const map<string, string> &/*dict*/) {}
141
Paul Stewartca6abd42012-03-01 15:45:29 -0800142void OpenVPNDriverTest::ExpectInFlags(const vector<string> &options,
143 const string &flag,
144 const string &value) {
145 vector<string>::const_iterator it =
146 std::find(options.begin(), options.end(), flag);
147
148 EXPECT_TRUE(it != options.end());
149 if (it != options.end())
Darin Petkov36a3ace2012-03-06 17:22:14 +0100150 return; // Don't crash below.
Paul Stewartca6abd42012-03-01 15:45:29 -0800151 it++;
152 EXPECT_TRUE(it != options.end());
153 if (it != options.end())
Darin Petkov36a3ace2012-03-06 17:22:14 +0100154 return; // Don't crash below.
Paul Stewartca6abd42012-03-01 15:45:29 -0800155 EXPECT_EQ(value, *it);
156}
157
Darin Petkov33af05c2012-02-28 10:10:30 +0100158TEST_F(OpenVPNDriverTest, Connect) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100159 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
160 const string interface = kInterfaceName;
Darin Petkovf20994f2012-03-05 16:12:19 +0100161 EXPECT_CALL(device_info_, CreateTunnelInterface(_))
Darin Petkov79d74c92012-03-07 17:20:32 +0100162 .WillOnce(DoAll(SetArgumentPointee<0>(interface), Return(true)));
163 Error error;
164 driver_->Connect(service_, &error);
165 EXPECT_TRUE(error.IsSuccess());
166 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
167}
168
169TEST_F(OpenVPNDriverTest, ConnectTunnelFailure) {
170 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
Darin Petkov0e9735d2012-04-24 12:33:45 +0200171 EXPECT_CALL(device_info_, CreateTunnelInterface(_)).WillOnce(Return(false));
Darin Petkov79d74c92012-03-07 17:20:32 +0100172 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
173 Error error;
174 driver_->Connect(service_, &error);
175 EXPECT_EQ(Error::kInternalError, error.type());
176 EXPECT_TRUE(driver_->tunnel_interface_.empty());
Darin Petkov33af05c2012-02-28 10:10:30 +0100177}
178
Darin Petkov0e9735d2012-04-24 12:33:45 +0200179namespace {
180MATCHER_P(IsIPAddress, address, "") {
181 IPAddress ip_address(IPAddress::kFamilyIPv4);
182 EXPECT_TRUE(ip_address.SetAddressFromString(address));
183 return ip_address.Equals(arg);
184}
185} // namespace
186
Darin Petkov14c29ec2012-03-02 11:34:19 +0100187TEST_F(OpenVPNDriverTest, Notify) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200188 map<string, string> config;
Darin Petkov79d74c92012-03-07 17:20:32 +0100189 driver_->device_ = device_;
190 EXPECT_CALL(*device_, UpdateIPConfig(_));
Darin Petkov0e9735d2012-04-24 12:33:45 +0200191 driver_->Notify("up", config);
Darin Petkov79d74c92012-03-07 17:20:32 +0100192}
193
194TEST_F(OpenVPNDriverTest, NotifyFail) {
195 map<string, string> dict;
196 driver_->device_ = device_;
197 EXPECT_CALL(*device_, OnDisconnected());
198 driver_->Notify("fail", dict);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100199}
200
Darin Petkov60596742012-03-05 12:17:17 +0100201TEST_F(OpenVPNDriverTest, GetRouteOptionEntry) {
202 OpenVPNDriver::RouteOptions routes;
203 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "bar", &routes));
204 EXPECT_TRUE(routes.empty());
205 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "foo", &routes));
206 EXPECT_TRUE(routes.empty());
207 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "fooZ", &routes));
208 EXPECT_TRUE(routes.empty());
209 IPConfig::Route *route =
210 OpenVPNDriver::GetRouteOptionEntry("foo", "foo12", &routes);
211 EXPECT_EQ(1, routes.size());
212 EXPECT_EQ(route, &routes[12]);
213 route = OpenVPNDriver::GetRouteOptionEntry("foo", "foo13", &routes);
214 EXPECT_EQ(2, routes.size());
215 EXPECT_EQ(route, &routes[13]);
216}
217
218TEST_F(OpenVPNDriverTest, ParseRouteOption) {
219 OpenVPNDriver::RouteOptions routes;
220 OpenVPNDriver::ParseRouteOption("foo", "bar", &routes);
221 EXPECT_TRUE(routes.empty());
222 OpenVPNDriver::ParseRouteOption("gateway_2", kGateway2, &routes);
223 OpenVPNDriver::ParseRouteOption("netmask_2", kNetmask2, &routes);
224 OpenVPNDriver::ParseRouteOption("network_2", kNetwork2, &routes);
225 EXPECT_EQ(1, routes.size());
226 OpenVPNDriver::ParseRouteOption("gateway_1", kGateway1, &routes);
227 OpenVPNDriver::ParseRouteOption("netmask_1", kNetmask1, &routes);
228 OpenVPNDriver::ParseRouteOption("network_1", kNetwork1, &routes);
229 EXPECT_EQ(2, routes.size());
230 EXPECT_EQ(kGateway1, routes[1].gateway);
231 EXPECT_EQ(kNetmask1, routes[1].netmask);
232 EXPECT_EQ(kNetwork1, routes[1].host);
233 EXPECT_EQ(kGateway2, routes[2].gateway);
234 EXPECT_EQ(kNetmask2, routes[2].netmask);
235 EXPECT_EQ(kNetwork2, routes[2].host);
236}
237
238TEST_F(OpenVPNDriverTest, SetRoutes) {
239 OpenVPNDriver::RouteOptions routes;
240 routes[1].gateway = "1.2.3.4";
241 routes[1].host= "1.2.3.4";
242 routes[2].host = "2.3.4.5";
243 routes[2].netmask = "255.0.0.0";
244 routes[3].netmask = "255.0.0.0";
245 routes[3].gateway = "1.2.3.5";
246 routes[5].host = kNetwork2;
247 routes[5].netmask = kNetmask2;
248 routes[5].gateway = kGateway2;
249 routes[4].host = kNetwork1;
250 routes[4].netmask = kNetmask1;
251 routes[4].gateway = kGateway1;
252 IPConfig::Properties props;
253 OpenVPNDriver::SetRoutes(routes, &props);
254 ASSERT_EQ(2, props.routes.size());
255 EXPECT_EQ(kGateway1, props.routes[0].gateway);
256 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
257 EXPECT_EQ(kNetwork1, props.routes[0].host);
258 EXPECT_EQ(kGateway2, props.routes[1].gateway);
259 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
260 EXPECT_EQ(kNetwork2, props.routes[1].host);
261}
262
Darin Petkov14c29ec2012-03-02 11:34:19 +0100263TEST_F(OpenVPNDriverTest, ParseForeignOption) {
264 IPConfig::Properties props;
265 OpenVPNDriver::ParseForeignOption("", &props);
266 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN", &props);
267 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN zzz.com foo", &props);
268 OpenVPNDriver::ParseForeignOption("dhcp-Option DOmAIN xyz.com", &props);
269 ASSERT_EQ(1, props.domain_search.size());
270 EXPECT_EQ("xyz.com", props.domain_search[0]);
271 OpenVPNDriver::ParseForeignOption("dhcp-option DnS 1.2.3.4", &props);
272 ASSERT_EQ(1, props.dns_servers.size());
273 EXPECT_EQ("1.2.3.4", props.dns_servers[0]);
274}
275
276TEST_F(OpenVPNDriverTest, ParseForeignOptions) {
277 // Basically test that std::map is a sorted container.
278 map<int, string> options;
279 options[5] = "dhcp-option DOMAIN five.com";
280 options[2] = "dhcp-option DOMAIN two.com";
281 options[8] = "dhcp-option DOMAIN eight.com";
282 options[7] = "dhcp-option DOMAIN seven.com";
283 options[4] = "dhcp-option DOMAIN four.com";
284 IPConfig::Properties props;
285 OpenVPNDriver::ParseForeignOptions(options, &props);
286 ASSERT_EQ(5, props.domain_search.size());
287 EXPECT_EQ("two.com", props.domain_search[0]);
288 EXPECT_EQ("four.com", props.domain_search[1]);
289 EXPECT_EQ("five.com", props.domain_search[2]);
290 EXPECT_EQ("seven.com", props.domain_search[3]);
291 EXPECT_EQ("eight.com", props.domain_search[4]);
292}
293
294TEST_F(OpenVPNDriverTest, ParseIPConfiguration) {
295 map<string, string> config;
296 config["ifconfig_loCal"] = "4.5.6.7";
297 config["ifconfiG_broadcast"] = "1.2.255.255";
298 config["ifconFig_netmAsk"] = "255.255.255.0";
299 config["ifconfig_remotE"] = "33.44.55.66";
300 config["route_vpN_gateway"] = "192.168.1.1";
Paul Stewartce4ec192012-03-14 12:53:46 -0700301 config["trusted_ip"] = "99.88.77.66";
Darin Petkov14c29ec2012-03-02 11:34:19 +0100302 config["tun_mtu"] = "1000";
303 config["foreign_option_2"] = "dhcp-option DNS 4.4.4.4";
304 config["foreign_option_1"] = "dhcp-option DNS 1.1.1.1";
305 config["foreign_option_3"] = "dhcp-option DNS 2.2.2.2";
Darin Petkov60596742012-03-05 12:17:17 +0100306 config["route_network_2"] = kNetwork2;
307 config["route_network_1"] = kNetwork1;
308 config["route_netmask_2"] = kNetmask2;
309 config["route_netmask_1"] = kNetmask1;
310 config["route_gateway_2"] = kGateway2;
311 config["route_gateway_1"] = kGateway1;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100312 config["foo"] = "bar";
313 IPConfig::Properties props;
314 OpenVPNDriver::ParseIPConfiguration(config, &props);
315 EXPECT_EQ(IPAddress::kFamilyIPv4, props.address_family);
316 EXPECT_EQ("4.5.6.7", props.address);
317 EXPECT_EQ("1.2.255.255", props.broadcast_address);
Paul Stewart48100b02012-03-19 07:53:52 -0700318 EXPECT_EQ(24, props.subnet_prefix);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100319 EXPECT_EQ("33.44.55.66", props.peer_address);
320 EXPECT_EQ("192.168.1.1", props.gateway);
Paul Stewartce4ec192012-03-14 12:53:46 -0700321 EXPECT_EQ("99.88.77.66", props.trusted_ip);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100322 EXPECT_EQ(1000, props.mtu);
323 ASSERT_EQ(3, props.dns_servers.size());
324 EXPECT_EQ("1.1.1.1", props.dns_servers[0]);
325 EXPECT_EQ("4.4.4.4", props.dns_servers[1]);
326 EXPECT_EQ("2.2.2.2", props.dns_servers[2]);
Darin Petkov60596742012-03-05 12:17:17 +0100327 ASSERT_EQ(2, props.routes.size());
328 EXPECT_EQ(kGateway1, props.routes[0].gateway);
329 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
330 EXPECT_EQ(kNetwork1, props.routes[0].host);
331 EXPECT_EQ(kGateway2, props.routes[1].gateway);
332 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
333 EXPECT_EQ(kNetwork2, props.routes[1].host);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100334}
335
Darin Petkovfe6a9372012-02-28 16:25:06 +0100336TEST_F(OpenVPNDriverTest, InitOptionsNoHost) {
337 Error error;
338 vector<string> options;
Darin Petkov79d74c92012-03-07 17:20:32 +0100339 driver_->InitOptions(&options, &error);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100340 EXPECT_EQ(Error::kInvalidArguments, error.type());
341 EXPECT_TRUE(options.empty());
342}
343
344TEST_F(OpenVPNDriverTest, InitOptions) {
345 static const char kHost[] = "192.168.2.254";
Darin Petkov1fa81942012-04-02 11:38:08 +0200346 static const char kTLSAuthContents[] = "SOME-RANDOM-CONTENTS\n";
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200347 static const char kCaCertNSS[] = "{1234}";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200348 static const char kID[] = "TestPKCS11ID";
349 FilePath empty_cert;
350 SetArg(flimflam::kProviderHostProperty, kHost);
351 SetArg(flimflam::kOpenVPNTLSAuthContentsProperty, kTLSAuthContents);
352 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
353 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
Darin Petkov79d74c92012-03-07 17:20:32 +0100354 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov79d74c92012-03-07 17:20:32 +0100355 driver_->tunnel_interface_ = kInterfaceName;
Darin Petkove0d5dd12012-04-04 16:10:48 +0200356 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
357 EXPECT_CALL(nss_, GetPEMCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));
358
359 Error error;
360 vector<string> options;
361 driver_->InitOptions(&options, &error);
362 EXPECT_TRUE(error.IsSuccess());
363 EXPECT_EQ("--client", options[0]);
364 ExpectInFlags(options, "--remote", kHost);
365 ExpectInFlags(options, "CONNMAN_PATH", RPCTaskMockAdaptor::kRpcId);
366 ExpectInFlags(options, "--dev", kInterfaceName);
367 ExpectInFlags(options, "--group", "openvpn");
368 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
369 ASSERT_FALSE(driver_->tls_auth_file_.empty());
370 ExpectInFlags(options, "--tls-auth", driver_->tls_auth_file_.value());
371 string contents;
372 EXPECT_TRUE(
373 file_util::ReadFileToString(driver_->tls_auth_file_, &contents));
374 EXPECT_EQ(kTLSAuthContents, contents);
375 ExpectInFlags(options, "--pkcs11-id", kID);
Darin Petkov55771b72012-04-25 09:25:19 +0200376 EXPECT_TRUE(std::find(options.begin(), options.end(), "--syslog") !=
377 options.end());
Darin Petkove0d5dd12012-04-04 16:10:48 +0200378}
379
380TEST_F(OpenVPNDriverTest, InitNSSOptions) {
381 static const char kHost[] = "192.168.2.254";
382 static const char kCaCertNSS[] = "{1234}";
383 static const char kNSSCertfile[] = "/tmp/nss-cert";
384 FilePath empty_cert;
385 FilePath nss_cert(kNSSCertfile);
386 SetArg(flimflam::kProviderHostProperty, kHost);
387 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200388 EXPECT_CALL(nss_,
389 GetPEMCertfile(kCaCertNSS,
390 ElementsAreArray(kHost, arraysize(kHost) - 1)))
Darin Petkove0d5dd12012-04-04 16:10:48 +0200391 .WillOnce(Return(empty_cert))
392 .WillOnce(Return(nss_cert));
393
394 Error error;
395 vector<string> options;
396 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
397 EXPECT_TRUE(error.IsSuccess());
398 EXPECT_TRUE(options.empty());
399 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
400 ExpectInFlags(options, "--ca", kNSSCertfile);
401 EXPECT_TRUE(error.IsSuccess());
402
403 SetArg(flimflam::kOpenVPNCaCertProperty, "foo");
404 options.clear();
405 EXPECT_FALSE(driver_->InitNSSOptions(&options, &error));
406 EXPECT_EQ(Error::kInvalidArguments, error.type());
407 EXPECT_EQ("Can't specify both CACert and CACertNSS.", error.message());
408}
409
410TEST_F(OpenVPNDriverTest, InitPKCS11Options) {
411 vector<string> options;
412 driver_->InitPKCS11Options(&options);
413 EXPECT_TRUE(options.empty());
414
415 static const char kID[] = "TestPKCS11ID";
416 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
417 driver_->InitPKCS11Options(&options);
418 ExpectInFlags(options, "--pkcs11-id", kID);
419 ExpectInFlags(options, "--pkcs11-providers", "libchaps.so");
420
421 static const char kProvider[] = "libpkcs11.so";
422 SetArg(flimflam::kOpenVPNProviderProperty, kProvider);
423 options.clear();
424 driver_->InitPKCS11Options(&options);
425 ExpectInFlags(options, "--pkcs11-id", kID);
426 ExpectInFlags(options, "--pkcs11-providers", kProvider);
427}
428
429TEST_F(OpenVPNDriverTest, InitManagementChannelOptions) {
430 vector<string> options;
431 EXPECT_CALL(*management_server_,
432 Start(&dispatcher_, &driver_->sockets_, &options))
433 .WillOnce(Return(false))
434 .WillOnce(Return(true));
435
436 Error error;
437 EXPECT_FALSE(driver_->InitManagementChannelOptions(&options, &error));
438 EXPECT_EQ(Error::kInternalError, error.type());
439 EXPECT_EQ("Unable to setup management channel.", error.message());
440
441 error.Reset();
442 EXPECT_TRUE(driver_->InitManagementChannelOptions(&options, &error));
443 EXPECT_TRUE(error.IsSuccess());
Darin Petkovfe6a9372012-02-28 16:25:06 +0100444}
445
Darin Petkov55771b72012-04-25 09:25:19 +0200446TEST_F(OpenVPNDriverTest, InitLoggingOptions) {
447 vector<string> options;
448 bool vpn_logging = SLOG_IS_ON(VPN, 0);
449 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
450 driver_->InitLoggingOptions(&options);
451 ASSERT_EQ(1, options.size());
452 EXPECT_EQ("--syslog", options[0]);
453 ScopeLogger::GetInstance()->EnableScopesByName("+vpn");
454 options.clear();
455 driver_->InitLoggingOptions(&options);
456 ExpectInFlags(options, "--verb", "3");
457 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
458 SetArg("OpenVPN.Verb", "2");
459 options.clear();
460 driver_->InitLoggingOptions(&options);
461 ExpectInFlags(options, "--verb", "2");
462 ScopeLogger::GetInstance()->EnableScopesByName("+vpn");
463 SetArg("OpenVPN.Verb", "1");
464 options.clear();
465 driver_->InitLoggingOptions(&options);
466 ExpectInFlags(options, "--verb", "1");
467 if (!vpn_logging) {
468 ScopeLogger::GetInstance()->EnableScopesByName("-vpn");
469 }
470}
471
Darin Petkovfe6a9372012-02-28 16:25:06 +0100472TEST_F(OpenVPNDriverTest, AppendValueOption) {
473 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200474 EXPECT_FALSE(
475 driver_->AppendValueOption("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100476 EXPECT_TRUE(options.empty());
477
Darin Petkove0d5dd12012-04-04 16:10:48 +0200478 SetArg(kProperty, "");
Darin Petkov46463022012-03-29 14:57:32 +0200479 EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100480 EXPECT_TRUE(options.empty());
481
Darin Petkove0d5dd12012-04-04 16:10:48 +0200482 SetArg(kProperty, kValue);
483 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200484 EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
485 EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100486 EXPECT_EQ(4, options.size());
487 EXPECT_EQ(kOption, options[0]);
488 EXPECT_EQ(kValue, options[1]);
489 EXPECT_EQ(kOption2, options[2]);
490 EXPECT_EQ(kValue2, options[3]);
491}
492
493TEST_F(OpenVPNDriverTest, AppendFlag) {
494 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200495 EXPECT_FALSE(
496 driver_->AppendFlag("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100497 EXPECT_TRUE(options.empty());
498
Darin Petkove0d5dd12012-04-04 16:10:48 +0200499 SetArg(kProperty, "");
500 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200501 EXPECT_TRUE(driver_->AppendFlag(kProperty, kOption, &options));
502 EXPECT_TRUE(driver_->AppendFlag(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100503 EXPECT_EQ(2, options.size());
504 EXPECT_EQ(kOption, options[0]);
505 EXPECT_EQ(kOption2, options[1]);
506}
507
Paul Stewartca6abd42012-03-01 15:45:29 -0800508TEST_F(OpenVPNDriverTest, ClaimInterface) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100509 driver_->tunnel_interface_ = kInterfaceName;
510 EXPECT_FALSE(driver_->ClaimInterface(string(kInterfaceName) + "XXX",
511 kInterfaceIndex));
512 EXPECT_FALSE(driver_->device_);
Paul Stewartca6abd42012-03-01 15:45:29 -0800513
Darin Petkov36a3ace2012-03-06 17:22:14 +0100514 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200515 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov46463022012-03-29 14:57:32 +0200516 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100517 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
518 .WillOnce(Return(true));
519 EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1));
Darin Petkov79d74c92012-03-07 17:20:32 +0100520 EXPECT_TRUE(driver_->ClaimInterface(kInterfaceName, kInterfaceIndex));
521 ASSERT_TRUE(driver_->device_);
522 EXPECT_EQ(kInterfaceIndex, driver_->device_->interface_index());
Paul Stewartca6abd42012-03-01 15:45:29 -0800523}
524
Darin Petkov36a3ace2012-03-06 17:22:14 +0100525TEST_F(OpenVPNDriverTest, Cleanup) {
Darin Petkov1fa81942012-04-02 11:38:08 +0200526 driver_->Cleanup(Service::kStateIdle); // Ensure no crash.
527
Darin Petkov36a3ace2012-03-06 17:22:14 +0100528 const unsigned int kTag = 123;
529 const int kPID = 123456;
Darin Petkov79d74c92012-03-07 17:20:32 +0100530 driver_->child_watch_tag_ = kTag;
531 driver_->pid_ = kPID;
532 driver_->rpc_task_.reset(new RPCTask(&control_, this));
533 driver_->tunnel_interface_ = kInterfaceName;
534 driver_->device_ = device_;
535 driver_->service_ = service_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200536 FilePath tls_auth_file;
537 EXPECT_TRUE(file_util::CreateTemporaryFile(&tls_auth_file));
538 EXPECT_FALSE(tls_auth_file.empty());
539 EXPECT_TRUE(file_util::PathExists(tls_auth_file));
540 driver_->tls_auth_file_ = tls_auth_file;
Darin Petkov46463022012-03-29 14:57:32 +0200541 // Stop will be called twice -- once by Cleanup and once by the destructor.
542 EXPECT_CALL(*management_server_, Stop()).Times(2);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100543 EXPECT_CALL(glib_, SourceRemove(kTag));
544 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Darin Petkov029d3532012-04-18 14:38:04 +0200545 EXPECT_CALL(*device_, OnDisconnected());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500546 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov79d74c92012-03-07 17:20:32 +0100547 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
548 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
Darin Petkov3f9131c2012-03-20 11:37:32 +0100549 driver_->Cleanup(Service::kStateFailure);
Darin Petkov79d74c92012-03-07 17:20:32 +0100550 EXPECT_EQ(0, driver_->child_watch_tag_);
551 EXPECT_EQ(0, driver_->pid_);
552 EXPECT_FALSE(driver_->rpc_task_.get());
553 EXPECT_TRUE(driver_->tunnel_interface_.empty());
554 EXPECT_FALSE(driver_->device_);
555 EXPECT_FALSE(driver_->service_);
Darin Petkov1fa81942012-04-02 11:38:08 +0200556 EXPECT_FALSE(file_util::PathExists(tls_auth_file));
557 EXPECT_TRUE(driver_->tls_auth_file_.empty());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100558}
559
560TEST_F(OpenVPNDriverTest, SpawnOpenVPN) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100561 EXPECT_FALSE(driver_->SpawnOpenVPN());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100562
563 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200564 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov79d74c92012-03-07 17:20:32 +0100565 driver_->tunnel_interface_ = "tun0";
566 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov46463022012-03-29 14:57:32 +0200567 EXPECT_CALL(*management_server_, Start(_, _, _))
568 .Times(2)
569 .WillRepeatedly(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100570
571 const int kPID = 234678;
572 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
573 .WillOnce(Return(false))
574 .WillOnce(DoAll(SetArgumentPointee<5>(kPID), Return(true)));
575 const int kTag = 6;
Darin Petkov79d74c92012-03-07 17:20:32 +0100576 EXPECT_CALL(glib_, ChildWatchAdd(kPID, &driver_->OnOpenVPNDied, driver_))
Darin Petkov36a3ace2012-03-06 17:22:14 +0100577 .WillOnce(Return(kTag));
Darin Petkov79d74c92012-03-07 17:20:32 +0100578 EXPECT_FALSE(driver_->SpawnOpenVPN());
579 EXPECT_TRUE(driver_->SpawnOpenVPN());
580 EXPECT_EQ(kPID, driver_->pid_);
581 EXPECT_EQ(kTag, driver_->child_watch_tag_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100582}
583
584TEST_F(OpenVPNDriverTest, OnOpenVPNDied) {
585 const int kPID = 99999;
Darin Petkov79d74c92012-03-07 17:20:32 +0100586 driver_->child_watch_tag_ = 333;
587 driver_->pid_ = kPID;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100588 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Darin Petkov79d74c92012-03-07 17:20:32 +0100589 OpenVPNDriver::OnOpenVPNDied(kPID, 2, driver_);
590 EXPECT_EQ(0, driver_->child_watch_tag_);
591 EXPECT_EQ(0, driver_->pid_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100592}
593
Darin Petkov6aa21872012-03-09 16:10:19 +0100594TEST_F(OpenVPNDriverTest, Disconnect) {
595 driver_->device_ = device_;
596 driver_->service_ = service_;
Darin Petkov029d3532012-04-18 14:38:04 +0200597 EXPECT_CALL(*device_, OnDisconnected());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500598 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov6aa21872012-03-09 16:10:19 +0100599 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
600 EXPECT_CALL(*service_, SetState(Service::kStateIdle));
601 driver_->Disconnect();
602 EXPECT_FALSE(driver_->service_);
603}
604
Darin Petkov271fe522012-03-27 13:47:29 +0200605TEST_F(OpenVPNDriverTest, OnReconnecting) {
606 driver_->OnReconnecting(); // Expect no crash.
607 driver_->device_ = device_;
608 driver_->service_ = service_;
609 EXPECT_CALL(*device_, OnDisconnected());
610 EXPECT_CALL(*service_, SetState(Service::kStateAssociating));
611 driver_->OnReconnecting();
612}
613
Paul Stewart291a4732012-03-14 19:19:02 -0700614TEST_F(OpenVPNDriverTest, VerifyPaths) {
615 // Ensure that the various path constants that the OpenVPN driver uses
616 // actually exists in the build image. Due to build dependencies, they
617 // should already exist by the time we run unit tests.
618
619 // The OpenVPNDriver path constants are absolute. FilePath::Append
620 // asserts that its argument is not an absolute path, so we need to
621 // strip the leading separators. There's nothing built into FilePath
622 // to do so.
623 string vpn_path(OpenVPNDriver::kOpenVPNPath);
624 TrimString(vpn_path, FilePath::kSeparators, &vpn_path);
625 EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(vpn_path)));
626
627 string vpn_script(OpenVPNDriver::kOpenVPNScript);
628 TrimString(vpn_script, FilePath::kSeparators, &vpn_script);
629 EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(vpn_script)));
630}
631
Darin Petkovd4325392012-04-23 15:48:22 +0200632TEST_F(OpenVPNDriverTest, InitPropertyStore) {
633 // Sanity test property store initialization.
634 PropertyStore store;
635 driver_->InitPropertyStore(&store);
636 const string kUser = "joe";
637 Error error;
638 EXPECT_TRUE(
639 store.SetStringProperty(flimflam::kOpenVPNUserProperty, kUser, &error));
640 EXPECT_TRUE(error.IsSuccess());
641 EXPECT_EQ(kUser, GetArgs()->GetString(flimflam::kOpenVPNUserProperty));
642}
643
Darin Petkov33af05c2012-02-28 10:10:30 +0100644} // namespace shill