blob: ac974599c7da2719bb386b52ea1eb4af803d532a [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
Darin Petkov5a850472012-06-06 15:44:24 +020024namespace base {
25
26template<typename T>
27class WeakPtr;
28
29} // namespace base;
30
Darin Petkov33af05c2012-02-28 10:10:30 +010031namespace shill {
32
Darin Petkova9b1fed2012-02-29 11:49:05 +010033class ControlInterface;
Paul Stewartca6abd42012-03-01 15:45:29 -080034class DeviceInfo;
Darin Petkov33af05c2012-02-28 10:10:30 +010035class Error;
Darin Petkovf20994f2012-03-05 16:12:19 +010036class Metrics;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020037class NSS;
Darin Petkov46463022012-03-29 14:57:32 +020038class OpenVPNManagementServer;
Darin Petkov5a850472012-06-06 15:44:24 +020039class ProcessKiller;
Darin Petkov33af05c2012-02-28 10:10:30 +010040
Darin Petkov36a3ace2012-03-06 17:22:14 +010041class OpenVPNDriver : public VPNDriver,
42 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010043 public:
Paul Stewartca6abd42012-03-01 15:45:29 -080044 OpenVPNDriver(ControlInterface *control,
Darin Petkovf20994f2012-03-05 16:12:19 +010045 EventDispatcher *dispatcher,
46 Metrics *metrics,
47 Manager *manager,
Paul Stewartca6abd42012-03-01 15:45:29 -080048 DeviceInfo *device_info,
Paul Stewart451aa7f2012-04-11 19:07:58 -070049 GLib *glib);
Darin Petkov33af05c2012-02-28 10:10:30 +010050 virtual ~OpenVPNDriver();
51
Darin Petkovf20994f2012-03-05 16:12:19 +010052 // Inherited from VPNDriver. |Connect| initiates the VPN connection by
53 // creating a tunnel device. When the device index becomes available, this
54 // instance is notified through |ClaimInterface| and resumes the connection
55 // process by setting up and spawning an external 'openvpn' process. IP
56 // configuration settings are passed back from the external process through
57 // the |Notify| RPC service method.
Darin Petkov79d74c92012-03-07 17:20:32 +010058 virtual void Connect(const VPNServiceRefPtr &service, Error *error);
Paul Stewartca6abd42012-03-01 15:45:29 -080059 virtual bool ClaimInterface(const std::string &link_name,
60 int interface_index);
Darin Petkov6aa21872012-03-09 16:10:19 +010061 virtual void Disconnect();
Darin Petkov5eb05422012-05-11 15:45:25 +020062 virtual void OnConnectionDisconnected();
Darin Petkov602303f2012-06-06 12:15:59 +020063 virtual std::string GetProviderType() const;
Darin Petkov33af05c2012-02-28 10:10:30 +010064
Darin Petkov271fe522012-03-27 13:47:29 +020065 virtual void OnReconnecting();
66
Darin Petkov0440b9b2012-04-17 16:11:56 +020067 virtual void Cleanup(Service::ConnectState state);
68
Darin Petkov46463022012-03-29 14:57:32 +020069 // Returns true if an opton was appended.
70 bool AppendValueOption(const std::string &property,
71 const std::string &option,
72 std::vector<std::string> *options);
73
74 // Returns true if a flag was appended.
75 bool AppendFlag(const std::string &property,
76 const std::string &option,
77 std::vector<std::string> *options);
78
Darin Petkov33af05c2012-02-28 10:10:30 +010079 private:
Darin Petkovfe6a9372012-02-28 16:25:06 +010080 friend class OpenVPNDriverTest;
Paul Stewartca6abd42012-03-01 15:45:29 -080081 FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
Darin Petkov36a3ace2012-03-06 17:22:14 +010082 FRIEND_TEST(OpenVPNDriverTest, Cleanup);
Darin Petkovf20994f2012-03-05 16:12:19 +010083 FRIEND_TEST(OpenVPNDriverTest, Connect);
Darin Petkov79d74c92012-03-07 17:20:32 +010084 FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
Darin Petkov5a850472012-06-06 15:44:24 +020085 FRIEND_TEST(OpenVPNDriverTest, DeleteInterface);
Darin Petkov6aa21872012-03-09 16:10:19 +010086 FRIEND_TEST(OpenVPNDriverTest, Disconnect);
Darin Petkov60596742012-03-05 12:17:17 +010087 FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
Darin Petkovca8a0e62012-09-26 13:16:52 +020088 FRIEND_TEST(OpenVPNDriverTest, InitCAOptions);
Darin Petkov4e1b3f82012-09-27 13:22:37 +020089 FRIEND_TEST(OpenVPNDriverTest, InitClientAuthOptions);
Darin Petkov1a462de2012-05-02 11:10:48 +020090 FRIEND_TEST(OpenVPNDriverTest, InitEnvironment);
Darin Petkov55771b72012-04-25 09:25:19 +020091 FRIEND_TEST(OpenVPNDriverTest, InitLoggingOptions);
Darin Petkove0d5dd12012-04-04 16:10:48 +020092 FRIEND_TEST(OpenVPNDriverTest, InitManagementChannelOptions);
Darin Petkovfe6a9372012-02-28 16:25:06 +010093 FRIEND_TEST(OpenVPNDriverTest, InitOptions);
Darin Petkov4b944842012-09-21 10:48:48 +020094 FRIEND_TEST(OpenVPNDriverTest, InitOptionsHostWithPort);
Darin Petkovfe6a9372012-02-28 16:25:06 +010095 FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
Darin Petkove0d5dd12012-04-04 16:10:48 +020096 FRIEND_TEST(OpenVPNDriverTest, InitPKCS11Options);
Darin Petkov36a3ace2012-03-06 17:22:14 +010097 FRIEND_TEST(OpenVPNDriverTest, Notify);
Darin Petkov79d74c92012-03-07 17:20:32 +010098 FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
Darin Petkov5eb05422012-05-11 15:45:25 +020099 FRIEND_TEST(OpenVPNDriverTest, OnConnectionDisconnected);
Darin Petkova5e07ef2012-07-09 14:27:57 +0200100 FRIEND_TEST(OpenVPNDriverTest, OnDefaultServiceChanged);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100101 FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
Darin Petkov271fe522012-03-27 13:47:29 +0200102 FRIEND_TEST(OpenVPNDriverTest, OnReconnecting);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100103 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
104 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
105 FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
Darin Petkov1a462de2012-05-02 11:10:48 +0200106 FRIEND_TEST(OpenVPNDriverTest, ParseLSBRelease);
Darin Petkov60596742012-03-05 12:17:17 +0100107 FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
108 FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100109 FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
Darin Petkov4b944842012-09-21 10:48:48 +0200110 FRIEND_TEST(OpenVPNDriverTest, SplitPortFromHost);
Paul Stewart291a4732012-03-14 19:19:02 -0700111 FRIEND_TEST(OpenVPNDriverTest, VerifyPaths);
112
Darin Petkov4e1b3f82012-09-27 13:22:37 +0200113 static const char kOpenVPNCertProperty[];
114 static const char kOpenVPNKeyProperty[];
115
Darin Petkovc418b4b2012-10-05 11:42:52 +0200116 static const char kDefaultCACertificates[];
Darin Petkovca8a0e62012-09-26 13:16:52 +0200117
Paul Stewart291a4732012-03-14 19:19:02 -0700118 static const char kOpenVPNPath[];
119 static const char kOpenVPNScript[];
Paul Stewartebd38562012-03-23 13:06:40 -0700120 static const Property kProperties[];
Darin Petkov14c29ec2012-03-02 11:34:19 +0100121
Darin Petkov1a462de2012-05-02 11:10:48 +0200122 static const char kLSBReleaseFile[];
123 static const char kChromeOSReleaseName[];
124 static const char kChromeOSReleaseVersion[];
125
Darin Petkov14c29ec2012-03-02 11:34:19 +0100126 // The map is a sorted container that allows us to iterate through the options
127 // in order.
128 typedef std::map<int, std::string> ForeignOptions;
Darin Petkov60596742012-03-05 12:17:17 +0100129 typedef std::map<int, IPConfig::Route> RouteOptions;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100130
131 static void ParseIPConfiguration(
132 const std::map<std::string, std::string> &configuration,
133 IPConfig::Properties *properties);
134 static void ParseForeignOptions(const ForeignOptions &options,
135 IPConfig::Properties *properties);
136 static void ParseForeignOption(const std::string &option,
Darin Petkove8587e32012-07-02 13:56:07 +0200137 std::vector<std::string> *domain_search,
138 std::vector<std::string> *dns_servers);
Darin Petkov60596742012-03-05 12:17:17 +0100139 static IPConfig::Route *GetRouteOptionEntry(const std::string &prefix,
140 const std::string &key,
141 RouteOptions *routes);
142 static void ParseRouteOption(const std::string &key,
143 const std::string &value,
144 RouteOptions *routes);
145 static void SetRoutes(const RouteOptions &routes,
146 IPConfig::Properties *properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100147
Darin Petkov4b944842012-09-21 10:48:48 +0200148 // If |host| is in the "name:port" format, sets up |name| and |port|
149 // appropriately and returns true. Otherwise, returns false.
150 static bool SplitPortFromHost(const std::string &host,
151 std::string *name,
152 std::string *port);
153
Darin Petkovfe6a9372012-02-28 16:25:06 +0100154 void InitOptions(std::vector<std::string> *options, Error *error);
Darin Petkovca8a0e62012-09-26 13:16:52 +0200155 bool InitCAOptions(std::vector<std::string> *options, Error *error);
Darin Petkov4e1b3f82012-09-27 13:22:37 +0200156 void InitClientAuthOptions(std::vector<std::string> *options);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200157 void InitPKCS11Options(std::vector<std::string> *options);
158 bool InitManagementChannelOptions(
159 std::vector<std::string> *options, Error *error);
Darin Petkov55771b72012-04-25 09:25:19 +0200160 void InitLoggingOptions(std::vector<std::string> *options);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100161
Darin Petkov1a462de2012-05-02 11:10:48 +0200162 void InitEnvironment(std::vector<std::string> *environment);
163 bool ParseLSBRelease(std::map<std::string, std::string> *lsb_release);
164
Darin Petkov36a3ace2012-03-06 17:22:14 +0100165 bool SpawnOpenVPN();
Darin Petkov36a3ace2012-03-06 17:22:14 +0100166
167 // Called when the openpvn process exits.
168 static void OnOpenVPNDied(GPid pid, gint status, gpointer data);
169
Darin Petkov5a850472012-06-06 15:44:24 +0200170 // Standalone callback used to delete the tunnel interface when the openvpn
171 // process dies.
Darin Petkov5dbd2612012-06-07 16:22:16 +0200172 static void DeleteInterface(const base::WeakPtr<DeviceInfo> &device_info,
Darin Petkov5a850472012-06-06 15:44:24 +0200173 int interface_index);
174
Darin Petkovb536a742012-04-26 11:31:28 +0200175 // Inherit from VPNDriver to add custom properties.
176 virtual KeyValueStore GetProvider(Error *error);
177
Darin Petkov36a3ace2012-03-06 17:22:14 +0100178 // Implements RPCTaskDelegate.
Darin Petkov209e6292012-04-20 11:33:32 +0200179 virtual void GetLogin(std::string *user, std::string *password);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100180 virtual void Notify(const std::string &reason,
181 const std::map<std::string, std::string> &dict);
182
Darin Petkova5e07ef2012-07-09 14:27:57 +0200183 void OnDefaultServiceChanged(const ServiceRefPtr &service);
184
Darin Petkova9b1fed2012-02-29 11:49:05 +0100185 ControlInterface *control_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100186 Metrics *metrics_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800187 DeviceInfo *device_info_;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100188 GLib *glib_;
Darin Petkov46463022012-03-29 14:57:32 +0200189 Sockets sockets_;
190 scoped_ptr<OpenVPNManagementServer> management_server_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200191 NSS *nss_;
Darin Petkov5a850472012-06-06 15:44:24 +0200192 ProcessKiller *process_killer_;
Darin Petkov1a462de2012-05-02 11:10:48 +0200193 FilePath lsb_release_file_;
Darin Petkov79d74c92012-03-07 17:20:32 +0100194
195 VPNServiceRefPtr service_;
Darin Petkova9b1fed2012-02-29 11:49:05 +0100196 scoped_ptr<RPCTask> rpc_task_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800197 std::string tunnel_interface_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100198 VPNRefPtr device_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200199 FilePath tls_auth_file_;
Darin Petkov3189a472012-10-05 09:55:33 +0200200 IPConfig::Properties ip_properties_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100201
Darin Petkov36a3ace2012-03-06 17:22:14 +0100202 // The PID of the spawned openvpn process. May be 0 if no process has been
203 // spawned yet or the process has died.
204 int pid_;
205
206 // Child exit watch callback source tag.
207 unsigned int child_watch_tag_;
208
Darin Petkova5e07ef2012-07-09 14:27:57 +0200209 // Default service watch callback tag.
210 int default_service_callback_tag_;
211
Darin Petkov33af05c2012-02-28 10:10:30 +0100212 DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
213};
214
215} // namespace shill
216
217#endif // SHILL_OPENVPN_DRIVER_