blob: d51d19d0e69c177f4da30051fa500ec3792a7e55 [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#ifndef SHILL_OPENVPN_DRIVER_
6#define SHILL_OPENVPN_DRIVER_
7
Darin Petkov14c29ec2012-03-02 11:34:19 +01008#include <map>
Darin Petkovfe6a9372012-02-28 16:25:06 +01009#include <string>
10#include <vector>
11
Darin Petkov1fa81942012-04-02 11:38:08 +020012#include <base/file_path.h>
Darin Petkova9b1fed2012-02-29 11:49:05 +010013#include <base/memory/scoped_ptr.h>
Darin Petkovfe6a9372012-02-28 16:25:06 +010014#include <gtest/gtest_prod.h> // for FRIEND_TEST
15
Darin Petkov36a3ace2012-03-06 17:22:14 +010016#include "shill/glib.h"
Paul Stewarte93b0382012-04-24 13:11:28 -070017#include "shill/ipconfig.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010018#include "shill/refptr_types.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010019#include "shill/rpc_task.h"
Darin Petkov3f9131c2012-03-20 11:37:32 +010020#include "shill/service.h"
Darin Petkov46463022012-03-29 14:57:32 +020021#include "shill/sockets.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010022#include "shill/vpn_driver.h"
23
24namespace shill {
25
Darin Petkova9b1fed2012-02-29 11:49:05 +010026class ControlInterface;
Paul Stewartca6abd42012-03-01 15:45:29 -080027class DeviceInfo;
Darin Petkov33af05c2012-02-28 10:10:30 +010028class Error;
Darin Petkovf20994f2012-03-05 16:12:19 +010029class EventDispatcher;
Darin Petkovf20994f2012-03-05 16:12:19 +010030class Metrics;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020031class NSS;
Darin Petkov46463022012-03-29 14:57:32 +020032class OpenVPNManagementServer;
Darin Petkov33af05c2012-02-28 10:10:30 +010033
Darin Petkov36a3ace2012-03-06 17:22:14 +010034class OpenVPNDriver : public VPNDriver,
35 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010036 public:
Paul Stewartca6abd42012-03-01 15:45:29 -080037 OpenVPNDriver(ControlInterface *control,
Darin Petkovf20994f2012-03-05 16:12:19 +010038 EventDispatcher *dispatcher,
39 Metrics *metrics,
40 Manager *manager,
Paul Stewartca6abd42012-03-01 15:45:29 -080041 DeviceInfo *device_info,
Paul Stewart451aa7f2012-04-11 19:07:58 -070042 GLib *glib);
Darin Petkov33af05c2012-02-28 10:10:30 +010043 virtual ~OpenVPNDriver();
44
Darin Petkovf20994f2012-03-05 16:12:19 +010045 // Inherited from VPNDriver. |Connect| initiates the VPN connection by
46 // creating a tunnel device. When the device index becomes available, this
47 // instance is notified through |ClaimInterface| and resumes the connection
48 // process by setting up and spawning an external 'openvpn' process. IP
49 // configuration settings are passed back from the external process through
50 // the |Notify| RPC service method.
Darin Petkov79d74c92012-03-07 17:20:32 +010051 virtual void Connect(const VPNServiceRefPtr &service, Error *error);
Paul Stewartca6abd42012-03-01 15:45:29 -080052 virtual bool ClaimInterface(const std::string &link_name,
53 int interface_index);
Darin Petkov6aa21872012-03-09 16:10:19 +010054 virtual void Disconnect();
Darin Petkov33af05c2012-02-28 10:10:30 +010055
Darin Petkov271fe522012-03-27 13:47:29 +020056 virtual void OnReconnecting();
57
Paul Stewart39964fa2012-04-04 09:50:25 -070058 virtual std::string GetProviderType() const;
59
Darin Petkov0440b9b2012-04-17 16:11:56 +020060 virtual void Cleanup(Service::ConnectState state);
61
Darin Petkov46463022012-03-29 14:57:32 +020062 // Returns true if an opton was appended.
63 bool AppendValueOption(const std::string &property,
64 const std::string &option,
65 std::vector<std::string> *options);
66
67 // Returns true if a flag was appended.
68 bool AppendFlag(const std::string &property,
69 const std::string &option,
70 std::vector<std::string> *options);
71
Darin Petkov33af05c2012-02-28 10:10:30 +010072 private:
Darin Petkovfe6a9372012-02-28 16:25:06 +010073 friend class OpenVPNDriverTest;
Paul Stewartca6abd42012-03-01 15:45:29 -080074 FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
Darin Petkov36a3ace2012-03-06 17:22:14 +010075 FRIEND_TEST(OpenVPNDriverTest, Cleanup);
Darin Petkovf20994f2012-03-05 16:12:19 +010076 FRIEND_TEST(OpenVPNDriverTest, Connect);
Darin Petkov79d74c92012-03-07 17:20:32 +010077 FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
Darin Petkov6aa21872012-03-09 16:10:19 +010078 FRIEND_TEST(OpenVPNDriverTest, Disconnect);
Darin Petkov60596742012-03-05 12:17:17 +010079 FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
Darin Petkov55771b72012-04-25 09:25:19 +020080 FRIEND_TEST(OpenVPNDriverTest, InitLoggingOptions);
Darin Petkove0d5dd12012-04-04 16:10:48 +020081 FRIEND_TEST(OpenVPNDriverTest, InitManagementChannelOptions);
82 FRIEND_TEST(OpenVPNDriverTest, InitNSSOptions);
Darin Petkovfe6a9372012-02-28 16:25:06 +010083 FRIEND_TEST(OpenVPNDriverTest, InitOptions);
84 FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
Darin Petkove0d5dd12012-04-04 16:10:48 +020085 FRIEND_TEST(OpenVPNDriverTest, InitPKCS11Options);
Darin Petkov36a3ace2012-03-06 17:22:14 +010086 FRIEND_TEST(OpenVPNDriverTest, Notify);
Darin Petkov79d74c92012-03-07 17:20:32 +010087 FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
Darin Petkov36a3ace2012-03-06 17:22:14 +010088 FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
Darin Petkov271fe522012-03-27 13:47:29 +020089 FRIEND_TEST(OpenVPNDriverTest, OnReconnecting);
Darin Petkov14c29ec2012-03-02 11:34:19 +010090 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
91 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
92 FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
Darin Petkov60596742012-03-05 12:17:17 +010093 FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
94 FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
Darin Petkov36a3ace2012-03-06 17:22:14 +010095 FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
Paul Stewart291a4732012-03-14 19:19:02 -070096 FRIEND_TEST(OpenVPNDriverTest, VerifyPaths);
97
98 static const char kOpenVPNPath[];
99 static const char kOpenVPNScript[];
Paul Stewartebd38562012-03-23 13:06:40 -0700100 static const Property kProperties[];
Darin Petkov14c29ec2012-03-02 11:34:19 +0100101
102 // The map is a sorted container that allows us to iterate through the options
103 // in order.
104 typedef std::map<int, std::string> ForeignOptions;
Darin Petkov60596742012-03-05 12:17:17 +0100105 typedef std::map<int, IPConfig::Route> RouteOptions;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100106
107 static void ParseIPConfiguration(
108 const std::map<std::string, std::string> &configuration,
109 IPConfig::Properties *properties);
110 static void ParseForeignOptions(const ForeignOptions &options,
111 IPConfig::Properties *properties);
112 static void ParseForeignOption(const std::string &option,
113 IPConfig::Properties *properties);
Darin Petkov60596742012-03-05 12:17:17 +0100114 static IPConfig::Route *GetRouteOptionEntry(const std::string &prefix,
115 const std::string &key,
116 RouteOptions *routes);
117 static void ParseRouteOption(const std::string &key,
118 const std::string &value,
119 RouteOptions *routes);
120 static void SetRoutes(const RouteOptions &routes,
121 IPConfig::Properties *properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100122
123 void InitOptions(std::vector<std::string> *options, Error *error);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200124 bool InitNSSOptions(std::vector<std::string> *options, Error *error);
125 void InitPKCS11Options(std::vector<std::string> *options);
126 bool InitManagementChannelOptions(
127 std::vector<std::string> *options, Error *error);
Darin Petkov55771b72012-04-25 09:25:19 +0200128 void InitLoggingOptions(std::vector<std::string> *options);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100129
Darin Petkov36a3ace2012-03-06 17:22:14 +0100130 bool SpawnOpenVPN();
Darin Petkov36a3ace2012-03-06 17:22:14 +0100131
132 // Called when the openpvn process exits.
133 static void OnOpenVPNDied(GPid pid, gint status, gpointer data);
134
Darin Petkovb536a742012-04-26 11:31:28 +0200135 // Inherit from VPNDriver to add custom properties.
136 virtual KeyValueStore GetProvider(Error *error);
137
Darin Petkov36a3ace2012-03-06 17:22:14 +0100138 // Implements RPCTaskDelegate.
Darin Petkov209e6292012-04-20 11:33:32 +0200139 virtual void GetLogin(std::string *user, std::string *password);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100140 virtual void Notify(const std::string &reason,
141 const std::map<std::string, std::string> &dict);
142
Darin Petkova9b1fed2012-02-29 11:49:05 +0100143 ControlInterface *control_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100144 EventDispatcher *dispatcher_;
145 Metrics *metrics_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800146 DeviceInfo *device_info_;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100147 GLib *glib_;
Darin Petkov46463022012-03-29 14:57:32 +0200148 Sockets sockets_;
149 scoped_ptr<OpenVPNManagementServer> management_server_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200150 NSS *nss_;
Darin Petkov79d74c92012-03-07 17:20:32 +0100151
152 VPNServiceRefPtr service_;
Darin Petkova9b1fed2012-02-29 11:49:05 +0100153 scoped_ptr<RPCTask> rpc_task_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800154 std::string tunnel_interface_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100155 VPNRefPtr device_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200156 FilePath tls_auth_file_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100157
Darin Petkov36a3ace2012-03-06 17:22:14 +0100158 // The PID of the spawned openvpn process. May be 0 if no process has been
159 // spawned yet or the process has died.
160 int pid_;
161
162 // Child exit watch callback source tag.
163 unsigned int child_watch_tag_;
164
Darin Petkov33af05c2012-02-28 10:10:30 +0100165 DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
166};
167
168} // namespace shill
169
170#endif // SHILL_OPENVPN_DRIVER_