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