1 // Copyright (c) 2012 The Chromium 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 "chrome/browser/chromeos/options/vpn_config_view.h" 6 7 #include "ash/system/chromeos/network/network_connect.h" 8 #include "base/bind.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "chrome/browser/chromeos/enrollment_dialog_view.h" 13 #include "chrome/browser/chromeos/net/onc_utils.h" 14 #include "chrome/browser/profiles/profile_manager.h" 15 #include "chrome/common/net/x509_certificate_model.h" 16 #include "chrome/grit/generated_resources.h" 17 #include "chromeos/login/login_state.h" 18 #include "chromeos/network/network_configuration_handler.h" 19 #include "chromeos/network/network_event_log.h" 20 #include "chromeos/network/network_state.h" 21 #include "chromeos/network/network_state_handler.h" 22 #include "chromeos/network/network_ui_data.h" 23 #include "components/onc/onc_constants.h" 24 #include "third_party/cros_system_api/dbus/service_constants.h" 25 #include "ui/base/l10n/l10n_util.h" 26 #include "ui/base/models/combobox_model.h" 27 #include "ui/events/event.h" 28 #include "ui/views/controls/button/checkbox.h" 29 #include "ui/views/controls/combobox/combobox.h" 30 #include "ui/views/controls/label.h" 31 #include "ui/views/controls/textfield/textfield.h" 32 #include "ui/views/layout/grid_layout.h" 33 #include "ui/views/layout/layout_constants.h" 34 #include "ui/views/widget/widget.h" 35 #include "ui/views/window/dialog_client_view.h" 36 37 namespace { 38 39 enum ProviderTypeIndex { 40 PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK = 0, 41 PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT = 1, 42 PROVIDER_TYPE_INDEX_OPEN_VPN = 2, 43 PROVIDER_TYPE_INDEX_MAX = 3, 44 }; 45 46 base::string16 ProviderTypeIndexToString(int index) { 47 switch (index) { 48 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: 49 return l10n_util::GetStringUTF16( 50 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK); 51 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: 52 return l10n_util::GetStringUTF16( 53 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT); 54 case PROVIDER_TYPE_INDEX_OPEN_VPN: 55 return l10n_util::GetStringUTF16( 56 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN); 57 } 58 NOTREACHED(); 59 return base::string16(); 60 } 61 62 int ProviderTypeToIndex(const std::string& provider_type, 63 const std::string& client_cert_id) { 64 if (provider_type == shill::kProviderL2tpIpsec) { 65 if (!client_cert_id.empty()) 66 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; 67 else 68 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK; 69 } else { 70 DCHECK(provider_type == shill::kProviderOpenVpn); 71 return PROVIDER_TYPE_INDEX_OPEN_VPN; 72 } 73 } 74 75 // Translates the provider type to the name of the respective ONC dictionary 76 // containing configuration data for the type. 77 std::string ProviderTypeIndexToONCDictKey(int provider_type_index) { 78 switch (provider_type_index) { 79 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: 80 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: 81 return onc::vpn::kIPsec; 82 case PROVIDER_TYPE_INDEX_OPEN_VPN: 83 return onc::vpn::kOpenVPN; 84 } 85 NOTREACHED() << "Unhandled provider type index " << provider_type_index; 86 return std::string(); 87 } 88 89 std::string GetPemFromDictionary( 90 const base::DictionaryValue* provider_properties, 91 const std::string& key) { 92 const base::ListValue* pems = NULL; 93 if (!provider_properties->GetListWithoutPathExpansion(key, &pems)) 94 return std::string(); 95 std::string pem; 96 pems->GetString(0, &pem); 97 return pem; 98 } 99 100 } // namespace 101 102 namespace chromeos { 103 104 namespace internal { 105 106 class ProviderTypeComboboxModel : public ui::ComboboxModel { 107 public: 108 ProviderTypeComboboxModel(); 109 virtual ~ProviderTypeComboboxModel(); 110 111 // Overridden from ui::ComboboxModel: 112 virtual int GetItemCount() const OVERRIDE; 113 virtual base::string16 GetItemAt(int index) OVERRIDE; 114 115 private: 116 DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel); 117 }; 118 119 class VpnServerCACertComboboxModel : public ui::ComboboxModel { 120 public: 121 VpnServerCACertComboboxModel(); 122 virtual ~VpnServerCACertComboboxModel(); 123 124 // Overridden from ui::ComboboxModel: 125 virtual int GetItemCount() const OVERRIDE; 126 virtual base::string16 GetItemAt(int index) OVERRIDE; 127 128 private: 129 DISALLOW_COPY_AND_ASSIGN(VpnServerCACertComboboxModel); 130 }; 131 132 class VpnUserCertComboboxModel : public ui::ComboboxModel { 133 public: 134 VpnUserCertComboboxModel(); 135 virtual ~VpnUserCertComboboxModel(); 136 137 // Overridden from ui::ComboboxModel: 138 virtual int GetItemCount() const OVERRIDE; 139 virtual base::string16 GetItemAt(int index) OVERRIDE; 140 141 private: 142 DISALLOW_COPY_AND_ASSIGN(VpnUserCertComboboxModel); 143 }; 144 145 // ProviderTypeComboboxModel --------------------------------------------------- 146 147 ProviderTypeComboboxModel::ProviderTypeComboboxModel() { 148 } 149 150 ProviderTypeComboboxModel::~ProviderTypeComboboxModel() { 151 } 152 153 int ProviderTypeComboboxModel::GetItemCount() const { 154 return PROVIDER_TYPE_INDEX_MAX; 155 } 156 157 base::string16 ProviderTypeComboboxModel::GetItemAt(int index) { 158 return ProviderTypeIndexToString(index); 159 } 160 161 // VpnServerCACertComboboxModel ------------------------------------------------ 162 163 VpnServerCACertComboboxModel::VpnServerCACertComboboxModel() { 164 } 165 166 VpnServerCACertComboboxModel::~VpnServerCACertComboboxModel() { 167 } 168 169 int VpnServerCACertComboboxModel::GetItemCount() const { 170 if (CertLibrary::Get()->CertificatesLoading()) 171 return 1; // "Loading" 172 // "Default" + certs. 173 return CertLibrary::Get()->NumCertificates( 174 CertLibrary::CERT_TYPE_SERVER_CA) + 1; 175 } 176 177 base::string16 VpnServerCACertComboboxModel::GetItemAt(int index) { 178 if (CertLibrary::Get()->CertificatesLoading()) 179 return l10n_util::GetStringUTF16( 180 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING); 181 if (index == 0) 182 return l10n_util::GetStringUTF16( 183 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT); 184 int cert_index = index - 1; 185 return CertLibrary::Get()->GetCertDisplayStringAt( 186 CertLibrary::CERT_TYPE_SERVER_CA, cert_index); 187 } 188 189 // VpnUserCertComboboxModel ---------------------------------------------------- 190 191 VpnUserCertComboboxModel::VpnUserCertComboboxModel() { 192 } 193 194 VpnUserCertComboboxModel::~VpnUserCertComboboxModel() { 195 } 196 197 int VpnUserCertComboboxModel::GetItemCount() const { 198 if (CertLibrary::Get()->CertificatesLoading()) 199 return 1; // "Loading" 200 int num_certs = 201 CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER); 202 if (num_certs == 0) 203 return 1; // "None installed" 204 return num_certs; 205 } 206 207 base::string16 VpnUserCertComboboxModel::GetItemAt(int index) { 208 if (CertLibrary::Get()->CertificatesLoading()) { 209 return l10n_util::GetStringUTF16( 210 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING); 211 } 212 if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) == 0) { 213 return l10n_util::GetStringUTF16( 214 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED); 215 } 216 return CertLibrary::Get()->GetCertDisplayStringAt( 217 CertLibrary::CERT_TYPE_USER, index); 218 } 219 220 } // namespace internal 221 222 VPNConfigView::VPNConfigView(NetworkConfigView* parent, 223 const std::string& service_path) 224 : ChildNetworkConfigView(parent, service_path), 225 service_text_modified_(false), 226 enable_psk_passphrase_(false), 227 enable_user_cert_(false), 228 enable_server_ca_cert_(false), 229 enable_otp_(false), 230 enable_group_name_(false), 231 title_(0), 232 layout_(NULL), 233 server_textfield_(NULL), 234 service_text_(NULL), 235 service_textfield_(NULL), 236 provider_type_combobox_(NULL), 237 provider_type_text_label_(NULL), 238 psk_passphrase_label_(NULL), 239 psk_passphrase_textfield_(NULL), 240 user_cert_label_(NULL), 241 user_cert_combobox_(NULL), 242 server_ca_cert_label_(NULL), 243 server_ca_cert_combobox_(NULL), 244 username_textfield_(NULL), 245 user_passphrase_textfield_(NULL), 246 otp_label_(NULL), 247 otp_textfield_(NULL), 248 group_name_label_(NULL), 249 group_name_textfield_(NULL), 250 save_credentials_checkbox_(NULL), 251 error_label_(NULL), 252 provider_type_index_(PROVIDER_TYPE_INDEX_MAX), 253 weak_ptr_factory_(this) { 254 Init(); 255 } 256 257 VPNConfigView::~VPNConfigView() { 258 RemoveAllChildViews(true); // Destroy children before models 259 CertLibrary::Get()->RemoveObserver(this); 260 } 261 262 base::string16 VPNConfigView::GetTitle() const { 263 DCHECK_NE(title_, 0); 264 return l10n_util::GetStringUTF16(title_); 265 } 266 267 views::View* VPNConfigView::GetInitiallyFocusedView() { 268 if (service_path_.empty()) { 269 // Put focus in the first editable field. 270 if (server_textfield_) 271 return server_textfield_; 272 else if (service_textfield_) 273 return service_textfield_; 274 else if (provider_type_combobox_) 275 return provider_type_combobox_; 276 else if (psk_passphrase_textfield_ && psk_passphrase_textfield_->enabled()) 277 return psk_passphrase_textfield_; 278 else if (user_cert_combobox_ && user_cert_combobox_->enabled()) 279 return user_cert_combobox_; 280 else if (server_ca_cert_combobox_ && server_ca_cert_combobox_->enabled()) 281 return server_ca_cert_combobox_; 282 } 283 if (user_passphrase_textfield_) 284 return user_passphrase_textfield_; 285 else if (otp_textfield_) 286 return otp_textfield_; 287 return NULL; 288 } 289 290 bool VPNConfigView::CanLogin() { 291 // Username is always required. 292 if (GetUsername().empty()) 293 return false; 294 295 // TODO(stevenjb): min kMinPassphraseLen length? 296 if (service_path_.empty() && 297 (GetService().empty() || GetServer().empty())) 298 return false; 299 300 // Block login if certs are required but user has none. 301 bool cert_required = 302 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; 303 if (cert_required && (!HaveUserCerts() || !IsUserCertValid())) 304 return false; 305 306 return true; 307 } 308 309 void VPNConfigView::ContentsChanged(views::Textfield* sender, 310 const base::string16& new_contents) { 311 if (sender == server_textfield_ && !service_text_modified_) { 312 // Set the service name to the server name up to '.', unless it has 313 // been explicitly set by the user. 314 base::string16 server = server_textfield_->text(); 315 base::string16::size_type n = server.find_first_of(L'.'); 316 service_name_from_server_ = server.substr(0, n); 317 service_textfield_->SetText(service_name_from_server_); 318 } 319 if (sender == service_textfield_) { 320 if (new_contents.empty()) 321 service_text_modified_ = false; 322 else if (new_contents != service_name_from_server_) 323 service_text_modified_ = true; 324 } 325 UpdateCanLogin(); 326 } 327 328 bool VPNConfigView::HandleKeyEvent(views::Textfield* sender, 329 const ui::KeyEvent& key_event) { 330 if ((sender == psk_passphrase_textfield_ || 331 sender == user_passphrase_textfield_) && 332 key_event.key_code() == ui::VKEY_RETURN) { 333 parent_->GetDialogClientView()->AcceptWindow(); 334 } 335 return false; 336 } 337 338 void VPNConfigView::ButtonPressed(views::Button* sender, 339 const ui::Event& event) { 340 } 341 342 void VPNConfigView::OnPerformAction(views::Combobox* combobox) { 343 UpdateControls(); 344 UpdateErrorLabel(); 345 UpdateCanLogin(); 346 } 347 348 void VPNConfigView::OnCertificatesLoaded(bool initial_load) { 349 Refresh(); 350 } 351 352 bool VPNConfigView::Login() { 353 if (service_path_.empty()) { 354 base::DictionaryValue properties; 355 // Identifying properties 356 properties.SetStringWithoutPathExpansion( 357 shill::kTypeProperty, shill::kTypeVPN); 358 properties.SetStringWithoutPathExpansion( 359 shill::kNameProperty, GetService()); 360 properties.SetStringWithoutPathExpansion( 361 shill::kProviderHostProperty, GetServer()); 362 properties.SetStringWithoutPathExpansion( 363 shill::kProviderTypeProperty, GetProviderTypeString()); 364 365 SetConfigProperties(&properties); 366 bool shared = false; 367 bool modifiable = false; 368 ChildNetworkConfigView::GetShareStateForLoginState(&shared, &modifiable); 369 370 bool only_policy_autoconnect = 371 onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!shared); 372 if (only_policy_autoconnect) { 373 properties.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty, 374 false); 375 } 376 377 ash::network_connect::CreateConfigurationAndConnect(&properties, shared); 378 } else { 379 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> 380 GetNetworkState(service_path_); 381 if (!vpn) { 382 // Shill no longer knows about this network (edge case). 383 // TODO(stevenjb): Add notification for this. 384 NET_LOG_ERROR("Network not found", service_path_); 385 return true; // Close dialog 386 } 387 base::DictionaryValue properties; 388 SetConfigProperties(&properties); 389 ash::network_connect::ConfigureNetworkAndConnect( 390 service_path_, properties, false /* not shared */); 391 } 392 return true; // Close dialog. 393 } 394 395 void VPNConfigView::Cancel() { 396 } 397 398 void VPNConfigView::InitFocus() { 399 views::View* view_to_focus = GetInitiallyFocusedView(); 400 if (view_to_focus) 401 view_to_focus->RequestFocus(); 402 } 403 404 const std::string VPNConfigView::GetService() const { 405 if (service_textfield_ != NULL) 406 return GetTextFromField(service_textfield_, true); 407 return service_path_; 408 } 409 410 const std::string VPNConfigView::GetServer() const { 411 if (server_textfield_ != NULL) 412 return GetTextFromField(server_textfield_, true); 413 return std::string(); 414 } 415 416 const std::string VPNConfigView::GetPSKPassphrase() const { 417 if (psk_passphrase_textfield_ && 418 enable_psk_passphrase_ && 419 psk_passphrase_textfield_->visible()) 420 return GetPassphraseFromField(psk_passphrase_textfield_); 421 return std::string(); 422 } 423 424 const std::string VPNConfigView::GetUsername() const { 425 return GetTextFromField(username_textfield_, true); 426 } 427 428 const std::string VPNConfigView::GetUserPassphrase() const { 429 return GetPassphraseFromField(user_passphrase_textfield_); 430 } 431 432 const std::string VPNConfigView::GetGroupName() const { 433 return GetTextFromField(group_name_textfield_, false); 434 } 435 436 const std::string VPNConfigView::GetOTP() const { 437 return GetTextFromField(otp_textfield_, true); 438 } 439 440 const std::string VPNConfigView::GetServerCACertPEM() const { 441 int index = server_ca_cert_combobox_ ? 442 server_ca_cert_combobox_->selected_index() : 0; 443 if (index == 0) { 444 // First item is "Default". 445 return std::string(); 446 } else { 447 int cert_index = index - 1; 448 return CertLibrary::Get()->GetServerCACertPEMAt(cert_index); 449 } 450 } 451 452 void VPNConfigView::SetUserCertProperties( 453 chromeos::client_cert::ConfigType client_cert_type, 454 base::DictionaryValue* properties) const { 455 if (!HaveUserCerts()) { 456 // No certificate selected or not required. 457 chromeos::client_cert::SetEmptyShillProperties(client_cert_type, 458 properties); 459 } else { 460 // Certificates are listed in the order they appear in the model. 461 int index = user_cert_combobox_ ? user_cert_combobox_->selected_index() : 0; 462 int slot_id = -1; 463 const std::string pkcs11_id = 464 CertLibrary::Get()->GetUserCertPkcs11IdAt(index, &slot_id); 465 chromeos::client_cert::SetShillProperties( 466 client_cert_type, slot_id, pkcs11_id, properties); 467 } 468 } 469 470 bool VPNConfigView::GetSaveCredentials() const { 471 return save_credentials_checkbox_->checked(); 472 } 473 474 int VPNConfigView::GetProviderTypeIndex() const { 475 if (provider_type_combobox_) 476 return provider_type_combobox_->selected_index(); 477 return provider_type_index_; 478 } 479 480 std::string VPNConfigView::GetProviderTypeString() const { 481 int index = GetProviderTypeIndex(); 482 switch (index) { 483 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: 484 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: 485 return shill::kProviderL2tpIpsec; 486 case PROVIDER_TYPE_INDEX_OPEN_VPN: 487 return shill::kProviderOpenVpn; 488 } 489 NOTREACHED(); 490 return std::string(); 491 } 492 493 void VPNConfigView::Init() { 494 const NetworkState* vpn = NULL; 495 if (!service_path_.empty()) { 496 vpn = NetworkHandler::Get()->network_state_handler()-> 497 GetNetworkState(service_path_); 498 DCHECK(vpn && vpn->type() == shill::kTypeVPN); 499 } 500 layout_ = views::GridLayout::CreatePanel(this); 501 SetLayoutManager(layout_); 502 503 // Observer any changes to the certificate list. 504 CertLibrary::Get()->AddObserver(this); 505 506 views::ColumnSet* column_set = layout_->AddColumnSet(0); 507 // Label. 508 column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1, 509 views::GridLayout::USE_PREF, 0, 0); 510 column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); 511 // Textfield, combobox. 512 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, 513 views::GridLayout::USE_PREF, 0, 514 ChildNetworkConfigView::kInputFieldMinWidth); 515 column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); 516 // Policy indicator. 517 column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0, 518 views::GridLayout::USE_PREF, 0, 0); 519 520 // Initialize members. 521 service_text_modified_ = false; 522 title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN; 523 524 // By default enable all controls. 525 enable_psk_passphrase_ = true; 526 enable_user_cert_ = true; 527 enable_server_ca_cert_ = true; 528 enable_otp_ = true; 529 enable_group_name_ = true; 530 531 // Server label and input. 532 layout_->StartRow(0, 0); 533 views::View* server_label = 534 new views::Label(l10n_util::GetStringUTF16( 535 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME)); 536 layout_->AddView(server_label); 537 server_textfield_ = new views::Textfield(); 538 server_textfield_->set_controller(this); 539 layout_->AddView(server_textfield_); 540 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 541 if (!service_path_.empty()) { 542 server_label->SetEnabled(false); 543 server_textfield_->SetEnabled(false); 544 } 545 546 // Service label and name or input. 547 layout_->StartRow(0, 0); 548 layout_->AddView(new views::Label(l10n_util::GetStringUTF16( 549 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME))); 550 if (service_path_.empty()) { 551 service_textfield_ = new views::Textfield(); 552 service_textfield_->set_controller(this); 553 layout_->AddView(service_textfield_); 554 service_text_ = NULL; 555 } else { 556 service_text_ = new views::Label(); 557 service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 558 layout_->AddView(service_text_); 559 service_textfield_ = NULL; 560 } 561 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 562 563 // Provider type label and select. 564 layout_->StartRow(0, 0); 565 layout_->AddView(new views::Label(l10n_util::GetStringUTF16( 566 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE))); 567 if (service_path_.empty()) { 568 provider_type_combobox_model_.reset( 569 new internal::ProviderTypeComboboxModel); 570 provider_type_combobox_ = new views::Combobox( 571 provider_type_combobox_model_.get()); 572 provider_type_combobox_->set_listener(this); 573 layout_->AddView(provider_type_combobox_); 574 provider_type_text_label_ = NULL; 575 } else { 576 provider_type_text_label_ = new views::Label(); 577 provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 578 layout_->AddView(provider_type_text_label_); 579 provider_type_combobox_ = NULL; 580 } 581 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 582 583 // PSK passphrase label, input and visible button. 584 layout_->StartRow(0, 0); 585 psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16( 586 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE)); 587 layout_->AddView(psk_passphrase_label_); 588 psk_passphrase_textfield_ = new PassphraseTextfield(); 589 psk_passphrase_textfield_->set_controller(this); 590 layout_->AddView(psk_passphrase_textfield_); 591 layout_->AddView( 592 new ControlledSettingIndicatorView(psk_passphrase_ui_data_)); 593 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 594 595 // Server CA certificate 596 if (service_path_.empty()) { 597 layout_->StartRow(0, 0); 598 server_ca_cert_label_ = new views::Label(l10n_util::GetStringUTF16( 599 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA)); 600 layout_->AddView(server_ca_cert_label_); 601 server_ca_cert_combobox_model_.reset( 602 new internal::VpnServerCACertComboboxModel()); 603 server_ca_cert_combobox_ = new views::Combobox( 604 server_ca_cert_combobox_model_.get()); 605 layout_->AddView(server_ca_cert_combobox_); 606 layout_->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_)); 607 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 608 } else { 609 server_ca_cert_label_ = NULL; 610 server_ca_cert_combobox_ = NULL; 611 } 612 613 // User certificate label and input. 614 layout_->StartRow(0, 0); 615 user_cert_label_ = new views::Label(l10n_util::GetStringUTF16( 616 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT)); 617 layout_->AddView(user_cert_label_); 618 user_cert_combobox_model_.reset( 619 new internal::VpnUserCertComboboxModel()); 620 user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get()); 621 user_cert_combobox_->set_listener(this); 622 layout_->AddView(user_cert_combobox_); 623 layout_->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_)); 624 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 625 626 // Username label and input. 627 layout_->StartRow(0, 0); 628 layout_->AddView(new views::Label(l10n_util::GetStringUTF16( 629 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME))); 630 username_textfield_ = new views::Textfield(); 631 username_textfield_->set_controller(this); 632 username_textfield_->SetEnabled(username_ui_data_.IsEditable()); 633 layout_->AddView(username_textfield_); 634 layout_->AddView(new ControlledSettingIndicatorView(username_ui_data_)); 635 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 636 637 // User passphrase label, input and visble button. 638 layout_->StartRow(0, 0); 639 layout_->AddView(new views::Label(l10n_util::GetStringUTF16( 640 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE))); 641 user_passphrase_textfield_ = new PassphraseTextfield(); 642 user_passphrase_textfield_->set_controller(this); 643 user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable()); 644 layout_->AddView(user_passphrase_textfield_); 645 layout_->AddView( 646 new ControlledSettingIndicatorView(user_passphrase_ui_data_)); 647 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 648 649 // OTP label and input. 650 layout_->StartRow(0, 0); 651 otp_label_ = new views::Label(l10n_util::GetStringUTF16( 652 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP)); 653 layout_->AddView(otp_label_); 654 otp_textfield_ = new views::Textfield(); 655 otp_textfield_->set_controller(this); 656 layout_->AddView(otp_textfield_); 657 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 658 659 // Group Name label and input. 660 layout_->StartRow(0, 0); 661 group_name_label_ = new views::Label(l10n_util::GetStringUTF16( 662 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME)); 663 layout_->AddView(group_name_label_); 664 group_name_textfield_ = 665 new views::Textfield(); 666 group_name_textfield_->set_controller(this); 667 layout_->AddView(group_name_textfield_); 668 layout_->AddView(new ControlledSettingIndicatorView(group_name_ui_data_)); 669 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 670 671 // Save credentials 672 layout_->StartRow(0, 0); 673 save_credentials_checkbox_ = new views::Checkbox( 674 l10n_util::GetStringUTF16( 675 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS)); 676 save_credentials_checkbox_->SetEnabled( 677 save_credentials_ui_data_.IsEditable()); 678 layout_->SkipColumns(1); 679 layout_->AddView(save_credentials_checkbox_); 680 layout_->AddView( 681 new ControlledSettingIndicatorView(save_credentials_ui_data_)); 682 683 // Error label. 684 layout_->StartRow(0, 0); 685 layout_->SkipColumns(1); 686 error_label_ = new views::Label(); 687 error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 688 error_label_->SetEnabledColor(SK_ColorRED); 689 layout_->AddView(error_label_); 690 691 // Set or hide the UI, update comboboxes and error labels. 692 Refresh(); 693 694 if (vpn) { 695 NetworkHandler::Get()->network_configuration_handler()->GetProperties( 696 service_path_, 697 base::Bind(&VPNConfigView::InitFromProperties, 698 weak_ptr_factory_.GetWeakPtr()), 699 base::Bind(&VPNConfigView::GetPropertiesError, 700 weak_ptr_factory_.GetWeakPtr())); 701 } 702 } 703 704 void VPNConfigView::InitFromProperties( 705 const std::string& service_path, 706 const base::DictionaryValue& service_properties) { 707 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> 708 GetNetworkState(service_path); 709 if (!vpn) { 710 NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path); 711 return; 712 } 713 714 std::string provider_type, server_hostname, username, group_name; 715 bool psk_passphrase_required = false; 716 bool user_passphrase_required = true; 717 const base::DictionaryValue* provider_properties; 718 if (service_properties.GetDictionaryWithoutPathExpansion( 719 shill::kProviderProperty, &provider_properties)) { 720 provider_properties->GetStringWithoutPathExpansion( 721 shill::kTypeProperty, &provider_type); 722 provider_properties->GetStringWithoutPathExpansion( 723 shill::kHostProperty, &server_hostname); 724 if (provider_type == shill::kProviderL2tpIpsec) { 725 provider_properties->GetStringWithoutPathExpansion( 726 shill::kL2tpIpsecClientCertIdProperty, &client_cert_id_); 727 ca_cert_pem_ = GetPemFromDictionary( 728 provider_properties, shill::kL2tpIpsecCaCertPemProperty); 729 provider_properties->GetBooleanWithoutPathExpansion( 730 shill::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required); 731 provider_properties->GetStringWithoutPathExpansion( 732 shill::kL2tpIpsecUserProperty, &username); 733 provider_properties->GetStringWithoutPathExpansion( 734 shill::kL2tpIpsecTunnelGroupProperty, &group_name); 735 } else if (provider_type == shill::kProviderOpenVpn) { 736 provider_properties->GetStringWithoutPathExpansion( 737 shill::kOpenVPNClientCertIdProperty, &client_cert_id_); 738 ca_cert_pem_ = GetPemFromDictionary( 739 provider_properties, shill::kOpenVPNCaCertPemProperty); 740 provider_properties->GetStringWithoutPathExpansion( 741 shill::kOpenVPNUserProperty, &username); 742 provider_properties->GetBooleanWithoutPathExpansion( 743 shill::kPassphraseRequiredProperty, &user_passphrase_required); 744 } 745 } 746 bool save_credentials = false; 747 service_properties.GetBooleanWithoutPathExpansion( 748 shill::kSaveCredentialsProperty, &save_credentials); 749 750 provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_); 751 752 if (service_text_) 753 service_text_->SetText(base::ASCIIToUTF16(vpn->name())); 754 if (provider_type_text_label_) 755 provider_type_text_label_->SetText( 756 ProviderTypeIndexToString(provider_type_index_)); 757 758 if (server_textfield_ && !server_hostname.empty()) 759 server_textfield_->SetText(base::UTF8ToUTF16(server_hostname)); 760 if (username_textfield_ && !username.empty()) 761 username_textfield_->SetText(base::UTF8ToUTF16(username)); 762 if (group_name_textfield_ && !group_name.empty()) 763 group_name_textfield_->SetText(base::UTF8ToUTF16(group_name)); 764 if (psk_passphrase_textfield_) 765 psk_passphrase_textfield_->SetShowFake(!psk_passphrase_required); 766 if (user_passphrase_textfield_) 767 user_passphrase_textfield_->SetShowFake(!user_passphrase_required); 768 if (save_credentials_checkbox_) 769 save_credentials_checkbox_->SetChecked(save_credentials); 770 771 Refresh(); 772 UpdateCanLogin(); 773 } 774 775 void VPNConfigView::ParseUIProperties(const NetworkState* vpn) { 776 std::string type_dict_name = 777 ProviderTypeIndexToONCDictKey(provider_type_index_); 778 if (provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) { 779 ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kServerCARef, 780 &ca_cert_ui_data_); 781 ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kPSK, 782 &psk_passphrase_ui_data_); 783 ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kGroup, 784 &group_name_ui_data_); 785 } else if (provider_type_index_ == PROVIDER_TYPE_INDEX_OPEN_VPN) { 786 ParseVPNUIProperty(vpn, type_dict_name, ::onc::openvpn::kServerCARef, 787 &ca_cert_ui_data_); 788 } 789 ParseVPNUIProperty(vpn, type_dict_name, ::onc::client_cert::kClientCertRef, 790 &user_cert_ui_data_); 791 792 const std::string credentials_dict_name( 793 provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK ? 794 ::onc::vpn::kL2TP : type_dict_name); 795 ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kUsername, 796 &username_ui_data_); 797 ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kPassword, 798 &user_passphrase_ui_data_); 799 ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kSaveCredentials, 800 &save_credentials_ui_data_); 801 } 802 803 void VPNConfigView::GetPropertiesError( 804 const std::string& error_name, 805 scoped_ptr<base::DictionaryValue> error_data) { 806 NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, ""); 807 } 808 809 void VPNConfigView::SetConfigProperties( 810 base::DictionaryValue* properties) { 811 int provider_type_index = GetProviderTypeIndex(); 812 std::string user_passphrase = GetUserPassphrase(); 813 std::string user_name = GetUsername(); 814 std::string group_name = GetGroupName(); 815 switch (provider_type_index) { 816 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: { 817 std::string psk_passphrase = GetPSKPassphrase(); 818 if (!psk_passphrase.empty()) { 819 properties->SetStringWithoutPathExpansion( 820 shill::kL2tpIpsecPskProperty, GetPSKPassphrase()); 821 } 822 if (!group_name.empty()) { 823 properties->SetStringWithoutPathExpansion( 824 shill::kL2tpIpsecTunnelGroupProperty, group_name); 825 } 826 if (!user_name.empty()) { 827 properties->SetStringWithoutPathExpansion( 828 shill::kL2tpIpsecUserProperty, user_name); 829 } 830 if (!user_passphrase.empty()) { 831 properties->SetStringWithoutPathExpansion( 832 shill::kL2tpIpsecPasswordProperty, user_passphrase); 833 } 834 break; 835 } 836 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: { 837 if (server_ca_cert_combobox_) { 838 std::string ca_cert_pem = GetServerCACertPEM(); 839 base::ListValue* pem_list = new base::ListValue; 840 if (!ca_cert_pem.empty()) 841 pem_list->AppendString(ca_cert_pem); 842 properties->SetWithoutPathExpansion(shill::kL2tpIpsecCaCertPemProperty, 843 pem_list); 844 } 845 SetUserCertProperties(client_cert::CONFIG_TYPE_IPSEC, properties); 846 if (!group_name.empty()) { 847 properties->SetStringWithoutPathExpansion( 848 shill::kL2tpIpsecTunnelGroupProperty, GetGroupName()); 849 } 850 if (!user_name.empty()) { 851 properties->SetStringWithoutPathExpansion( 852 shill::kL2tpIpsecUserProperty, user_name); 853 } 854 if (!user_passphrase.empty()) { 855 properties->SetStringWithoutPathExpansion( 856 shill::kL2tpIpsecPasswordProperty, user_passphrase); 857 } 858 break; 859 } 860 case PROVIDER_TYPE_INDEX_OPEN_VPN: { 861 if (server_ca_cert_combobox_) { 862 std::string ca_cert_pem = GetServerCACertPEM(); 863 base::ListValue* pem_list = new base::ListValue; 864 if (!ca_cert_pem.empty()) 865 pem_list->AppendString(ca_cert_pem); 866 properties->SetWithoutPathExpansion(shill::kOpenVPNCaCertPemProperty, 867 pem_list); 868 } 869 SetUserCertProperties(client_cert::CONFIG_TYPE_OPENVPN, properties); 870 properties->SetStringWithoutPathExpansion( 871 shill::kOpenVPNUserProperty, GetUsername()); 872 if (!user_passphrase.empty()) { 873 properties->SetStringWithoutPathExpansion( 874 shill::kOpenVPNPasswordProperty, user_passphrase); 875 } 876 std::string otp = GetOTP(); 877 if (!otp.empty()) { 878 properties->SetStringWithoutPathExpansion( 879 shill::kOpenVPNOTPProperty, otp); 880 } 881 break; 882 } 883 case PROVIDER_TYPE_INDEX_MAX: 884 NOTREACHED(); 885 break; 886 } 887 properties->SetBooleanWithoutPathExpansion( 888 shill::kSaveCredentialsProperty, GetSaveCredentials()); 889 } 890 891 void VPNConfigView::Refresh() { 892 UpdateControls(); 893 894 // Set certificate combo boxes. 895 if (server_ca_cert_combobox_) { 896 server_ca_cert_combobox_->ModelChanged(); 897 if (enable_server_ca_cert_ && !ca_cert_pem_.empty()) { 898 // Select the current server CA certificate in the combobox. 899 int cert_index = 900 CertLibrary::Get()->GetServerCACertIndexByPEM(ca_cert_pem_); 901 if (cert_index >= 0) { 902 // Skip item for "Default" 903 server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index); 904 } else { 905 server_ca_cert_combobox_->SetSelectedIndex(0); 906 } 907 } else { 908 server_ca_cert_combobox_->SetSelectedIndex(0); 909 } 910 } 911 912 if (user_cert_combobox_) { 913 user_cert_combobox_->ModelChanged(); 914 if (enable_user_cert_ && !client_cert_id_.empty()) { 915 int cert_index = 916 CertLibrary::Get()->GetUserCertIndexByPkcs11Id(client_cert_id_); 917 if (cert_index >= 0) 918 user_cert_combobox_->SetSelectedIndex(cert_index); 919 else 920 user_cert_combobox_->SetSelectedIndex(0); 921 } else { 922 user_cert_combobox_->SetSelectedIndex(0); 923 } 924 } 925 926 UpdateErrorLabel(); 927 } 928 929 void VPNConfigView::UpdateControlsToEnable() { 930 enable_psk_passphrase_ = false; 931 enable_user_cert_ = false; 932 enable_server_ca_cert_ = false; 933 enable_otp_ = false; 934 enable_group_name_ = false; 935 int provider_type_index = GetProviderTypeIndex(); 936 if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) { 937 enable_psk_passphrase_ = true; 938 enable_group_name_ = true; 939 } else if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT) { 940 enable_server_ca_cert_ = true; 941 enable_user_cert_ = HaveUserCerts(); 942 enable_group_name_ = true; 943 } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default) 944 enable_server_ca_cert_ = true; 945 enable_user_cert_ = HaveUserCerts(); 946 enable_otp_ = true; 947 } 948 } 949 950 void VPNConfigView::UpdateControls() { 951 UpdateControlsToEnable(); 952 953 if (psk_passphrase_label_) 954 psk_passphrase_label_->SetEnabled(enable_psk_passphrase_); 955 if (psk_passphrase_textfield_) 956 psk_passphrase_textfield_->SetEnabled(enable_psk_passphrase_ && 957 psk_passphrase_ui_data_.IsEditable()); 958 959 if (user_cert_label_) 960 user_cert_label_->SetEnabled(enable_user_cert_); 961 if (user_cert_combobox_) 962 user_cert_combobox_->SetEnabled(enable_user_cert_ && 963 user_cert_ui_data_.IsEditable()); 964 965 if (server_ca_cert_label_) 966 server_ca_cert_label_->SetEnabled(enable_server_ca_cert_); 967 if (server_ca_cert_combobox_) 968 server_ca_cert_combobox_->SetEnabled(enable_server_ca_cert_ && 969 ca_cert_ui_data_.IsEditable()); 970 971 if (otp_label_) 972 otp_label_->SetEnabled(enable_otp_); 973 if (otp_textfield_) 974 otp_textfield_->SetEnabled(enable_otp_); 975 976 if (group_name_label_) 977 group_name_label_->SetEnabled(enable_group_name_); 978 if (group_name_textfield_) 979 group_name_textfield_->SetEnabled(enable_group_name_ && 980 group_name_ui_data_.IsEditable()); 981 } 982 983 void VPNConfigView::UpdateErrorLabel() { 984 // Error message. 985 base::string16 error_msg; 986 bool cert_required = 987 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT; 988 if (cert_required && CertLibrary::Get()->CertificatesLoaded()) { 989 if (!HaveUserCerts()) { 990 error_msg = l10n_util::GetStringUTF16( 991 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT); 992 } else if (!IsUserCertValid()) { 993 error_msg = l10n_util::GetStringUTF16( 994 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED); 995 } 996 } 997 if (error_msg.empty() && !service_path_.empty()) { 998 // TODO(kuan): differentiate between bad psk and user passphrases. 999 const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> 1000 GetNetworkState(service_path_); 1001 if (vpn && vpn->connection_state() == shill::kStateFailure) 1002 error_msg = ash::network_connect::ErrorString( 1003 vpn->last_error(), vpn->path()); 1004 } 1005 if (!error_msg.empty()) { 1006 error_label_->SetText(error_msg); 1007 error_label_->SetVisible(true); 1008 } else { 1009 error_label_->SetVisible(false); 1010 } 1011 } 1012 1013 void VPNConfigView::UpdateCanLogin() { 1014 parent_->GetDialogClientView()->UpdateDialogButtons(); 1015 } 1016 1017 bool VPNConfigView::HaveUserCerts() const { 1018 return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0; 1019 } 1020 1021 bool VPNConfigView::IsUserCertValid() const { 1022 if (!user_cert_combobox_ || !enable_user_cert_) 1023 return false; 1024 int index = user_cert_combobox_->selected_index(); 1025 if (index < 0) 1026 return false; 1027 // Currently only hardware-backed user certificates are valid. 1028 if (CertLibrary::Get()->IsHardwareBacked() && 1029 !CertLibrary::Get()->IsCertHardwareBackedAt( 1030 CertLibrary::CERT_TYPE_USER, index)) 1031 return false; 1032 return true; 1033 } 1034 1035 const std::string VPNConfigView::GetTextFromField(views::Textfield* textfield, 1036 bool trim_whitespace) const { 1037 if (!textfield) 1038 return std::string(); 1039 std::string untrimmed = base::UTF16ToUTF8(textfield->text()); 1040 if (!trim_whitespace) 1041 return untrimmed; 1042 std::string result; 1043 base::TrimWhitespaceASCII(untrimmed, base::TRIM_ALL, &result); 1044 return result; 1045 } 1046 1047 const std::string VPNConfigView::GetPassphraseFromField( 1048 PassphraseTextfield* textfield) const { 1049 if (!textfield) 1050 return std::string(); 1051 return textfield->GetPassphrase(); 1052 } 1053 1054 void VPNConfigView::ParseVPNUIProperty( 1055 const NetworkState* network, 1056 const std::string& dict_key, 1057 const std::string& key, 1058 NetworkPropertyUIData* property_ui_data) { 1059 ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE; 1060 const base::DictionaryValue* onc = 1061 onc::FindPolicyForActiveUser(network->guid(), &onc_source); 1062 1063 VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->guid(); 1064 property_ui_data->ParseOncProperty( 1065 onc_source, 1066 onc, 1067 base::StringPrintf("%s.%s.%s", 1068 ::onc::network_config::kVPN, 1069 dict_key.c_str(), 1070 key.c_str())); 1071 } 1072 1073 } // namespace chromeos 1074