blob: 05b257f7cd4cff1e3af4d5b14d5e72c1d009b92e [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 Stewartce4ec192012-03-14 12:53:46 -070019#include "shill/mock_connection.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080020#include "shill/mock_device_info.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010021#include "shill/mock_glib.h"
22#include "shill/mock_manager.h"
23#include "shill/mock_metrics.h"
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020024#include "shill/mock_nss.h"
Darin Petkov46463022012-03-29 14:57:32 +020025#include "shill/mock_openvpn_management_server.h"
Paul Stewartce4ec192012-03-14 12:53:46 -070026#include "shill/mock_service.h"
Darin Petkovf3c71d72012-03-21 12:32:15 +010027#include "shill/mock_store.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010028#include "shill/mock_vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010029#include "shill/mock_vpn_service.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010030#include "shill/nice_mock_control.h"
31#include "shill/rpc_task.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010032#include "shill/vpn.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010033#include "shill/vpn_service.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010034
Darin Petkova9b1fed2012-02-29 11:49:05 +010035using std::map;
Darin Petkovfe6a9372012-02-28 16:25:06 +010036using std::string;
37using std::vector;
Paul Stewartca6abd42012-03-01 15:45:29 -080038using testing::_;
Darin Petkovf3c71d72012-03-21 12:32:15 +010039using testing::AnyNumber;
Paul Stewartca6abd42012-03-01 15:45:29 -080040using testing::DoAll;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020041using testing::ElementsAreArray;
Darin Petkovf3c71d72012-03-21 12:32:15 +010042using testing::Ne;
Paul Stewartce4ec192012-03-14 12:53:46 -070043using testing::NiceMock;
Paul Stewartca6abd42012-03-01 15:45:29 -080044using testing::Return;
45using testing::SetArgumentPointee;
Paul Stewartce4ec192012-03-14 12:53:46 -070046using testing::StrictMock;
Darin Petkovfe6a9372012-02-28 16:25:06 +010047
Darin Petkov33af05c2012-02-28 10:10:30 +010048namespace shill {
49
Darin Petkova9b1fed2012-02-29 11:49:05 +010050class OpenVPNDriverTest : public testing::Test,
51 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010052 public:
Darin Petkovfe6a9372012-02-28 16:25:06 +010053 OpenVPNDriverTest()
Paul Stewartca6abd42012-03-01 15:45:29 -080054 : device_info_(&control_, NULL, NULL, NULL),
Darin Petkovf20994f2012-03-05 16:12:19 +010055 manager_(&control_, &dispatcher_, &metrics_, &glib_),
Darin Petkov79d74c92012-03-07 17:20:32 +010056 driver_(new OpenVPNDriver(&control_, &dispatcher_, &metrics_, &manager_,
57 &device_info_, &glib_, args_)),
58 service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
59 &manager_, driver_)),
60 device_(new MockVPN(&control_, &dispatcher_, &metrics_, &manager_,
Darin Petkov46463022012-03-29 14:57:32 +020061 kInterfaceName, kInterfaceIndex)),
62 management_server_(new NiceMock<MockOpenVPNManagementServer>()) {
63 driver_->management_server_.reset(management_server_);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020064 driver_->nss_ = &nss_;
Darin Petkov46463022012-03-29 14:57:32 +020065 }
Darin Petkovfe6a9372012-02-28 16:25:06 +010066
Darin Petkov33af05c2012-02-28 10:10:30 +010067 virtual ~OpenVPNDriverTest() {}
68
Darin Petkov36a3ace2012-03-06 17:22:14 +010069 virtual void TearDown() {
Darin Petkov79d74c92012-03-07 17:20:32 +010070 driver_->child_watch_tag_ = 0;
71 driver_->pid_ = 0;
72 driver_->device_ = NULL;
73 driver_->service_ = NULL;
Darin Petkov36a3ace2012-03-06 17:22:14 +010074 }
Darin Petkova9b1fed2012-02-29 11:49:05 +010075
Darin Petkov33af05c2012-02-28 10:10:30 +010076 protected:
Darin Petkovfe6a9372012-02-28 16:25:06 +010077 static const char kOption[];
78 static const char kProperty[];
79 static const char kValue[];
80 static const char kOption2[];
81 static const char kProperty2[];
82 static const char kValue2[];
Darin Petkov60596742012-03-05 12:17:17 +010083 static const char kGateway1[];
84 static const char kNetmask1[];
85 static const char kNetwork1[];
86 static const char kGateway2[];
87 static const char kNetmask2[];
88 static const char kNetwork2[];
Darin Petkov79d74c92012-03-07 17:20:32 +010089 static const char kInterfaceName[];
90 static const int kInterfaceIndex;
Darin Petkovfe6a9372012-02-28 16:25:06 +010091
Darin Petkove0d5dd12012-04-04 16:10:48 +020092 void SetArg(const std::string &arg, const std::string &value) {
93 driver_->args_.SetString(arg, value);
Darin Petkovfe6a9372012-02-28 16:25:06 +010094 }
95
Darin Petkovf3c71d72012-03-21 12:32:15 +010096 KeyValueStore *GetArgs() {
97 return &driver_->args_;
98 }
99
Paul Stewartca6abd42012-03-01 15:45:29 -0800100 // Used to assert that a flag appears in the options.
101 void ExpectInFlags(const vector<string> &options, const string &flag,
102 const string &value);
103
Paul Stewartebd38562012-03-23 13:06:40 -0700104 bool FindStringPropertyInStore(const PropertyStore &store,
105 const string &key,
106 string *value,
107 Error *error);
108
Darin Petkov36a3ace2012-03-06 17:22:14 +0100109 // Inherited from RPCTaskDelegate.
110 virtual void Notify(const string &reason, const map<string, string> &dict);
Paul Stewartca6abd42012-03-01 15:45:29 -0800111
Darin Petkova9b1fed2012-02-29 11:49:05 +0100112 NiceMockControl control_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800113 MockDeviceInfo device_info_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100114 EventDispatcher dispatcher_;
115 MockMetrics metrics_;
116 MockGLib glib_;
117 MockManager manager_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100118 KeyValueStore args_;
Darin Petkov46463022012-03-29 14:57:32 +0200119 OpenVPNDriver *driver_; // Owned by |service_|.
Darin Petkov79d74c92012-03-07 17:20:32 +0100120 scoped_refptr<MockVPNService> service_;
121 scoped_refptr<MockVPN> device_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200122 MockNSS nss_;
Darin Petkov46463022012-03-29 14:57:32 +0200123
124 // Owned by |driver_|.
125 NiceMock<MockOpenVPNManagementServer> *management_server_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100126};
127
Darin Petkovfe6a9372012-02-28 16:25:06 +0100128const char OpenVPNDriverTest::kOption[] = "--openvpn-option";
129const char OpenVPNDriverTest::kProperty[] = "OpenVPN.SomeProperty";
130const char OpenVPNDriverTest::kValue[] = "some-property-value";
131const char OpenVPNDriverTest::kOption2[] = "--openvpn-option2";
132const char OpenVPNDriverTest::kProperty2[] = "OpenVPN.SomeProperty2";
133const char OpenVPNDriverTest::kValue2[] = "some-property-value2";
Darin Petkov60596742012-03-05 12:17:17 +0100134const char OpenVPNDriverTest::kGateway1[] = "10.242.2.13";
135const char OpenVPNDriverTest::kNetmask1[] = "255.255.255.255";
136const char OpenVPNDriverTest::kNetwork1[] = "10.242.2.1";
137const char OpenVPNDriverTest::kGateway2[] = "10.242.2.14";
138const char OpenVPNDriverTest::kNetmask2[] = "255.255.0.0";
139const char OpenVPNDriverTest::kNetwork2[] = "192.168.0.0";
Darin Petkov79d74c92012-03-07 17:20:32 +0100140const char OpenVPNDriverTest::kInterfaceName[] = "tun0";
141const int OpenVPNDriverTest::kInterfaceIndex = 123;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100142
Darin Petkova9b1fed2012-02-29 11:49:05 +0100143void OpenVPNDriverTest::Notify(const string &/*reason*/,
144 const map<string, string> &/*dict*/) {}
145
Paul Stewartca6abd42012-03-01 15:45:29 -0800146void OpenVPNDriverTest::ExpectInFlags(const vector<string> &options,
147 const string &flag,
148 const string &value) {
149 vector<string>::const_iterator it =
150 std::find(options.begin(), options.end(), flag);
151
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 it++;
156 EXPECT_TRUE(it != options.end());
157 if (it != options.end())
Darin Petkov36a3ace2012-03-06 17:22:14 +0100158 return; // Don't crash below.
Paul Stewartca6abd42012-03-01 15:45:29 -0800159 EXPECT_EQ(value, *it);
160}
161
Paul Stewartebd38562012-03-23 13:06:40 -0700162bool OpenVPNDriverTest::FindStringPropertyInStore(const PropertyStore &store,
163 const string &key,
164 string *value,
165 Error *error) {
166 ReadablePropertyConstIterator<std::string> it =
167 store.GetStringPropertiesIter();
168 for ( ; !it.AtEnd(); it.Advance()) {
169 if (it.Key() == key) {
170 *value = it.Value(error);
171 return error->IsSuccess();
172 }
173 }
174 error->Populate(Error::kNotFound);
175 return false;
176}
Paul Stewartca6abd42012-03-01 15:45:29 -0800177
Darin Petkov33af05c2012-02-28 10:10:30 +0100178TEST_F(OpenVPNDriverTest, Connect) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100179 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
180 const string interface = kInterfaceName;
Darin Petkovf20994f2012-03-05 16:12:19 +0100181 EXPECT_CALL(device_info_, CreateTunnelInterface(_))
Darin Petkov79d74c92012-03-07 17:20:32 +0100182 .WillOnce(DoAll(SetArgumentPointee<0>(interface), Return(true)));
183 Error error;
184 driver_->Connect(service_, &error);
185 EXPECT_TRUE(error.IsSuccess());
186 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
187}
188
189TEST_F(OpenVPNDriverTest, ConnectTunnelFailure) {
190 EXPECT_CALL(*service_, SetState(Service::kStateConfiguring));
191 EXPECT_CALL(device_info_, CreateTunnelInterface(_))
192 .WillOnce(Return(false));
193 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
194 Error error;
195 driver_->Connect(service_, &error);
196 EXPECT_EQ(Error::kInternalError, error.type());
197 EXPECT_TRUE(driver_->tunnel_interface_.empty());
Darin Petkov33af05c2012-02-28 10:10:30 +0100198}
199
Darin Petkov14c29ec2012-03-02 11:34:19 +0100200TEST_F(OpenVPNDriverTest, Notify) {
201 map<string, string> dict;
Darin Petkov79d74c92012-03-07 17:20:32 +0100202 driver_->device_ = device_;
203 EXPECT_CALL(*device_, UpdateIPConfig(_));
204 driver_->Notify("up", dict);
205}
206
207TEST_F(OpenVPNDriverTest, NotifyFail) {
208 map<string, string> dict;
209 driver_->device_ = device_;
210 EXPECT_CALL(*device_, OnDisconnected());
211 driver_->Notify("fail", dict);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100212}
213
Darin Petkov60596742012-03-05 12:17:17 +0100214TEST_F(OpenVPNDriverTest, GetRouteOptionEntry) {
215 OpenVPNDriver::RouteOptions routes;
216 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "bar", &routes));
217 EXPECT_TRUE(routes.empty());
218 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "foo", &routes));
219 EXPECT_TRUE(routes.empty());
220 EXPECT_EQ(NULL, OpenVPNDriver::GetRouteOptionEntry("foo", "fooZ", &routes));
221 EXPECT_TRUE(routes.empty());
222 IPConfig::Route *route =
223 OpenVPNDriver::GetRouteOptionEntry("foo", "foo12", &routes);
224 EXPECT_EQ(1, routes.size());
225 EXPECT_EQ(route, &routes[12]);
226 route = OpenVPNDriver::GetRouteOptionEntry("foo", "foo13", &routes);
227 EXPECT_EQ(2, routes.size());
228 EXPECT_EQ(route, &routes[13]);
229}
230
231TEST_F(OpenVPNDriverTest, ParseRouteOption) {
232 OpenVPNDriver::RouteOptions routes;
233 OpenVPNDriver::ParseRouteOption("foo", "bar", &routes);
234 EXPECT_TRUE(routes.empty());
235 OpenVPNDriver::ParseRouteOption("gateway_2", kGateway2, &routes);
236 OpenVPNDriver::ParseRouteOption("netmask_2", kNetmask2, &routes);
237 OpenVPNDriver::ParseRouteOption("network_2", kNetwork2, &routes);
238 EXPECT_EQ(1, routes.size());
239 OpenVPNDriver::ParseRouteOption("gateway_1", kGateway1, &routes);
240 OpenVPNDriver::ParseRouteOption("netmask_1", kNetmask1, &routes);
241 OpenVPNDriver::ParseRouteOption("network_1", kNetwork1, &routes);
242 EXPECT_EQ(2, routes.size());
243 EXPECT_EQ(kGateway1, routes[1].gateway);
244 EXPECT_EQ(kNetmask1, routes[1].netmask);
245 EXPECT_EQ(kNetwork1, routes[1].host);
246 EXPECT_EQ(kGateway2, routes[2].gateway);
247 EXPECT_EQ(kNetmask2, routes[2].netmask);
248 EXPECT_EQ(kNetwork2, routes[2].host);
249}
250
251TEST_F(OpenVPNDriverTest, SetRoutes) {
252 OpenVPNDriver::RouteOptions routes;
253 routes[1].gateway = "1.2.3.4";
254 routes[1].host= "1.2.3.4";
255 routes[2].host = "2.3.4.5";
256 routes[2].netmask = "255.0.0.0";
257 routes[3].netmask = "255.0.0.0";
258 routes[3].gateway = "1.2.3.5";
259 routes[5].host = kNetwork2;
260 routes[5].netmask = kNetmask2;
261 routes[5].gateway = kGateway2;
262 routes[4].host = kNetwork1;
263 routes[4].netmask = kNetmask1;
264 routes[4].gateway = kGateway1;
265 IPConfig::Properties props;
266 OpenVPNDriver::SetRoutes(routes, &props);
267 ASSERT_EQ(2, props.routes.size());
268 EXPECT_EQ(kGateway1, props.routes[0].gateway);
269 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
270 EXPECT_EQ(kNetwork1, props.routes[0].host);
271 EXPECT_EQ(kGateway2, props.routes[1].gateway);
272 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
273 EXPECT_EQ(kNetwork2, props.routes[1].host);
274}
275
Darin Petkov14c29ec2012-03-02 11:34:19 +0100276TEST_F(OpenVPNDriverTest, ParseForeignOption) {
277 IPConfig::Properties props;
278 OpenVPNDriver::ParseForeignOption("", &props);
279 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN", &props);
280 OpenVPNDriver::ParseForeignOption("dhcp-option DOMAIN zzz.com foo", &props);
281 OpenVPNDriver::ParseForeignOption("dhcp-Option DOmAIN xyz.com", &props);
282 ASSERT_EQ(1, props.domain_search.size());
283 EXPECT_EQ("xyz.com", props.domain_search[0]);
284 OpenVPNDriver::ParseForeignOption("dhcp-option DnS 1.2.3.4", &props);
285 ASSERT_EQ(1, props.dns_servers.size());
286 EXPECT_EQ("1.2.3.4", props.dns_servers[0]);
287}
288
289TEST_F(OpenVPNDriverTest, ParseForeignOptions) {
290 // Basically test that std::map is a sorted container.
291 map<int, string> options;
292 options[5] = "dhcp-option DOMAIN five.com";
293 options[2] = "dhcp-option DOMAIN two.com";
294 options[8] = "dhcp-option DOMAIN eight.com";
295 options[7] = "dhcp-option DOMAIN seven.com";
296 options[4] = "dhcp-option DOMAIN four.com";
297 IPConfig::Properties props;
298 OpenVPNDriver::ParseForeignOptions(options, &props);
299 ASSERT_EQ(5, props.domain_search.size());
300 EXPECT_EQ("two.com", props.domain_search[0]);
301 EXPECT_EQ("four.com", props.domain_search[1]);
302 EXPECT_EQ("five.com", props.domain_search[2]);
303 EXPECT_EQ("seven.com", props.domain_search[3]);
304 EXPECT_EQ("eight.com", props.domain_search[4]);
305}
306
307TEST_F(OpenVPNDriverTest, ParseIPConfiguration) {
308 map<string, string> config;
309 config["ifconfig_loCal"] = "4.5.6.7";
310 config["ifconfiG_broadcast"] = "1.2.255.255";
311 config["ifconFig_netmAsk"] = "255.255.255.0";
312 config["ifconfig_remotE"] = "33.44.55.66";
313 config["route_vpN_gateway"] = "192.168.1.1";
Paul Stewartce4ec192012-03-14 12:53:46 -0700314 config["trusted_ip"] = "99.88.77.66";
Darin Petkov14c29ec2012-03-02 11:34:19 +0100315 config["tun_mtu"] = "1000";
316 config["foreign_option_2"] = "dhcp-option DNS 4.4.4.4";
317 config["foreign_option_1"] = "dhcp-option DNS 1.1.1.1";
318 config["foreign_option_3"] = "dhcp-option DNS 2.2.2.2";
Darin Petkov60596742012-03-05 12:17:17 +0100319 config["route_network_2"] = kNetwork2;
320 config["route_network_1"] = kNetwork1;
321 config["route_netmask_2"] = kNetmask2;
322 config["route_netmask_1"] = kNetmask1;
323 config["route_gateway_2"] = kGateway2;
324 config["route_gateway_1"] = kGateway1;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100325 config["foo"] = "bar";
326 IPConfig::Properties props;
327 OpenVPNDriver::ParseIPConfiguration(config, &props);
328 EXPECT_EQ(IPAddress::kFamilyIPv4, props.address_family);
329 EXPECT_EQ("4.5.6.7", props.address);
330 EXPECT_EQ("1.2.255.255", props.broadcast_address);
Paul Stewart48100b02012-03-19 07:53:52 -0700331 EXPECT_EQ(24, props.subnet_prefix);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100332 EXPECT_EQ("33.44.55.66", props.peer_address);
333 EXPECT_EQ("192.168.1.1", props.gateway);
Paul Stewartce4ec192012-03-14 12:53:46 -0700334 EXPECT_EQ("99.88.77.66", props.trusted_ip);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100335 EXPECT_EQ(1000, props.mtu);
336 ASSERT_EQ(3, props.dns_servers.size());
337 EXPECT_EQ("1.1.1.1", props.dns_servers[0]);
338 EXPECT_EQ("4.4.4.4", props.dns_servers[1]);
339 EXPECT_EQ("2.2.2.2", props.dns_servers[2]);
Darin Petkov60596742012-03-05 12:17:17 +0100340 ASSERT_EQ(2, props.routes.size());
341 EXPECT_EQ(kGateway1, props.routes[0].gateway);
342 EXPECT_EQ(kNetmask1, props.routes[0].netmask);
343 EXPECT_EQ(kNetwork1, props.routes[0].host);
344 EXPECT_EQ(kGateway2, props.routes[1].gateway);
345 EXPECT_EQ(kNetmask2, props.routes[1].netmask);
346 EXPECT_EQ(kNetwork2, props.routes[1].host);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100347}
348
Darin Petkovfe6a9372012-02-28 16:25:06 +0100349TEST_F(OpenVPNDriverTest, InitOptionsNoHost) {
350 Error error;
351 vector<string> options;
Darin Petkov79d74c92012-03-07 17:20:32 +0100352 driver_->InitOptions(&options, &error);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100353 EXPECT_EQ(Error::kInvalidArguments, error.type());
354 EXPECT_TRUE(options.empty());
355}
356
357TEST_F(OpenVPNDriverTest, InitOptions) {
358 static const char kHost[] = "192.168.2.254";
Darin Petkov1fa81942012-04-02 11:38:08 +0200359 static const char kTLSAuthContents[] = "SOME-RANDOM-CONTENTS\n";
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200360 static const char kCaCertNSS[] = "{1234}";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200361 static const char kID[] = "TestPKCS11ID";
362 FilePath empty_cert;
363 SetArg(flimflam::kProviderHostProperty, kHost);
364 SetArg(flimflam::kOpenVPNTLSAuthContentsProperty, kTLSAuthContents);
365 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
366 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
Darin Petkov79d74c92012-03-07 17:20:32 +0100367 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov79d74c92012-03-07 17:20:32 +0100368 driver_->tunnel_interface_ = kInterfaceName;
Darin Petkove0d5dd12012-04-04 16:10:48 +0200369 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
370 EXPECT_CALL(nss_, GetPEMCertfile(kCaCertNSS, _)).WillOnce(Return(empty_cert));
371
372 Error error;
373 vector<string> options;
374 driver_->InitOptions(&options, &error);
375 EXPECT_TRUE(error.IsSuccess());
376 EXPECT_EQ("--client", options[0]);
377 ExpectInFlags(options, "--remote", kHost);
378 ExpectInFlags(options, "CONNMAN_PATH", RPCTaskMockAdaptor::kRpcId);
379 ExpectInFlags(options, "--dev", kInterfaceName);
380 ExpectInFlags(options, "--group", "openvpn");
381 EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
382 ASSERT_FALSE(driver_->tls_auth_file_.empty());
383 ExpectInFlags(options, "--tls-auth", driver_->tls_auth_file_.value());
384 string contents;
385 EXPECT_TRUE(
386 file_util::ReadFileToString(driver_->tls_auth_file_, &contents));
387 EXPECT_EQ(kTLSAuthContents, contents);
388 ExpectInFlags(options, "--pkcs11-id", kID);
389}
390
391TEST_F(OpenVPNDriverTest, InitNSSOptions) {
392 static const char kHost[] = "192.168.2.254";
393 static const char kCaCertNSS[] = "{1234}";
394 static const char kNSSCertfile[] = "/tmp/nss-cert";
395 FilePath empty_cert;
396 FilePath nss_cert(kNSSCertfile);
397 SetArg(flimflam::kProviderHostProperty, kHost);
398 SetArg(flimflam::kOpenVPNCaCertNSSProperty, kCaCertNSS);
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200399 EXPECT_CALL(nss_,
400 GetPEMCertfile(kCaCertNSS,
401 ElementsAreArray(kHost, arraysize(kHost) - 1)))
Darin Petkove0d5dd12012-04-04 16:10:48 +0200402 .WillOnce(Return(empty_cert))
403 .WillOnce(Return(nss_cert));
404
405 Error error;
406 vector<string> options;
407 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
408 EXPECT_TRUE(error.IsSuccess());
409 EXPECT_TRUE(options.empty());
410 EXPECT_TRUE(driver_->InitNSSOptions(&options, &error));
411 ExpectInFlags(options, "--ca", kNSSCertfile);
412 EXPECT_TRUE(error.IsSuccess());
413
414 SetArg(flimflam::kOpenVPNCaCertProperty, "foo");
415 options.clear();
416 EXPECT_FALSE(driver_->InitNSSOptions(&options, &error));
417 EXPECT_EQ(Error::kInvalidArguments, error.type());
418 EXPECT_EQ("Can't specify both CACert and CACertNSS.", error.message());
419}
420
421TEST_F(OpenVPNDriverTest, InitPKCS11Options) {
422 vector<string> options;
423 driver_->InitPKCS11Options(&options);
424 EXPECT_TRUE(options.empty());
425
426 static const char kID[] = "TestPKCS11ID";
427 SetArg(flimflam::kOpenVPNClientCertIdProperty, kID);
428 driver_->InitPKCS11Options(&options);
429 ExpectInFlags(options, "--pkcs11-id", kID);
430 ExpectInFlags(options, "--pkcs11-providers", "libchaps.so");
431
432 static const char kProvider[] = "libpkcs11.so";
433 SetArg(flimflam::kOpenVPNProviderProperty, kProvider);
434 options.clear();
435 driver_->InitPKCS11Options(&options);
436 ExpectInFlags(options, "--pkcs11-id", kID);
437 ExpectInFlags(options, "--pkcs11-providers", kProvider);
438}
439
440TEST_F(OpenVPNDriverTest, InitManagementChannelOptions) {
441 vector<string> options;
442 EXPECT_CALL(*management_server_,
443 Start(&dispatcher_, &driver_->sockets_, &options))
444 .WillOnce(Return(false))
445 .WillOnce(Return(true));
446
447 Error error;
448 EXPECT_FALSE(driver_->InitManagementChannelOptions(&options, &error));
449 EXPECT_EQ(Error::kInternalError, error.type());
450 EXPECT_EQ("Unable to setup management channel.", error.message());
451
452 error.Reset();
453 EXPECT_TRUE(driver_->InitManagementChannelOptions(&options, &error));
454 EXPECT_TRUE(error.IsSuccess());
Darin Petkovfe6a9372012-02-28 16:25:06 +0100455}
456
457TEST_F(OpenVPNDriverTest, AppendValueOption) {
458 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200459 EXPECT_FALSE(
460 driver_->AppendValueOption("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100461 EXPECT_TRUE(options.empty());
462
Darin Petkove0d5dd12012-04-04 16:10:48 +0200463 SetArg(kProperty, "");
Darin Petkov46463022012-03-29 14:57:32 +0200464 EXPECT_FALSE(driver_->AppendValueOption(kProperty, kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100465 EXPECT_TRUE(options.empty());
466
Darin Petkove0d5dd12012-04-04 16:10:48 +0200467 SetArg(kProperty, kValue);
468 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200469 EXPECT_TRUE(driver_->AppendValueOption(kProperty, kOption, &options));
470 EXPECT_TRUE(driver_->AppendValueOption(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100471 EXPECT_EQ(4, options.size());
472 EXPECT_EQ(kOption, options[0]);
473 EXPECT_EQ(kValue, options[1]);
474 EXPECT_EQ(kOption2, options[2]);
475 EXPECT_EQ(kValue2, options[3]);
476}
477
478TEST_F(OpenVPNDriverTest, AppendFlag) {
479 vector<string> options;
Darin Petkov46463022012-03-29 14:57:32 +0200480 EXPECT_FALSE(
481 driver_->AppendFlag("OpenVPN.UnknownProperty", kOption, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100482 EXPECT_TRUE(options.empty());
483
Darin Petkove0d5dd12012-04-04 16:10:48 +0200484 SetArg(kProperty, "");
485 SetArg(kProperty2, kValue2);
Darin Petkov46463022012-03-29 14:57:32 +0200486 EXPECT_TRUE(driver_->AppendFlag(kProperty, kOption, &options));
487 EXPECT_TRUE(driver_->AppendFlag(kProperty2, kOption2, &options));
Darin Petkovfe6a9372012-02-28 16:25:06 +0100488 EXPECT_EQ(2, options.size());
489 EXPECT_EQ(kOption, options[0]);
490 EXPECT_EQ(kOption2, options[1]);
491}
492
Paul Stewartca6abd42012-03-01 15:45:29 -0800493TEST_F(OpenVPNDriverTest, ClaimInterface) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100494 driver_->tunnel_interface_ = kInterfaceName;
495 EXPECT_FALSE(driver_->ClaimInterface(string(kInterfaceName) + "XXX",
496 kInterfaceIndex));
497 EXPECT_FALSE(driver_->device_);
Paul Stewartca6abd42012-03-01 15:45:29 -0800498
Darin Petkov36a3ace2012-03-06 17:22:14 +0100499 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200500 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov46463022012-03-29 14:57:32 +0200501 EXPECT_CALL(*management_server_, Start(_, _, _)).WillOnce(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100502 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
503 .WillOnce(Return(true));
504 EXPECT_CALL(glib_, ChildWatchAdd(_, _, _)).WillOnce(Return(1));
Darin Petkov79d74c92012-03-07 17:20:32 +0100505 EXPECT_TRUE(driver_->ClaimInterface(kInterfaceName, kInterfaceIndex));
506 ASSERT_TRUE(driver_->device_);
507 EXPECT_EQ(kInterfaceIndex, driver_->device_->interface_index());
Paul Stewartca6abd42012-03-01 15:45:29 -0800508}
509
Darin Petkov36a3ace2012-03-06 17:22:14 +0100510TEST_F(OpenVPNDriverTest, Cleanup) {
Darin Petkov1fa81942012-04-02 11:38:08 +0200511 driver_->Cleanup(Service::kStateIdle); // Ensure no crash.
512
Darin Petkov36a3ace2012-03-06 17:22:14 +0100513 const unsigned int kTag = 123;
514 const int kPID = 123456;
Darin Petkov79d74c92012-03-07 17:20:32 +0100515 driver_->child_watch_tag_ = kTag;
516 driver_->pid_ = kPID;
517 driver_->rpc_task_.reset(new RPCTask(&control_, this));
518 driver_->tunnel_interface_ = kInterfaceName;
519 driver_->device_ = device_;
520 driver_->service_ = service_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200521 FilePath tls_auth_file;
522 EXPECT_TRUE(file_util::CreateTemporaryFile(&tls_auth_file));
523 EXPECT_FALSE(tls_auth_file.empty());
524 EXPECT_TRUE(file_util::PathExists(tls_auth_file));
525 driver_->tls_auth_file_ = tls_auth_file;
Darin Petkov46463022012-03-29 14:57:32 +0200526 // Stop will be called twice -- once by Cleanup and once by the destructor.
527 EXPECT_CALL(*management_server_, Stop()).Times(2);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100528 EXPECT_CALL(glib_, SourceRemove(kTag));
529 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500530 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov79d74c92012-03-07 17:20:32 +0100531 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
532 EXPECT_CALL(*service_, SetState(Service::kStateFailure));
Darin Petkov3f9131c2012-03-20 11:37:32 +0100533 driver_->Cleanup(Service::kStateFailure);
Darin Petkov79d74c92012-03-07 17:20:32 +0100534 EXPECT_EQ(0, driver_->child_watch_tag_);
535 EXPECT_EQ(0, driver_->pid_);
536 EXPECT_FALSE(driver_->rpc_task_.get());
537 EXPECT_TRUE(driver_->tunnel_interface_.empty());
538 EXPECT_FALSE(driver_->device_);
539 EXPECT_FALSE(driver_->service_);
Darin Petkov1fa81942012-04-02 11:38:08 +0200540 EXPECT_FALSE(file_util::PathExists(tls_auth_file));
541 EXPECT_TRUE(driver_->tls_auth_file_.empty());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100542}
543
544TEST_F(OpenVPNDriverTest, SpawnOpenVPN) {
Darin Petkov79d74c92012-03-07 17:20:32 +0100545 EXPECT_FALSE(driver_->SpawnOpenVPN());
Darin Petkov36a3ace2012-03-06 17:22:14 +0100546
547 static const char kHost[] = "192.168.2.254";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200548 SetArg(flimflam::kProviderHostProperty, kHost);
Darin Petkov79d74c92012-03-07 17:20:32 +0100549 driver_->tunnel_interface_ = "tun0";
550 driver_->rpc_task_.reset(new RPCTask(&control_, this));
Darin Petkov46463022012-03-29 14:57:32 +0200551 EXPECT_CALL(*management_server_, Start(_, _, _))
552 .Times(2)
553 .WillRepeatedly(Return(true));
Darin Petkov36a3ace2012-03-06 17:22:14 +0100554
555 const int kPID = 234678;
556 EXPECT_CALL(glib_, SpawnAsyncWithPipesCWD(_, _, _, _, _, _, _, _, _, _))
557 .WillOnce(Return(false))
558 .WillOnce(DoAll(SetArgumentPointee<5>(kPID), Return(true)));
559 const int kTag = 6;
Darin Petkov79d74c92012-03-07 17:20:32 +0100560 EXPECT_CALL(glib_, ChildWatchAdd(kPID, &driver_->OnOpenVPNDied, driver_))
Darin Petkov36a3ace2012-03-06 17:22:14 +0100561 .WillOnce(Return(kTag));
Darin Petkov79d74c92012-03-07 17:20:32 +0100562 EXPECT_FALSE(driver_->SpawnOpenVPN());
563 EXPECT_TRUE(driver_->SpawnOpenVPN());
564 EXPECT_EQ(kPID, driver_->pid_);
565 EXPECT_EQ(kTag, driver_->child_watch_tag_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100566}
567
568TEST_F(OpenVPNDriverTest, OnOpenVPNDied) {
569 const int kPID = 99999;
Darin Petkov79d74c92012-03-07 17:20:32 +0100570 driver_->child_watch_tag_ = 333;
571 driver_->pid_ = kPID;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100572 EXPECT_CALL(glib_, SpawnClosePID(kPID));
Darin Petkov79d74c92012-03-07 17:20:32 +0100573 OpenVPNDriver::OnOpenVPNDied(kPID, 2, driver_);
574 EXPECT_EQ(0, driver_->child_watch_tag_);
575 EXPECT_EQ(0, driver_->pid_);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100576}
577
Darin Petkov6aa21872012-03-09 16:10:19 +0100578TEST_F(OpenVPNDriverTest, Disconnect) {
579 driver_->device_ = device_;
580 driver_->service_ = service_;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500581 EXPECT_CALL(*device_, SetEnabled(false));
Darin Petkov6aa21872012-03-09 16:10:19 +0100582 EXPECT_CALL(device_info_, DeleteInterface(kInterfaceIndex));
583 EXPECT_CALL(*service_, SetState(Service::kStateIdle));
584 driver_->Disconnect();
585 EXPECT_FALSE(driver_->service_);
586}
587
Darin Petkov271fe522012-03-27 13:47:29 +0200588TEST_F(OpenVPNDriverTest, OnReconnecting) {
589 driver_->OnReconnecting(); // Expect no crash.
590 driver_->device_ = device_;
591 driver_->service_ = service_;
592 EXPECT_CALL(*device_, OnDisconnected());
593 EXPECT_CALL(*service_, SetState(Service::kStateAssociating));
594 driver_->OnReconnecting();
595}
596
Paul Stewartce4ec192012-03-14 12:53:46 -0700597MATCHER_P(IsIPAddress, address, "") {
598 IPAddress ip_address(IPAddress::kFamilyIPv4);
599 EXPECT_TRUE(ip_address.SetAddressFromString(address));
600 return ip_address.Equals(arg);
601}
602
603TEST_F(OpenVPNDriverTest, PinHostRoute) {
604 IPConfig::Properties props;
605 props.address_family = IPAddress::kFamilyIPv4;
606 EXPECT_FALSE(driver_->PinHostRoute(props));
607
608 props.gateway = kGateway1;
609 EXPECT_FALSE(driver_->PinHostRoute(props));
610
611 props.gateway.clear();
612 props.trusted_ip = "xxx";
613 EXPECT_FALSE(driver_->PinHostRoute(props));
614
615 props.gateway = kGateway1;
616 EXPECT_FALSE(driver_->PinHostRoute(props));
617
618 props.trusted_ip = kNetwork1;
619 EXPECT_CALL(manager_, GetDefaultService())
620 .WillOnce(Return(reinterpret_cast<Service *>(NULL)));
621 EXPECT_FALSE(driver_->PinHostRoute(props));
622
623 scoped_refptr<MockService> mock_service(
624 new NiceMock<MockService>(&control_,
625 &dispatcher_,
626 &metrics_,
627 &manager_));
628 scoped_refptr<MockConnection> mock_connection(
629 new StrictMock<MockConnection>(&device_info_));
630 mock_service->set_mock_connection(mock_connection);
631 EXPECT_CALL(manager_, GetDefaultService())
632 .WillOnce(Return(mock_service));
633
634 EXPECT_CALL(*mock_connection.get(), RequestHostRoute(IsIPAddress(kNetwork1)))
635 .WillOnce(Return(false));
636 EXPECT_FALSE(driver_->PinHostRoute(props));
637
638 EXPECT_CALL(manager_, GetDefaultService())
639 .WillOnce(Return(mock_service));
640 EXPECT_CALL(*mock_connection.get(), RequestHostRoute(IsIPAddress(kNetwork1)))
641 .WillOnce(Return(true));
642 EXPECT_TRUE(driver_->PinHostRoute(props));
643}
644
Paul Stewart291a4732012-03-14 19:19:02 -0700645TEST_F(OpenVPNDriverTest, VerifyPaths) {
646 // Ensure that the various path constants that the OpenVPN driver uses
647 // actually exists in the build image. Due to build dependencies, they
648 // should already exist by the time we run unit tests.
649
650 // The OpenVPNDriver path constants are absolute. FilePath::Append
651 // asserts that its argument is not an absolute path, so we need to
652 // strip the leading separators. There's nothing built into FilePath
653 // to do so.
654 string vpn_path(OpenVPNDriver::kOpenVPNPath);
655 TrimString(vpn_path, FilePath::kSeparators, &vpn_path);
656 EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(vpn_path)));
657
658 string vpn_script(OpenVPNDriver::kOpenVPNScript);
659 TrimString(vpn_script, FilePath::kSeparators, &vpn_script);
660 EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(vpn_script)));
661}
662
Darin Petkovf3c71d72012-03-21 12:32:15 +0100663TEST_F(OpenVPNDriverTest, Load) {
664 MockStore storage;
665 static const char kStorageID[] = "vpn_service_id";
666 const string port = "1234";
667 const string password = "random-password";
668 EXPECT_CALL(storage, GetString(kStorageID, _, _))
669 .WillRepeatedly(Return(false));
670 EXPECT_CALL(storage, GetString(kStorageID, flimflam::kOpenVPNPortProperty, _))
671 .WillOnce(DoAll(SetArgumentPointee<2>(port), Return(true)));
672 EXPECT_CALL(storage, GetCryptedString(kStorageID,
673 flimflam::kOpenVPNPasswordProperty,
674 _))
675 .WillOnce(DoAll(SetArgumentPointee<2>(password), Return(true)));
676 EXPECT_TRUE(driver_->Load(&storage, kStorageID));
677 EXPECT_EQ(port,
678 GetArgs()->LookupString(flimflam::kOpenVPNPortProperty, ""));
679 EXPECT_EQ(password,
680 GetArgs()->LookupString(flimflam::kOpenVPNPasswordProperty, ""));
681}
682
683TEST_F(OpenVPNDriverTest, Store) {
684 const string key_direction = "1";
685 const string password = "foobar";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200686 SetArg(flimflam::kOpenVPNKeyDirectionProperty, key_direction);
687 SetArg(flimflam::kOpenVPNPasswordProperty, password);
Darin Petkovf3c71d72012-03-21 12:32:15 +0100688 MockStore storage;
689 static const char kStorageID[] = "vpn_service_id";
690 EXPECT_CALL(storage,
691 SetString(kStorageID,
692 flimflam::kOpenVPNKeyDirectionProperty,
693 key_direction))
694 .WillOnce(Return(true));
695 EXPECT_CALL(storage, SetCryptedString(kStorageID,
696 flimflam::kOpenVPNPasswordProperty,
697 password))
698 .WillOnce(Return(true));
699 EXPECT_CALL(storage, DeleteKey(kStorageID, _)).Times(AnyNumber());
700 EXPECT_CALL(storage, DeleteKey(kStorageID, flimflam::kOpenVPNAuthProperty))
701 .Times(1);
702 EXPECT_TRUE(driver_->Save(&storage, kStorageID));
703}
704
Paul Stewartebd38562012-03-23 13:06:40 -0700705TEST_F(OpenVPNDriverTest, InitPropertyStore) {
706 // Figure out if the store is actually hooked up to the driver argument
707 // KeyValueStore.
708 PropertyStore store;
709 driver_->InitPropertyStore(&store);
710
711 // An un-set property in OpenVPN should not be readable.
712 {
713 Error error;
714 string string_property;
715 EXPECT_FALSE(
716 FindStringPropertyInStore(store, flimflam::kOpenVPNKeyDirectionProperty,
717 &string_property,
718 &error));
719 EXPECT_EQ(Error::kNotFound, error.type());
720 }
721
722 const string kKeyDirection = "1";
723 const string kPassword0 = "foobar";
724 const string kPassword1 = "baz";
Darin Petkove0d5dd12012-04-04 16:10:48 +0200725 SetArg(flimflam::kOpenVPNKeyDirectionProperty, kKeyDirection);
726 SetArg(flimflam::kOpenVPNPasswordProperty, kPassword0);
Paul Stewartebd38562012-03-23 13:06:40 -0700727
728 // Read a property out of the driver args using the PropertyStore interface.
729 {
730 Error error;
731 string string_property;
732 EXPECT_TRUE(
733 FindStringPropertyInStore(store, flimflam::kOpenVPNKeyDirectionProperty,
734 &string_property,
735 &error));
736 EXPECT_EQ(kKeyDirection, string_property);
737 }
738
739 // If we clear this property, we should no longer be able to find it.
740 {
741 Error error;
742 EXPECT_TRUE(store.ClearProperty(flimflam::kOpenVPNKeyDirectionProperty,
743 &error));
744 EXPECT_TRUE(error.IsSuccess());
745 }
746
747 {
748 Error error;
749 string string_property;
750 EXPECT_FALSE(
751 FindStringPropertyInStore(store, flimflam::kOpenVPNKeyDirectionProperty,
752 &string_property,
753 &error));
754 EXPECT_EQ(Error::kNotFound, error.type());
755 }
756
757 // A second attempt to clear this property should return an error.
758 {
759 Error error;
760 EXPECT_FALSE(store.ClearProperty(flimflam::kOpenVPNKeyDirectionProperty,
761 &error));
762 EXPECT_EQ(Error::kNotFound, error.type());
763 }
764
765 // This one should be write-only.
766 {
767 Error error;
768 string string_property;
769 EXPECT_FALSE(
770 FindStringPropertyInStore(store, flimflam::kOpenVPNPasswordProperty,
771 &string_property,
772 &error));
773 // We get NotFound here instead of PermissionDenied here due to the
774 // implementation of ReadablePropertyConstIterator: it shields us from
775 // store members for which Value() would have returned an error.
776 EXPECT_EQ(Error::kNotFound, error.type());
777 }
778
779 // Write a property to the driver args using the PropertyStore interface.
780 {
781 Error error;
782 EXPECT_TRUE(store.SetStringProperty(flimflam::kOpenVPNPasswordProperty,
783 kPassword1,
784 &error));
785 }
786
787 KeyValueStore *driver_args = GetArgs();
788 EXPECT_EQ(kPassword1,
789 driver_args->GetString(flimflam::kOpenVPNPasswordProperty));
790}
791
Darin Petkov33af05c2012-02-28 10:10:30 +0100792} // namespace shill