diff options
author | mef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-13 18:25:17 +0000 |
---|---|---|
committer | mef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-13 18:25:17 +0000 |
commit | e425d0367f95faebf357a0bd38e6e15750512ca1 (patch) | |
tree | 798b51ee7e6900a2585eb7bee4fa8fcb39b71475 | |
parent | 67675306efb33be9b362be04d6bf76ce8acff8c7 (diff) | |
download | chromium_src-e425d0367f95faebf357a0bd38e6e15750512ca1.zip chromium_src-e425d0367f95faebf357a0bd38e6e15750512ca1.tar.gz chromium_src-e425d0367f95faebf357a0bd38e6e15750512ca1.tar.bz2 |
Implement Networking Private API CreateNetwork function on Windows. Allows connection to hidden WiFi networks.
Defaults to TKIP encryption for WAPPSK and AES encryption for WAP2PSK. Exact encryption to use will have to be determined during Connect.
TBR=cpu@chromium.org for +third_party/libxml to DEPS.
BUG=267667
Review URL: https://codereview.chromium.org/105153002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240703 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | components/onc/onc_constants.cc | 1 | ||||
-rw-r--r-- | components/onc/onc_constants.h | 1 | ||||
-rw-r--r-- | components/wifi.gypi | 3 | ||||
-rw-r--r-- | components/wifi/DEPS | 1 | ||||
-rw-r--r-- | components/wifi/wifi_service.cc | 10 | ||||
-rw-r--r-- | components/wifi/wifi_service.h | 5 | ||||
-rw-r--r-- | components/wifi/wifi_service_win.cc | 161 | ||||
-rw-r--r-- | components/wifi/wifi_test.cc | 48 |
8 files changed, 210 insertions, 20 deletions
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc index 5b65f69..efd2b9d 100644 --- a/components/onc/onc_constants.cc +++ b/components/onc/onc_constants.cc @@ -140,6 +140,7 @@ const char kWEP_8021X[] = "WEP-8021X"; const char kWEP_PSK[] = "WEP-PSK"; const char kWPA_EAP[] = "WPA-EAP"; const char kWPA_PSK[] = "WPA-PSK"; +const char kWPA2_PSK[] = "WPA2-PSK"; } // namespace wifi namespace certificate { diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h index 21c6b5a..4ef51e7 100644 --- a/components/onc/onc_constants.h +++ b/components/onc/onc_constants.h @@ -162,6 +162,7 @@ ONC_EXPORT extern const char kSignalStrength[]; ONC_EXPORT extern const char kWEP_PSK[]; ONC_EXPORT extern const char kWEP_8021X[]; ONC_EXPORT extern const char kWPA_PSK[]; +ONC_EXPORT extern const char kWPA2_PSK[]; ONC_EXPORT extern const char kWPA_EAP[]; } // namespace wifi diff --git a/components/wifi.gypi b/components/wifi.gypi index 9685e11..4cfb12a 100644 --- a/components/wifi.gypi +++ b/components/wifi.gypi @@ -9,7 +9,8 @@ 'type': '<(component)', 'dependencies': [ '../base/base.gyp:base', - '../components/components.gyp:onc_component', + '../components/components.gyp:onc_component', + '../third_party/libxml/libxml.gyp:libxml', ], 'include_dirs': [ '..', diff --git a/components/wifi/DEPS b/components/wifi/DEPS index 273d26b..f88b423 100644 --- a/components/wifi/DEPS +++ b/components/wifi/DEPS @@ -1,3 +1,4 @@ include_rules = [ "+components/onc", + "+third_party/libxml", ] diff --git a/components/wifi/wifi_service.cc b/components/wifi/wifi_service.cc index 2218ba0..2ce8b47 100644 --- a/components/wifi/wifi_service.cc +++ b/components/wifi/wifi_service.cc @@ -72,12 +72,10 @@ bool WiFiService::NetworkProperties::UpdateFromValue( type = network_type; } if (value.GetDictionary(onc::network_type::kWiFi, &wifi)) { - std::string wifi_security; - if (wifi->GetString(onc::wifi::kSecurity, &wifi_security)) - security = wifi_security; - std::string wifi_ssid; - if (wifi->GetString(onc::wifi::kSSID, &wifi_ssid)) - ssid = wifi_ssid; + wifi->GetString(onc::wifi::kSecurity, &security); + wifi->GetString(onc::wifi::kSSID, &ssid); + wifi->GetString(onc::wifi::kPassphrase, &password); + wifi->GetBoolean(onc::wifi::kAutoConnect, &auto_connect); return true; } return false; diff --git a/components/wifi/wifi_service.h b/components/wifi/wifi_service.h index 9fc8411..6a288af 100644 --- a/components/wifi/wifi_service.h +++ b/components/wifi/wifi_service.h @@ -130,6 +130,10 @@ class WIFI_EXPORT WiFiService { std::string bssid; std::string type; std::string security; + // |password| field is used to pass wifi password for network creation via + // |CreateNetwork| or connection via |StartConnect|. It does not persist + // once operation is completed. + std::string password; // WiFi Signal Strength. 0..100 uint32 signal_strength; bool auto_connect; @@ -139,6 +143,7 @@ class WIFI_EXPORT WiFiService { std::string json_extra; // Extra JSON properties for unit tests scoped_ptr<base::DictionaryValue> ToValue(bool network_list) const; + // Updates only properties set in |value|. bool UpdateFromValue(const base::DictionaryValue& value); static std::string MacAddressAsString(const uint8 mac_as_int[6]); static bool OrderByType(const NetworkProperties& l, diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc index aeeed9c..e32aa31 100644 --- a/components/wifi/wifi_service_win.cc +++ b/components/wifi/wifi_service_win.cc @@ -21,6 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/registry.h" #include "components/onc/onc_constants.h" +#include "third_party/libxml/chromium/libxml_utils.h" namespace { const char kWiFiServiceError[] = "Error.WiFiService"; @@ -46,6 +47,7 @@ const char kWlanQueryInterface[] = "WlanQueryInterface"; const char kWlanRegisterNotification[] = "WlanRegisterNotification"; const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile"; const char kWlanScan[] = "WlanScan"; +const char kWlanSetProfile[] = "WlanSetProfile"; // WlanApi function definitions typedef DWORD (WINAPI* WlanConnectFunction)( @@ -136,6 +138,28 @@ typedef DWORD (WINAPI* WlanScanFunction)( CONST PWLAN_RAW_DATA pIeData, PVOID pReserved); +typedef DWORD (WINAPI* WlanSetProfileFunction)( + HANDLE hClientHandle, + const GUID *pInterfaceGuid, + DWORD dwFlags, + LPCWSTR strProfileXml, + LPCWSTR strAllUserProfileSecurity, + BOOL bOverwrite, + PVOID pReserved, + DWORD* pdwReasonCode); + +// Values for WLANProfile XML. +const char kAuthenticationOpen[] = "open"; +const char kAuthenticationWepPsk[] = "WEP"; +const char kAuthenticationWpaPsk[] = "WPAPSK"; +const char kAuthenticationWpa2Psk[] = "WPA2PSK"; +const char kEncryptionAES[] = "AES"; +const char kEncryptionNone[] = "none"; +const char kEncryptionTKIP[] = "TKIP"; +const char kEncryptionWEP[] = "WEP"; +const char kKeyTypeNetwork[] = "networkKey"; +const char kKeyTypePassphrase[] = "passPhrase"; + } // namespace namespace wifi { @@ -281,6 +305,12 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { // Deduce |onc::wifi| security from |alg|. std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const; + // Deduce WLANProfile |authEncryption| values from |onc::wifi| security. + bool AuthEncryptionFromSecurity(const std::string& security, + std::string* authentication, + std::string* encryption, + std::string* key_type) const; + // Populate |properties| based on |wlan| and its corresponding bss info from // |wlan_bss_list|. void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan, @@ -321,6 +351,10 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { // Normalizes |frequency_in_mhz| into one of |Frequency| values. Frequency GetNormalizedFrequency(int frequency_in_mhz) const; + // Create |profile_xml| based on |network_properties|. + bool CreateProfile(const NetworkProperties& network_properties, + std::string* profile_xml); + // Save temporary wireless profile for |network_guid|. DWORD SaveTempProfile(const std::string& network_guid); @@ -356,6 +390,7 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { WlanQueryInterfaceFunction WlanQueryInterface_function_; WlanRegisterNotificationFunction WlanRegisterNotification_function_; WlanScanFunction WlanScan_function_; + WlanSetProfileFunction WlanSetProfile_function_; // WlanSaveTemporaryProfile function may not be avaiable on Windows XP. WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_; @@ -402,6 +437,7 @@ WiFiServiceImpl::WiFiServiceImpl() WlanRegisterNotification_function_(NULL), WlanSaveTemporaryProfile_function_(NULL), WlanScan_function_(NULL), + WlanSetProfile_function_(NULL), client_(NULL), enable_notify_network_changed_(true) {} @@ -476,7 +512,41 @@ void WiFiServiceImpl::CreateNetwork( scoped_ptr<base::DictionaryValue> properties, std::string* network_guid, std::string* error) { - CheckError(ERROR_CALL_NOT_IMPLEMENTED, kWiFiServiceError, error); + DWORD error_code = EnsureInitialized(); + if (CheckError(error_code, kWiFiServiceError, error)) + return; + + WiFiService::NetworkProperties network_properties; + if (!network_properties.UpdateFromValue(*properties)) { + CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); + return; + } + + network_properties.guid = network_properties.ssid; + std::string profile_xml; + if (!CreateProfile(network_properties, &profile_xml)) { + CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); + return; + } + + string16 profile_xml16(UTF8ToUTF16(profile_xml)); + DWORD reason_code = 0u; + + error_code = WlanSetProfile_function_(client_, + &interface_guid_, + shared ? 0 : WLAN_PROFILE_USER, + profile_xml16.c_str(), + NULL, + FALSE, + NULL, + &reason_code); + if (CheckError(error_code, kWiFiServiceError, error)) { + DVLOG(0) << profile_xml; + DVLOG(0) << "SetProfile Reason Code:" << reason_code; + return; + } + + *network_guid = network_properties.guid; } void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type, @@ -751,6 +821,9 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { WlanScan_function_ = reinterpret_cast<WlanScanFunction>( ::GetProcAddress(wlan_api_library_, kWlanScan)); + WlanSetProfile_function_ = + reinterpret_cast<WlanSetProfileFunction>( + ::GetProcAddress(wlan_api_library_, kWlanSetProfile)); if (!WlanConnect_function_ || !WlanCloseHandle_function_ || @@ -762,7 +835,8 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { !WlanOpenHandle_function_ || !WlanQueryInterface_function_ || !WlanRegisterNotification_function_ || - !WlanScan_function_) { + !WlanScan_function_ || + !WlanSetProfile_function_) { DLOG(ERROR) << "Unable to find required WlanApi function."; FreeLibrary(wlan_api_library_); wlan_api_library_ = NULL; @@ -942,6 +1016,7 @@ DWORD WiFiServiceImpl::CloseClientHandle() { WlanRegisterNotification_function_ = NULL; WlanSaveTemporaryProfile_function_ = NULL; WlanScan_function_ = NULL; + WlanSetProfile_function_ = NULL; ::FreeLibrary(wlan_api_library_); wlan_api_library_ = NULL; } @@ -1401,6 +1476,88 @@ bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) { return GetProfile(network_guid, &profile_xml) == ERROR_SUCCESS; } +bool WiFiServiceImpl::AuthEncryptionFromSecurity( + const std::string& security, + std::string* authentication, + std::string* encryption, + std::string* key_type) const { + if (security == onc::wifi::kNone) { + *authentication = kAuthenticationOpen; + *encryption = kEncryptionNone; + } else if (security == onc::wifi::kWEP_PSK) { + *authentication = kAuthenticationOpen; + *encryption = kEncryptionWEP; + *key_type = kKeyTypeNetwork; + } else if (security == onc::wifi::kWPA_PSK) { + *authentication = kAuthenticationWpaPsk; + // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be + // determined and adjusted properly during |Connect|. + *encryption = kEncryptionAES; + *key_type = kKeyTypePassphrase; + } else if (security == onc::wifi::kWPA2_PSK) { + *authentication = kAuthenticationWpa2Psk; + // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be + // determined and adjusted properly during |Connect|. + *encryption = kEncryptionAES; + *key_type = kKeyTypePassphrase; + } else { + return false; + } + return true; +} + +bool WiFiServiceImpl::CreateProfile( + const NetworkProperties& network_properties, + std::string* profile_xml) { + // Get authentication and encryption values from security. + std::string authentication; + std::string encryption; + std::string key_type; + bool valid = AuthEncryptionFromSecurity(network_properties.security, + &authentication, + &encryption, + &key_type); + if (!valid) + return valid; + + // Generate profile XML. + XmlWriter xml_writer; + xml_writer.StartWriting(); + xml_writer.StartElement("WLANProfile"); + xml_writer.AddAttribute( + "xmlns", + "http://www.microsoft.com/networking/WLAN/profile/v1"); + xml_writer.WriteElement("name", network_properties.guid); + xml_writer.StartElement("SSIDConfig"); + xml_writer.StartElement("SSID"); + xml_writer.WriteElement("name", network_properties.ssid); + xml_writer.EndElement(); // Ends "SSID" element. + xml_writer.EndElement(); // Ends "SSIDConfig" element. + xml_writer.WriteElement("connectionType", "ESS"); + xml_writer.WriteElement("connectionMode", "manual"); + xml_writer.StartElement("MSM"); + xml_writer.StartElement("security"); + xml_writer.StartElement("authEncryption"); + xml_writer.WriteElement("authentication", authentication); + xml_writer.WriteElement("encryption", encryption); + xml_writer.WriteElement("useOneX", "false"); + xml_writer.EndElement(); // Ends "authEncryption" element. + if (!key_type.empty()) { + xml_writer.StartElement("sharedKey"); + xml_writer.WriteElement("keyType", key_type); + xml_writer.WriteElement("protected", "false"); + xml_writer.WriteElement("keyMaterial", network_properties.password); + xml_writer.EndElement(); // Ends "sharedKey" element. + } + xml_writer.EndElement(); // Ends "security" element. + xml_writer.EndElement(); // Ends "MSM" element. + xml_writer.EndElement(); // Ends "WLANProfile" element. + xml_writer.StopWriting(); + *profile_xml = xml_writer.GetWrittenString(); + + return true; +} + void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) { if (network_list_changed_observer_.is_null()) return; diff --git a/components/wifi/wifi_test.cc b/components/wifi/wifi_test.cc index eae084f..ff27b0d 100644 --- a/components/wifi/wifi_test.cc +++ b/components/wifi/wifi_test.cc @@ -67,10 +67,13 @@ WiFiTest::Result WiFiTest::Main(int argc, const char* argv[]) { VLOG(0) << "Usage: " << argv[0] << " [--list]" " [--get_properties]" + " [--create]" " [--connect]" " [--disconnect]" " [--network_guid=<network_guid>]" " [--frequency=0|2400|5000]" + " [--security=none|WEP-PSK|WPA-PSK|WPA2-PSK]" + " [--password=<wifi password>]" " [<network_guid>]\n"; return RESULT_WRONG_USAGE; } @@ -88,6 +91,10 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) { parsed_command_line.GetSwitchValueASCII("network_guid"); std::string frequency = parsed_command_line.GetSwitchValueASCII("frequency"); + std::string password = + parsed_command_line.GetSwitchValueASCII("password"); + std::string security = + parsed_command_line.GetSwitchValueASCII("security"); if (parsed_command_line.GetArgs().size() == 1) { #if defined(OS_WIN) @@ -127,26 +134,45 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) { } } - // Optional properties (frequency, password) to use for connect. - scoped_ptr<DictionaryValue> connect_properties(new DictionaryValue()); + // Optional properties (frequency, password) to use for connect or create. + scoped_ptr<DictionaryValue> properties(new DictionaryValue()); - if (parsed_command_line.HasSwitch("frequency")) { + if (!frequency.empty()) { int value = 0; - if (!network_guid.empty() && - !frequency.empty() && - base::StringToInt(frequency, &value)) { - connect_properties->SetInteger("WiFi.Frequency", value); + if (base::StringToInt(frequency, &value)) { + properties->SetInteger("WiFi.Frequency", value); // fall through to connect. } } + if (!password.empty()) + properties->SetString("WiFi.Passphrase", password); + + if (!security.empty()) + properties->SetString("WiFi.Security", security); + + if (parsed_command_line.HasSwitch("create")) { + if (!network_guid.empty()) { + std::string error; + std::string new_network_guid; + properties->SetString("WiFi.SSID", network_guid); + VLOG(0) << "Creating Network: " << *properties; + wifi_service->CreateNetwork(false, + properties.Pass(), + &new_network_guid, + &error); + VLOG(0) << error << ":\n" << new_network_guid; + return true; + } + } + if (parsed_command_line.HasSwitch("connect")) { - if (network_guid.length() > 0) { + if (!network_guid.empty()) { std::string error; - if (!connect_properties->empty()) { - VLOG(0) << "Using connect properties: " << *connect_properties; + if (!properties->empty()) { + VLOG(0) << "Using connect properties: " << *properties; wifi_service->SetProperties(network_guid, - connect_properties.Pass(), + properties.Pass(), &error); } wifi_service->StartConnect(network_guid, &error); |