summaryrefslogtreecommitdiffstats
path: root/components/wifi/wifi_service_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/wifi/wifi_service_win.cc')
-rw-r--r--components/wifi/wifi_service_win.cc161
1 files changed, 159 insertions, 2 deletions
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;