blob: e90ef20580a92a2529b492153e21449dcb5fa529 [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 Petkovfe6a9372012-02-28 16:25:06 +01007#include <base/logging.h>
8#include <chromeos/dbus/service_constants.h>
9
Paul Stewartca6abd42012-03-01 15:45:29 -080010#include "shill/device_info.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010011#include "shill/error.h"
Darin Petkova9b1fed2012-02-29 11:49:05 +010012#include "shill/rpc_task.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010013
Darin Petkovfe6a9372012-02-28 16:25:06 +010014using std::string;
15using std::vector;
16
Darin Petkov33af05c2012-02-28 10:10:30 +010017namespace shill {
18
Darin Petkova9b1fed2012-02-29 11:49:05 +010019namespace {
20const char kOpenVPNScript[] = "/usr/lib/flimflam/scripts/openvpn-script";
21} // namespace {}
22
23OpenVPNDriver::OpenVPNDriver(ControlInterface *control,
Paul Stewartca6abd42012-03-01 15:45:29 -080024 DeviceInfo *device_info,
Darin Petkova9b1fed2012-02-29 11:49:05 +010025 const KeyValueStore &args)
26 : control_(control),
Paul Stewartca6abd42012-03-01 15:45:29 -080027 device_info_(device_info),
28 args_(args),
29 interface_index_(-1) {}
Darin Petkov33af05c2012-02-28 10:10:30 +010030
31OpenVPNDriver::~OpenVPNDriver() {}
32
Paul Stewartca6abd42012-03-01 15:45:29 -080033bool OpenVPNDriver::ClaimInterface(const string &link_name,
34 int interface_index) {
35 if (link_name != tunnel_interface_) {
36 return false;
37 }
38
39 VLOG(2) << "Claiming " << link_name << " for OpenVPN tunnel";
40
41 // TODO(petkov): Could create a VPNDevice or DeviceStub here instead.
42 interface_index_ = interface_index;
43 return true;
44}
45
Darin Petkov33af05c2012-02-28 10:10:30 +010046void OpenVPNDriver::Connect(Error *error) {
Darin Petkova9b1fed2012-02-29 11:49:05 +010047 // TODO(petkov): Allocate rpc_task_.
Darin Petkov33af05c2012-02-28 10:10:30 +010048 error->Populate(Error::kNotSupported);
49}
50
Darin Petkovfe6a9372012-02-28 16:25:06 +010051void OpenVPNDriver::InitOptions(vector<string> *options, Error *error) {
52 string vpnhost;
53 if (args_.ContainsString(flimflam::kProviderHostProperty)) {
54 vpnhost = args_.GetString(flimflam::kProviderHostProperty);
55 }
56 if (vpnhost.empty()) {
57 Error::PopulateAndLog(
58 error, Error::kInvalidArguments, "VPN host not specified.");
59 return;
60 }
61 options->push_back("--client");
62 options->push_back("--tls-client");
63 options->push_back("--remote");
64 options->push_back(vpnhost);
65 options->push_back("--nobind");
66 options->push_back("--persist-key");
67 options->push_back("--persist-tun");
68
Paul Stewartca6abd42012-03-01 15:45:29 -080069 if (tunnel_interface_.empty() &&
70 !device_info_->CreateTunnelInterface(&tunnel_interface_)) {
71 Error::PopulateAndLog(
72 error, Error::kInternalError, "Could not create tunnel interface.");
73 return;
74 }
75
76 options->push_back("--dev");
77 options->push_back(tunnel_interface_);
Darin Petkovfe6a9372012-02-28 16:25:06 +010078 options->push_back("--dev-type");
79 options->push_back("tun");
80 options->push_back("--syslog");
81
82 // TODO(petkov): Enable verbosity based on shill logging options too.
83 AppendValueOption("OpenVPN.Verb", "--verb", options);
84
85 AppendValueOption("VPN.MTU", "--mtu", options);
86 AppendValueOption(flimflam::kOpenVPNProtoProperty, "--proto", options);
87 AppendValueOption(flimflam::kOpenVPNPortProperty, "--port", options);
88 AppendValueOption("OpenVPN.TLSAuth", "--tls-auth", options);
89
90 // TODO(petkov): Implement this.
91 LOG_IF(ERROR, args_.ContainsString(flimflam::kOpenVPNTLSAuthContentsProperty))
92 << "Support for --tls-auth not implemented yet.";
93
94 AppendValueOption(
95 flimflam::kOpenVPNTLSRemoteProperty, "--tls-remote", options);
96 AppendValueOption(flimflam::kOpenVPNCipherProperty, "--cipher", options);
97 AppendValueOption(flimflam::kOpenVPNAuthProperty, "--auth", options);
98 AppendFlag(flimflam::kOpenVPNAuthNoCacheProperty, "--auth-nocache", options);
99 AppendValueOption(
100 flimflam::kOpenVPNAuthRetryProperty, "--auth-retry", options);
101 AppendFlag(flimflam::kOpenVPNCompLZOProperty, "--comp-lzo", options);
102 AppendFlag(flimflam::kOpenVPNCompNoAdaptProperty, "--comp-noadapt", options);
103 AppendFlag(
104 flimflam::kOpenVPNPushPeerInfoProperty, "--push-peer-info", options);
105 AppendValueOption(flimflam::kOpenVPNRenegSecProperty, "--reneg-sec", options);
106 AppendValueOption(flimflam::kOpenVPNShaperProperty, "--shaper", options);
107 AppendValueOption(flimflam::kOpenVPNServerPollTimeoutProperty,
108 "--server-poll-timeout", options);
109
110 // TODO(petkov): Implement this.
111 LOG_IF(ERROR, args_.ContainsString(flimflam::kOpenVPNCaCertNSSProperty))
112 << "Support for NSS CA not implemented yet.";
113
114 // Client-side ping support.
115 AppendValueOption("OpenVPN.Ping", "--ping", options);
116 AppendValueOption("OpenVPN.PingExit", "--ping-exit", options);
117 AppendValueOption("OpenVPN.PingRestart", "--ping-restart", options);
118
119 AppendValueOption(flimflam::kOpenVPNCaCertProperty, "--ca", options);
120 AppendValueOption("OpenVPN.Cert", "--cert", options);
121 AppendValueOption(
122 flimflam::kOpenVPNNsCertTypeProperty, "--ns-cert-type", options);
123 AppendValueOption("OpenVPN.Key", "--key", options);
124
125 // TODO(petkov): Implement this.
126 LOG_IF(ERROR, args_.ContainsString(flimflam::kOpenVPNClientCertIdProperty))
127 << "Support for PKCS#11 (--pkcs11-id and --pkcs11-providers) "
128 << "not implemented yet.";
129
130 // TLS suport.
131 string remote_cert_tls;
132 if (args_.ContainsString(flimflam::kOpenVPNRemoteCertTLSProperty)) {
133 remote_cert_tls = args_.GetString(flimflam::kOpenVPNRemoteCertTLSProperty);
134 }
135 if (remote_cert_tls.empty()) {
136 remote_cert_tls = "server";
137 }
138 if (remote_cert_tls != "none") {
139 options->push_back("--remote-cert-tls");
140 options->push_back(remote_cert_tls);
141 }
142
143 // This is an undocumented command line argument that works like a .cfg file
144 // entry. TODO(sleffler): Maybe roll this into --tls-auth?
145 AppendValueOption(
146 flimflam::kOpenVPNKeyDirectionProperty, "--key-direction", options);
147 // TODO(sleffler): Support more than one eku parameter.
148 AppendValueOption(
149 flimflam::kOpenVPNRemoteCertEKUProperty, "--remote-cert-eku", options);
150 AppendValueOption(
151 flimflam::kOpenVPNRemoteCertKUProperty, "--remote-cert-ku", options);
152
153 // TODO(petkov): Setup management control channel and add the approprate
154 // options (crosbug.com/26994).
155
Darin Petkova9b1fed2012-02-29 11:49:05 +0100156 // Setup openvpn-script options and RPC information required to send back
157 // Layer 3 configuration.
158 options->push_back("--setenv");
159 options->push_back("CONNMAN_BUSNAME");
160 options->push_back(rpc_task_->GetRpcConnectionIdentifier());
161 options->push_back("--setenv");
162 options->push_back("CONNMAN_INTERFACE");
163 options->push_back(rpc_task_->GetRpcInterfaceIdentifier());
164 options->push_back("--setenv");
165 options->push_back("CONNMAN_PATH");
166 options->push_back(rpc_task_->GetRpcIdentifier());
167 options->push_back("--script-security");
168 options->push_back("2");
169 options->push_back("--up");
170 options->push_back(kOpenVPNScript);
171 options->push_back("--up-restart");
Darin Petkovfe6a9372012-02-28 16:25:06 +0100172
173 // Disable openvpn handling since we do route+ifconfig work.
174 options->push_back("--route-noexec");
175 options->push_back("--ifconfig-noexec");
176
177 // Drop root privileges on connection and enable callback scripts to send
178 // notify messages.
179 options->push_back("--user");
180 options->push_back("openvpn");
181 options->push_back("--group");
182 options->push_back("openvpn");
183}
184
185void OpenVPNDriver::AppendValueOption(
186 const string &property, const string &option, vector<string> *options) {
187 string value;
188 if (args_.ContainsString(property)) {
189 value = args_.GetString(property);
190 }
191 if (!value.empty()) {
192 options->push_back(option);
193 options->push_back(value);
194 }
195}
196
197void OpenVPNDriver::AppendFlag(
198 const string &property, const string &option, vector<string> *options) {
199 if (args_.ContainsString(property)) {
200 options->push_back(option);
201 }
202}
203
Darin Petkov33af05c2012-02-28 10:10:30 +0100204} // namespace shill