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