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 #include "shill/vpn/vpn_driver.h"
18
19 #include <string>
20 #include <vector>
21
22 #include <base/strings/string_util.h>
23 #if defined(__ANDROID__)
24 #include <dbus/service_constants.h>
25 #else
26 #include <chromeos/dbus/service_constants.h>
27 #endif // __ANDROID__
28
29 #include "shill/connection.h"
30 #include "shill/event_dispatcher.h"
31 #include "shill/logging.h"
32 #include "shill/manager.h"
33 #include "shill/property_accessor.h"
34 #include "shill/property_store.h"
35 #include "shill/store_interface.h"
36
37 using std::string;
38 using std::vector;
39
40 namespace shill {
41
42 namespace Logging {
43 static auto kModuleLogScope = ScopeLogger::kVPN;
ObjectID(VPNDriver * v)44 static string ObjectID(VPNDriver* v) { return "(vpn_driver)"; }
45 }
46
47 // static
48 const int VPNDriver::kDefaultConnectTimeoutSeconds = 60;
49
VPNDriver(EventDispatcher * dispatcher,Manager * manager,const Property * properties,size_t property_count)50 VPNDriver::VPNDriver(EventDispatcher* dispatcher,
51 Manager* manager,
52 const Property* properties,
53 size_t property_count)
54 : weak_ptr_factory_(this),
55 dispatcher_(dispatcher),
56 manager_(manager),
57 properties_(properties),
58 property_count_(property_count),
59 connect_timeout_seconds_(0) {}
60
~VPNDriver()61 VPNDriver::~VPNDriver() {}
62
Load(StoreInterface * storage,const string & storage_id)63 bool VPNDriver::Load(StoreInterface* storage, const string& storage_id) {
64 SLOG(this, 2) << __func__;
65 for (size_t i = 0; i < property_count_; i++) {
66 if ((properties_[i].flags & Property::kEphemeral)) {
67 continue;
68 }
69 const string property = properties_[i].property;
70 if (properties_[i].flags & Property::kArray) {
71 CHECK(!(properties_[i].flags & Property::kCredential))
72 << "Property cannot be both an array and a credential";
73 vector<string> value;
74 if (storage->GetStringList(storage_id, property, &value)) {
75 args_.SetStrings(property, value);
76 } else {
77 args_.RemoveStrings(property);
78 }
79 } else {
80 string value;
81 bool loaded = (properties_[i].flags & Property::kCredential) ?
82 storage->GetCryptedString(storage_id, property, &value) :
83 storage->GetString(storage_id, property, &value);
84 if (loaded) {
85 args_.SetString(property, value);
86 } else {
87 args_.RemoveString(property);
88 }
89 }
90 }
91 return true;
92 }
93
Save(StoreInterface * storage,const string & storage_id,bool save_credentials)94 bool VPNDriver::Save(StoreInterface* storage,
95 const string& storage_id,
96 bool save_credentials) {
97 SLOG(this, 2) << __func__;
98 for (size_t i = 0; i < property_count_; i++) {
99 if ((properties_[i].flags & Property::kEphemeral)) {
100 continue;
101 }
102 bool credential = (properties_[i].flags & Property::kCredential);
103 const string property = properties_[i].property;
104 if (properties_[i].flags & Property::kArray) {
105 CHECK(!credential)
106 << "Property cannot be both an array and a credential";
107 if (!args_.ContainsStrings(property)) {
108 storage->DeleteKey(storage_id, property);
109 continue;
110 }
111 Strings value = args_.GetStrings(property);
112 storage->SetStringList(storage_id, property, value);
113 } else {
114 if (!args_.ContainsString(property) ||
115 (credential && !save_credentials)) {
116 storage->DeleteKey(storage_id, property);
117 continue;
118 }
119 string value = args_.GetString(property);
120 if (credential) {
121 storage->SetCryptedString(storage_id, property, value);
122 } else {
123 storage->SetString(storage_id, property, value);
124 }
125 }
126 }
127 return true;
128 }
129
UnloadCredentials()130 void VPNDriver::UnloadCredentials() {
131 SLOG(this, 2) << __func__;
132 for (size_t i = 0; i < property_count_; i++) {
133 if ((properties_[i].flags &
134 (Property::kEphemeral | Property::kCredential))) {
135 args_.RemoveString(properties_[i].property);
136 }
137 }
138 }
139
InitPropertyStore(PropertyStore * store)140 void VPNDriver::InitPropertyStore(PropertyStore* store) {
141 SLOG(this, 2) << __func__;
142 for (size_t i = 0; i < property_count_; i++) {
143 if (properties_[i].flags & Property::kArray) {
144 store->RegisterDerivedStrings(
145 properties_[i].property,
146 StringsAccessor(
147 new CustomMappedAccessor<VPNDriver, Strings, size_t>(
148 this,
149 &VPNDriver::ClearMappedStringsProperty,
150 &VPNDriver::GetMappedStringsProperty,
151 &VPNDriver::SetMappedStringsProperty,
152 i)));
153 } else {
154 store->RegisterDerivedString(
155 properties_[i].property,
156 StringAccessor(
157 new CustomMappedAccessor<VPNDriver, string, size_t>(
158 this,
159 &VPNDriver::ClearMappedStringProperty,
160 &VPNDriver::GetMappedStringProperty,
161 &VPNDriver::SetMappedStringProperty,
162 i)));
163 }
164 }
165
166 store->RegisterDerivedKeyValueStore(
167 kProviderProperty,
168 KeyValueStoreAccessor(
169 new CustomAccessor<VPNDriver, KeyValueStore>(
170 this, &VPNDriver::GetProvider, nullptr)));
171 }
172
ClearMappedStringProperty(const size_t & index,Error * error)173 void VPNDriver::ClearMappedStringProperty(const size_t& index, Error* error) {
174 CHECK(index < property_count_);
175 if (args_.ContainsString(properties_[index].property)) {
176 args_.RemoveString(properties_[index].property);
177 } else {
178 error->Populate(Error::kNotFound, "Property is not set");
179 }
180 }
181
ClearMappedStringsProperty(const size_t & index,Error * error)182 void VPNDriver::ClearMappedStringsProperty(const size_t& index, Error* error) {
183 CHECK(index < property_count_);
184 if (args_.ContainsStrings(properties_[index].property)) {
185 args_.RemoveStrings(properties_[index].property);
186 } else {
187 error->Populate(Error::kNotFound, "Property is not set");
188 }
189 }
190
GetMappedStringProperty(const size_t & index,Error * error)191 string VPNDriver::GetMappedStringProperty(const size_t& index, Error* error) {
192 // Provider properties are set via SetProperty calls to "Provider.XXX",
193 // however, they are retrieved via a GetProperty call, which returns all
194 // properties in a single "Provider" dict. Therefore, none of the individual
195 // properties in the kProperties are available for enumeration in
196 // GetProperties. Instead, they are retrieved via GetProvider below.
197 error->Populate(Error::kInvalidArguments,
198 "Provider properties are not read back in this manner");
199 return string();
200 }
201
GetMappedStringsProperty(const size_t & index,Error * error)202 Strings VPNDriver::GetMappedStringsProperty(const size_t& index, Error* error) {
203 // Provider properties are set via SetProperty calls to "Provider.XXX",
204 // however, they are retrieved via a GetProperty call, which returns all
205 // properties in a single "Provider" dict. Therefore, none of the individual
206 // properties in the kProperties are available for enumeration in
207 // GetProperties. Instead, they are retrieved via GetProvider below.
208 error->Populate(Error::kInvalidArguments,
209 "Provider properties are not read back in this manner");
210 return Strings();
211 }
212
SetMappedStringProperty(const size_t & index,const string & value,Error * error)213 bool VPNDriver::SetMappedStringProperty(
214 const size_t& index, const string& value, Error* error) {
215 CHECK(index < property_count_);
216 if (args_.ContainsString(properties_[index].property) &&
217 args_.GetString(properties_[index].property) == value) {
218 return false;
219 }
220 args_.SetString(properties_[index].property, value);
221 return true;
222 }
223
SetMappedStringsProperty(const size_t & index,const Strings & value,Error * error)224 bool VPNDriver::SetMappedStringsProperty(
225 const size_t& index, const Strings& value, Error* error) {
226 CHECK(index < property_count_);
227 if (args_.ContainsStrings(properties_[index].property) &&
228 args_.GetStrings(properties_[index].property) == value) {
229 return false;
230 }
231 args_.SetStrings(properties_[index].property, value);
232 return true;
233 }
234
GetProvider(Error * error)235 KeyValueStore VPNDriver::GetProvider(Error* error) {
236 SLOG(this, 2) << __func__;
237 string provider_prefix = string(kProviderProperty) + ".";
238 KeyValueStore provider_properties;
239
240 for (size_t i = 0; i < property_count_; i++) {
241 if ((properties_[i].flags & Property::kWriteOnly)) {
242 continue;
243 }
244 string prop = properties_[i].property;
245
246 // Chomp off leading "Provider." from properties that have this prefix.
247 string chopped_prop;
248 if (base::StartsWith(prop, provider_prefix,
249 base::CompareCase::INSENSITIVE_ASCII)) {
250 chopped_prop = prop.substr(provider_prefix.length());
251 } else {
252 chopped_prop = prop;
253 }
254
255 if (properties_[i].flags & Property::kArray) {
256 if (!args_.ContainsStrings(prop)) {
257 continue;
258 }
259 Strings value = args_.GetStrings(prop);
260 provider_properties.SetStrings(chopped_prop, value);
261 } else {
262 if (!args_.ContainsString(prop)) {
263 continue;
264 }
265 string value = args_.GetString(prop);
266 provider_properties.SetString(chopped_prop, value);
267 }
268 }
269
270 return provider_properties;
271 }
272
StartConnectTimeout(int timeout_seconds)273 void VPNDriver::StartConnectTimeout(int timeout_seconds) {
274 if (IsConnectTimeoutStarted()) {
275 return;
276 }
277 LOG(INFO) << "Schedule VPN connect timeout: "
278 << timeout_seconds << " seconds.";
279 connect_timeout_seconds_ = timeout_seconds;
280 connect_timeout_callback_.Reset(
281 Bind(&VPNDriver::OnConnectTimeout, weak_ptr_factory_.GetWeakPtr()));
282 dispatcher_->PostDelayedTask(
283 connect_timeout_callback_.callback(), timeout_seconds * 1000);
284 }
285
StopConnectTimeout()286 void VPNDriver::StopConnectTimeout() {
287 SLOG(this, 2) << __func__;
288 connect_timeout_callback_.Cancel();
289 connect_timeout_seconds_ = 0;
290 }
291
IsConnectTimeoutStarted() const292 bool VPNDriver::IsConnectTimeoutStarted() const {
293 return !connect_timeout_callback_.IsCancelled();
294 }
295
OnConnectTimeout()296 void VPNDriver::OnConnectTimeout() {
297 LOG(INFO) << "VPN connect timeout.";
298 StopConnectTimeout();
299 }
300
GetHost() const301 string VPNDriver::GetHost() const {
302 return args_.LookupString(kProviderHostProperty, "");
303 }
304
305 } // namespace shill
306