1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef SHILL_VPN_OPENVPN_DRIVER_H_
18 #define SHILL_VPN_OPENVPN_DRIVER_H_
19 
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <base/files/file_path.h>
26 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
27 
28 #include "shill/ipconfig.h"
29 #include "shill/net/sockets.h"
30 #include "shill/refptr_types.h"
31 #include "shill/rpc_task.h"
32 #include "shill/service.h"
33 #include "shill/vpn/vpn_driver.h"
34 
35 namespace base {
36 
37 template<typename T>
38 class WeakPtr;
39 
40 }  // namespace base
41 
42 namespace shill {
43 
44 class CertificateFile;
45 class ControlInterface;
46 class DeviceInfo;
47 class Error;
48 class Metrics;
49 class OpenVPNManagementServer;
50 class ProcessManager;
51 
52 class OpenVPNDriver : public VPNDriver,
53                       public RPCTaskDelegate {
54  public:
55   enum ReconnectReason {
56     kReconnectReasonUnknown,
57     kReconnectReasonOffline,
58     kReconnectReasonTLSError,
59   };
60 
61   OpenVPNDriver(ControlInterface* control,
62                 EventDispatcher* dispatcher,
63                 Metrics* metrics,
64                 Manager* manager,
65                 DeviceInfo* device_info,
66                 ProcessManager* process_manager);
67   ~OpenVPNDriver() override;
68 
69   virtual void OnReconnecting(ReconnectReason reason);
70 
71   // Resets the VPN state and deallocates all resources. If there's a service
72   // associated through Connect, sets its state to Service::kStateIdle and
73   // disassociates from the service.
74   virtual void IdleService();
75 
76   // Resets the VPN state and deallocates all resources. If there's a service
77   // associated through Connect, sets its state to Service::kStateFailure, sets
78   // the failure reason to |failure|, sets its ErrorDetails property to
79   // |error_details|, and disassociates from the service.
80   virtual void FailService(Service::ConnectFailure failure,
81                            const std::string& error_details);
82 
83   // Append zero-valued, single-valued and double-valued options to the
84   // |options| array.
85   static void AppendOption(
86       const std::string& option,
87       std::vector<std::vector<std::string>>* options);
88   static void AppendOption(
89       const std::string& option,
90       const std::string& value,
91       std::vector<std::vector<std::string>>* options);
92   static void AppendOption(
93       const std::string& option,
94       const std::string& value0,
95       const std::string& value1,
96       std::vector<std::vector<std::string>>* options);
97 
98   // Returns true if an option was appended.
99   bool AppendValueOption(const std::string& property,
100                          const std::string& option,
101                          std::vector<std::vector<std::string>>* options);
102 
103   // If |property| exists, split its value up using |delimiter|.  Each element
104   // will be a separate argument to |option|. Returns true if the option was
105   // appended to |options|.
106   bool AppendDelimitedValueOption(
107       const std::string& property,
108       const std::string& option,
109       char delimiter,
110       std::vector<std::vector<std::string>>* options);
111 
112   // Returns true if a flag was appended.
113   bool AppendFlag(const std::string& property,
114                   const std::string& option,
115                   std::vector<std::vector<std::string>>* options);
116 
117   virtual std::string GetServiceRpcIdentifier() const;
118 
119  protected:
120   // Inherited from VPNDriver. |Connect| initiates the VPN connection by
121   // creating a tunnel device. When the device index becomes available, this
122   // instance is notified through |ClaimInterface| and resumes the connection
123   // process by setting up and spawning an external 'openvpn' process. IP
124   // configuration settings are passed back from the external process through
125   // the |Notify| RPC service method.
126   void Connect(const VPNServiceRefPtr& service, Error* error) override;
127   bool ClaimInterface(const std::string& link_name,
128                       int interface_index) override;
129   void Disconnect() override;
130   std::string GetProviderType() const override;
131   void OnConnectionDisconnected() override;
132   void OnConnectTimeout() override;
133 
134  private:
135   friend class OpenVPNDriverTest;
136   FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
137   FRIEND_TEST(OpenVPNDriverTest, Cleanup);
138   FRIEND_TEST(OpenVPNDriverTest, Connect);
139   FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
140   FRIEND_TEST(OpenVPNDriverTest, Disconnect);
141   FRIEND_TEST(OpenVPNDriverTest, GetEnvironment);
142   FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
143   FRIEND_TEST(OpenVPNDriverTest, InitCAOptions);
144   FRIEND_TEST(OpenVPNDriverTest, InitCertificateVerifyOptions);
145   FRIEND_TEST(OpenVPNDriverTest, InitClientAuthOptions);
146   FRIEND_TEST(OpenVPNDriverTest, InitExtraCertOptions);
147   FRIEND_TEST(OpenVPNDriverTest, InitLoggingOptions);
148   FRIEND_TEST(OpenVPNDriverTest, InitOptions);
149   FRIEND_TEST(OpenVPNDriverTest, InitOptionsHostWithPort);
150   FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
151   FRIEND_TEST(OpenVPNDriverTest, InitPKCS11Options);
152   FRIEND_TEST(OpenVPNDriverTest, Notify);
153   FRIEND_TEST(OpenVPNDriverTest, NotifyUMA);
154   FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
155   FRIEND_TEST(OpenVPNDriverTest, OnDefaultServiceChanged);
156   FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
157   FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNExited);
158   FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
159   FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
160   FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
161   FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
162   FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
163   FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
164   FRIEND_TEST(OpenVPNDriverTest, SplitPortFromHost);
165   FRIEND_TEST(OpenVPNDriverTest, WriteConfigFile);
166 
167   // The map is a sorted container that allows us to iterate through the options
168   // in order.
169   typedef std::map<int, std::string> ForeignOptions;
170   typedef std::map<int, IPConfig::Route> RouteOptions;
171 
172   static const char kDefaultCACertificates[];
173 
174   static const char kOpenVPNPath[];
175   static const char kOpenVPNScript[];
176   static const Property kProperties[];
177 
178   static const char kLSBReleaseFile[];
179 
180   static const char kDefaultOpenVPNConfigurationDirectory[];
181 
182   static const int kReconnectOfflineTimeoutSeconds;
183   static const int kReconnectTLSErrorTimeoutSeconds;
184 
185   static void ParseForeignOptions(const ForeignOptions& options,
186                                   IPConfig::Properties* properties);
187   static void ParseForeignOption(const std::string& option,
188                                  std::vector<std::string>* domain_search,
189                                  std::vector<std::string>* dns_servers);
190   static IPConfig::Route* GetRouteOptionEntry(const std::string& prefix,
191                                               const std::string& key,
192                                               RouteOptions* routes);
193   static void ParseRouteOption(const std::string& key,
194                                const std::string& value,
195                                RouteOptions* routes);
196   static void SetRoutes(const RouteOptions& routes,
197                         IPConfig::Properties* properties);
198 
199   // If |host| is in the "name:port" format, sets up |name| and |port|
200   // appropriately and returns true. Otherwise, returns false.
201   static bool SplitPortFromHost(const std::string& host,
202                                 std::string* name,
203                                 std::string* port);
204 
205   void InitOptions(
206       std::vector<std::vector<std::string>>* options, Error* error);
207   bool InitCAOptions(
208       std::vector<std::vector<std::string>>* options, Error* error);
209   void InitCertificateVerifyOptions(
210       std::vector<std::vector<std::string>>* options);
211   void InitClientAuthOptions(std::vector<std::vector<std::string>>* options);
212   bool InitExtraCertOptions(
213       std::vector<std::vector<std::string>>* options, Error* error);
214   void InitPKCS11Options(std::vector<std::vector<std::string>>* options);
215   bool InitManagementChannelOptions(
216       std::vector<std::vector<std::string>>* options, Error* error);
217   void InitLoggingOptions(std::vector<std::vector<std::string>>* options);
218 
219   std::map<std::string, std::string> GetEnvironment();
220   void ParseIPConfiguration(
221       const std::map<std::string, std::string>& configuration,
222       IPConfig::Properties* properties) const;
223 
224   bool SpawnOpenVPN();
225 
226   // Implements the public IdleService and FailService methods. Resets the VPN
227   // state and deallocates all resources. If there's a service associated
228   // through Connect, sets its state |state|; if |state| is
229   // Service::kStateFailure, sets the failure reason to |failure| and its
230   // ErrorDetails property to |error_details|; disassociates from the service.
231   void Cleanup(Service::ConnectState state,
232                Service::ConnectFailure failure,
233                const std::string& error_details);
234 
235   static int GetReconnectTimeoutSeconds(ReconnectReason reason);
236 
237   // Join a list of options into a single string.
238   static std::string JoinOptions(
239       const std::vector<std::vector<std::string>>& options, char separator);
240 
241   // Output an OpenVPN configuration.
242   bool WriteConfigFile(const std::vector<std::vector<std::string>>& options,
243                        base::FilePath* config_file);
244 
245   // Called when the openpvn process exits.
246   void OnOpenVPNDied(int exit_status);
247 
248   // Standalone callback used to delete the tunnel interface when the
249   // openvpn process exits as we clean up. ("Exiting" is expected
250   // termination during cleanup, while "dying" is any unexpected
251   // termination.)
252   static void OnOpenVPNExited(const base::WeakPtr<DeviceInfo>& device_info,
253                               int interface_index,
254                               int exit_status);
255 
256   // Inherit from VPNDriver to add custom properties.
257   KeyValueStore GetProvider(Error* error) override;
258 
259   // Implements RPCTaskDelegate.
260   void GetLogin(std::string* user, std::string* password) override;
261   void Notify(const std::string& reason,
262               const std::map<std::string, std::string>& dict) override;
263 
264   void OnDefaultServiceChanged(const ServiceRefPtr& service);
265 
266   void ReportConnectionMetrics();
267 
268   ControlInterface* control_;
269   Metrics* metrics_;
270   DeviceInfo* device_info_;
271   ProcessManager* process_manager_;
272   Sockets sockets_;
273   std::unique_ptr<OpenVPNManagementServer> management_server_;
274   std::unique_ptr<CertificateFile> certificate_file_;
275   std::unique_ptr<CertificateFile> extra_certificates_file_;
276   base::FilePath lsb_release_file_;
277 
278   VPNServiceRefPtr service_;
279   std::unique_ptr<RPCTask> rpc_task_;
280   std::string tunnel_interface_;
281   VirtualDeviceRefPtr device_;
282   base::FilePath tls_auth_file_;
283   base::FilePath openvpn_config_directory_;
284   base::FilePath openvpn_config_file_;
285   IPConfig::Properties ip_properties_;
286 
287   // The PID of the spawned openvpn process. May be 0 if no process has been
288   // spawned yet or the process has died.
289   int pid_;
290 
291   // Default service watch callback tag.
292   int default_service_callback_tag_;
293 
294   DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
295 };
296 
297 }  // namespace shill
298 
299 #endif  // SHILL_VPN_OPENVPN_DRIVER_H_
300