Index: components/wifi/wifi_service_win.cc |
diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc |
index aeeed9c46150d64ee914adb40a00c544a0643095..e32aa31a329c8ffe6484186a24fef938a06ffb27 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; |