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; 44 static string ObjectID(VPNDriver* v) { return "(vpn_driver)"; } 45 } 46 47 // static 48 const int VPNDriver::kDefaultConnectTimeoutSeconds = 60; 49 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 61 VPNDriver::~VPNDriver() {} 62 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 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 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 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 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 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 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 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 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 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 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 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 286 void VPNDriver::StopConnectTimeout() { 287 SLOG(this, 2) << __func__; 288 connect_timeout_callback_.Cancel(); 289 connect_timeout_seconds_ = 0; 290 } 291 292 bool VPNDriver::IsConnectTimeoutStarted() const { 293 return !connect_timeout_callback_.IsCancelled(); 294 } 295 296 void VPNDriver::OnConnectTimeout() { 297 LOG(INFO) << "VPN connect timeout."; 298 StopConnectTimeout(); 299 } 300 301 string VPNDriver::GetHost() const { 302 return args_.LookupString(kProviderHostProperty, ""); 303 } 304 305 } // namespace shill 306