blob: d5cedb56d2771e80f2096cc048fd9e413125da7d [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"
Darin Petkov14c29ec2012-03-02 11:34:19 +010017#include "shill/ipconfig.h"
Darin Petkovfe6a9372012-02-28 16:25:06 +010018#include "shill/key_value_store.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010019#include "shill/refptr_types.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010020#include "shill/rpc_task.h"
Darin Petkov3f9131c2012-03-20 11:37:32 +010021#include "shill/service.h"
Darin Petkov46463022012-03-29 14:57:32 +020022#include "shill/sockets.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010023#include "shill/vpn_driver.h"
24
25namespace shill {
26
Darin Petkova9b1fed2012-02-29 11:49:05 +010027class ControlInterface;
Paul Stewartca6abd42012-03-01 15:45:29 -080028class DeviceInfo;
Darin Petkov33af05c2012-02-28 10:10:30 +010029class Error;
Darin Petkovf20994f2012-03-05 16:12:19 +010030class EventDispatcher;
31class Manager;
32class Metrics;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +020033class NSS;
Darin Petkov46463022012-03-29 14:57:32 +020034class OpenVPNManagementServer;
Darin Petkov33af05c2012-02-28 10:10:30 +010035
Darin Petkov36a3ace2012-03-06 17:22:14 +010036class OpenVPNDriver : public VPNDriver,
37 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010038 public:
Paul Stewartca6abd42012-03-01 15:45:29 -080039 OpenVPNDriver(ControlInterface *control,
Darin Petkovf20994f2012-03-05 16:12:19 +010040 EventDispatcher *dispatcher,
41 Metrics *metrics,
42 Manager *manager,
Paul Stewartca6abd42012-03-01 15:45:29 -080043 DeviceInfo *device_info,
Darin Petkov36a3ace2012-03-06 17:22:14 +010044 GLib *glib,
Paul Stewartca6abd42012-03-01 15:45:29 -080045 const KeyValueStore &args);
Darin Petkov33af05c2012-02-28 10:10:30 +010046 virtual ~OpenVPNDriver();
47
Darin Petkovf20994f2012-03-05 16:12:19 +010048 // Inherited from VPNDriver. |Connect| initiates the VPN connection by
49 // creating a tunnel device. When the device index becomes available, this
50 // instance is notified through |ClaimInterface| and resumes the connection
51 // process by setting up and spawning an external 'openvpn' process. IP
52 // configuration settings are passed back from the external process through
53 // the |Notify| RPC service method.
Darin Petkov79d74c92012-03-07 17:20:32 +010054 virtual void Connect(const VPNServiceRefPtr &service, Error *error);
Paul Stewartca6abd42012-03-01 15:45:29 -080055 virtual bool ClaimInterface(const std::string &link_name,
56 int interface_index);
Darin Petkov6aa21872012-03-09 16:10:19 +010057 virtual void Disconnect();
Darin Petkov33af05c2012-02-28 10:10:30 +010058
Darin Petkovf3c71d72012-03-21 12:32:15 +010059 virtual bool Load(StoreInterface *storage, const std::string &storage_id);
60 virtual bool Save(StoreInterface *storage, const std::string &storage_id);
61
Darin Petkov271fe522012-03-27 13:47:29 +020062 virtual void OnReconnecting();
63
Paul Stewartebd38562012-03-23 13:06:40 -070064 virtual void InitPropertyStore(PropertyStore *store);
Paul Stewart39964fa2012-04-04 09:50:25 -070065
66 virtual std::string GetProviderType() const;
67
Paul Stewartebd38562012-03-23 13:06:40 -070068 void ClearMappedProperty(const size_t &index, Error *error);
69 std::string GetMappedProperty(const size_t &index, Error *error);
70 void SetMappedProperty(const size_t &index,
71 const std::string &value,
72 Error *error);
73
Darin Petkov683942b2012-03-27 18:00:04 +020074 KeyValueStore *args() { return &args_; }
75
Darin Petkov46463022012-03-29 14:57:32 +020076 // Returns true if an opton was appended.
77 bool AppendValueOption(const std::string &property,
78 const std::string &option,
79 std::vector<std::string> *options);
80
81 // Returns true if a flag was appended.
82 bool AppendFlag(const std::string &property,
83 const std::string &option,
84 std::vector<std::string> *options);
85
Darin Petkov33af05c2012-02-28 10:10:30 +010086 private:
Darin Petkovfe6a9372012-02-28 16:25:06 +010087 friend class OpenVPNDriverTest;
88 FRIEND_TEST(OpenVPNDriverTest, AppendFlag);
89 FRIEND_TEST(OpenVPNDriverTest, AppendValueOption);
Paul Stewartca6abd42012-03-01 15:45:29 -080090 FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
Darin Petkov36a3ace2012-03-06 17:22:14 +010091 FRIEND_TEST(OpenVPNDriverTest, Cleanup);
Darin Petkovf20994f2012-03-05 16:12:19 +010092 FRIEND_TEST(OpenVPNDriverTest, Connect);
Darin Petkov79d74c92012-03-07 17:20:32 +010093 FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
Darin Petkov6aa21872012-03-09 16:10:19 +010094 FRIEND_TEST(OpenVPNDriverTest, Disconnect);
Darin Petkov60596742012-03-05 12:17:17 +010095 FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
Darin Petkove0d5dd12012-04-04 16:10:48 +020096 FRIEND_TEST(OpenVPNDriverTest, InitManagementChannelOptions);
97 FRIEND_TEST(OpenVPNDriverTest, InitNSSOptions);
Darin Petkovfe6a9372012-02-28 16:25:06 +010098 FRIEND_TEST(OpenVPNDriverTest, InitOptions);
99 FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200100 FRIEND_TEST(OpenVPNDriverTest, InitPKCS11Options);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100101 FRIEND_TEST(OpenVPNDriverTest, Notify);
Darin Petkov79d74c92012-03-07 17:20:32 +0100102 FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100103 FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
Darin Petkov271fe522012-03-27 13:47:29 +0200104 FRIEND_TEST(OpenVPNDriverTest, OnReconnecting);
Darin Petkov14c29ec2012-03-02 11:34:19 +0100105 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
106 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
107 FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
Darin Petkov60596742012-03-05 12:17:17 +0100108 FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
Paul Stewartce4ec192012-03-14 12:53:46 -0700109 FRIEND_TEST(OpenVPNDriverTest, PinHostRoute);
Darin Petkov60596742012-03-05 12:17:17 +0100110 FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100111 FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
Paul Stewart291a4732012-03-14 19:19:02 -0700112 FRIEND_TEST(OpenVPNDriverTest, VerifyPaths);
113
Paul Stewartebd38562012-03-23 13:06:40 -0700114 struct Property {
115 const char *property;
116 bool crypted;
117 };
118
Paul Stewart291a4732012-03-14 19:19:02 -0700119 static const char kOpenVPNPath[];
120 static const char kOpenVPNScript[];
Paul Stewartebd38562012-03-23 13:06:40 -0700121 static const Property kProperties[];
Darin Petkov14c29ec2012-03-02 11:34:19 +0100122
123 // The map is a sorted container that allows us to iterate through the options
124 // in order.
125 typedef std::map<int, std::string> ForeignOptions;
Darin Petkov60596742012-03-05 12:17:17 +0100126 typedef std::map<int, IPConfig::Route> RouteOptions;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100127
128 static void ParseIPConfiguration(
129 const std::map<std::string, std::string> &configuration,
130 IPConfig::Properties *properties);
131 static void ParseForeignOptions(const ForeignOptions &options,
132 IPConfig::Properties *properties);
133 static void ParseForeignOption(const std::string &option,
134 IPConfig::Properties *properties);
Darin Petkov60596742012-03-05 12:17:17 +0100135 static IPConfig::Route *GetRouteOptionEntry(const std::string &prefix,
136 const std::string &key,
137 RouteOptions *routes);
138 static void ParseRouteOption(const std::string &key,
139 const std::string &value,
140 RouteOptions *routes);
141 static void SetRoutes(const RouteOptions &routes,
142 IPConfig::Properties *properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100143
144 void InitOptions(std::vector<std::string> *options, Error *error);
Darin Petkove0d5dd12012-04-04 16:10:48 +0200145 bool InitNSSOptions(std::vector<std::string> *options, Error *error);
146 void InitPKCS11Options(std::vector<std::string> *options);
147 bool InitManagementChannelOptions(
148 std::vector<std::string> *options, Error *error);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100149
Paul Stewartce4ec192012-03-14 12:53:46 -0700150 bool PinHostRoute(const IPConfig::Properties &properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100151
Darin Petkov36a3ace2012-03-06 17:22:14 +0100152 bool SpawnOpenVPN();
Darin Petkov3f9131c2012-03-20 11:37:32 +0100153 void Cleanup(Service::ConnectState state);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100154
155 // Called when the openpvn process exits.
156 static void OnOpenVPNDied(GPid pid, gint status, gpointer data);
157
158 // Implements RPCTaskDelegate.
159 virtual void Notify(const std::string &reason,
160 const std::map<std::string, std::string> &dict);
161
Darin Petkova9b1fed2012-02-29 11:49:05 +0100162 ControlInterface *control_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100163 EventDispatcher *dispatcher_;
164 Metrics *metrics_;
165 Manager *manager_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800166 DeviceInfo *device_info_;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100167 GLib *glib_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100168 KeyValueStore args_;
Darin Petkov46463022012-03-29 14:57:32 +0200169 Sockets sockets_;
170 scoped_ptr<OpenVPNManagementServer> management_server_;
Darin Petkov3c5e4dc2012-04-02 14:44:27 +0200171 NSS *nss_;
Darin Petkov79d74c92012-03-07 17:20:32 +0100172
173 VPNServiceRefPtr service_;
Darin Petkova9b1fed2012-02-29 11:49:05 +0100174 scoped_ptr<RPCTask> rpc_task_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800175 std::string tunnel_interface_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100176 VPNRefPtr device_;
Darin Petkov1fa81942012-04-02 11:38:08 +0200177 FilePath tls_auth_file_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100178
Darin Petkov36a3ace2012-03-06 17:22:14 +0100179 // The PID of the spawned openvpn process. May be 0 if no process has been
180 // spawned yet or the process has died.
181 int pid_;
182
183 // Child exit watch callback source tag.
184 unsigned int child_watch_tag_;
185
Darin Petkov33af05c2012-02-28 10:10:30 +0100186 DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
187};
188
189} // namespace shill
190
191#endif // SHILL_OPENVPN_DRIVER_