summaryrefslogtreecommitdiffstats
path: root/components/wifi/wifi_service_win.cc
diff options
context:
space:
mode:
authormef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 16:49:04 +0000
committermef@chromium.org <mef@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 16:49:04 +0000
commite040109e2ede5f52ed4d780666ce176b16159158 (patch)
tree1d625bbff6e18fc93ec2aa8d0a0a7c25ed53a3c3 /components/wifi/wifi_service_win.cc
parent98d45ddad2e4f23c059e07771fc41a2894bc7b09 (diff)
downloadchromium_src-e040109e2ede5f52ed4d780666ce176b16159158.zip
chromium_src-e040109e2ede5f52ed4d780666ce176b16159158.tar.gz
chromium_src-e040109e2ede5f52ed4d780666ce176b16159158.tar.bz2
WiFiService StartConnect after CreateNetwork will try TKIP encryption if AES encryption fails to connect to newly created network.
BUG=328959 Review URL: https://codereview.chromium.org/197873012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/wifi/wifi_service_win.cc')
-rw-r--r--components/wifi/wifi_service_win.cc187
1 files changed, 160 insertions, 27 deletions
diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc
index 1280b49..8b69e1a 100644
--- a/components/wifi/wifi_service_win.cc
+++ b/components/wifi/wifi_service_win.cc
@@ -35,9 +35,14 @@ const wchar_t kNwCategoryWizardSavedRegValue[] = L"ShowSaved";
const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete";
const wchar_t kWlanApiDll[] = L"wlanapi.dll";
+// Created Profile Dictionary keys
+const char kProfileXmlKey[] = "xml";
+const char kProfileSharedKey[] = "shared";
+
// WlanApi function names
const char kWlanConnect[] = "WlanConnect";
const char kWlanCloseHandle[] = "WlanCloseHandle";
+const char kWlanDeleteProfile[] = "WlanDeleteProfile";
const char kWlanDisconnect[] = "WlanDisconnect";
const char kWlanEnumInterfaces[] = "WlanEnumInterfaces";
const char kWlanFreeMemory[] = "WlanFreeMemory";
@@ -62,6 +67,12 @@ typedef DWORD (WINAPI* WlanCloseHandleFunction)(
HANDLE hClientHandle,
PVOID pReserved);
+typedef DWORD (WINAPI* WlanDeleteProfileFunction)(
+ HANDLE hClientHandle,
+ const GUID *pInterfaceGuid,
+ LPCWSTR strProfileName,
+ PVOID pReserved);
+
typedef DWORD (WINAPI* WlanDisconnectFunction)(
HANDLE hClientHandle,
CONST GUID *pInterfaceGuid,
@@ -222,6 +233,13 @@ class WiFiServiceImpl : public WiFiService {
virtual void RequestConnectedNetworkUpdate() OVERRIDE {}
private:
+ typedef int32 EncryptionType;
+ enum EncryptionTypeEnum {
+ kEncryptionTypeAny = 0,
+ kEncryptionTypeAES = 1,
+ kEncryptionTypeTKIP = 2
+ };
+
// Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
// on WiFiServiceImpl passed back as |context|.
static void __stdcall OnWlanNotificationCallback(
@@ -313,8 +331,13 @@ class WiFiServiceImpl : public WiFiService {
// Deduce |onc::wifi| security from |alg|.
std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;
+ // Convert |EncryptionType| into WPA(2) encryption type string.
+ std::string WpaEncryptionFromEncryptionType(
+ EncryptionType encryption_type) const;
+
// Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
bool AuthEncryptionFromSecurity(const std::string& security,
+ EncryptionType encryption_type,
std::string* authentication,
std::string* encryption,
std::string* key_type) const;
@@ -358,8 +381,11 @@ class WiFiServiceImpl : public WiFiService {
// Normalizes |frequency_in_mhz| into one of |Frequency| values.
Frequency GetNormalizedFrequency(int frequency_in_mhz) const;
- // Create |profile_xml| based on |network_properties|.
+ // Create |profile_xml| based on |network_properties|. If |encryption_type|
+ // is |kEncryptionTypeAny| applies the type most suitable for parameters in
+ // |network_properties|.
bool CreateProfile(const NetworkProperties& network_properties,
+ EncryptionType encryption_type,
std::string* profile_xml);
// Save temporary wireless profile for |network_guid|.
@@ -372,9 +398,16 @@ class WiFiServiceImpl : public WiFiService {
bool get_plaintext_key,
std::string* profile_xml);
+ // Set |profile_xml| to current user or all users depending on |shared| flag.
+ // If |overwrite| is false, then returns an error if profile exists.
+ DWORD SetProfile(bool shared, const std::string& profile_xml, bool overwrite);
+
// Return true if there is previously stored profile xml for |network_guid|.
bool HaveProfile(const std::string& network_guid);
+ // Delete profile that was created, but failed to connect.
+ DWORD DeleteCreatedProfile(const std::string& network_guid);
+
// Notify |network_list_changed_observer_| that list of visible networks has
// changed to |networks|.
void NotifyNetworkListChanged(const NetworkList& networks);
@@ -390,6 +423,7 @@ class WiFiServiceImpl : public WiFiService {
// WlanApi function pointers
WlanConnectFunction WlanConnect_function_;
WlanCloseHandleFunction WlanCloseHandle_function_;
+ WlanDeleteProfileFunction WlanDeleteProfile_function_;
WlanDisconnectFunction WlanDisconnect_function_;
WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
WlanFreeMemoryFunction WlanFreeMemory_function_;
@@ -415,6 +449,11 @@ class WiFiServiceImpl : public WiFiService {
base::DictionaryValue connect_properties_;
// Preserved WLAN profile xml.
std::map<std::string, std::string> saved_profiles_xml_;
+ // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
+ // encryption type saved by |CreateNetwork| if applicable. Profile has to be
+ // deleted if connection fails. Implicitly created profiles have to be deleted
+ // if connection succeeds. Persist only in memory.
+ base::DictionaryValue created_profiles_;
// Observer to get notified when network(s) have changed (e.g. connect).
NetworkGuidListCallback networks_changed_observer_;
// Observer to get notified when network list has changed (scan complete).
@@ -438,6 +477,7 @@ WiFiServiceImpl::WiFiServiceImpl()
: wlan_api_library_(NULL),
WlanConnect_function_(NULL),
WlanCloseHandle_function_(NULL),
+ WlanDeleteProfile_function_(NULL),
WlanDisconnect_function_(NULL),
WlanEnumInterfaces_function_(NULL),
WlanFreeMemory_function_(NULL),
@@ -536,28 +576,36 @@ void WiFiServiceImpl::CreateNetwork(
network_properties.guid = network_properties.ssid;
std::string profile_xml;
- if (!CreateProfile(network_properties, &profile_xml)) {
+ if (!CreateProfile(network_properties, kEncryptionTypeAny, &profile_xml)) {
CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error);
return;
}
- base::string16 profile_xml16(base::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);
+ error_code = SetProfile(shared, profile_xml, false);
if (CheckError(error_code, kWiFiServiceError, error)) {
DVLOG(0) << profile_xml;
- DVLOG(0) << "SetProfile Reason Code:" << reason_code;
return;
}
+ // WAP and WAP2 networks could use either AES or TKIP encryption type.
+ // Preserve alternative profile to use in case if connection with default
+ // encryption type fails.
+ std::string tkip_profile_xml;
+ if (!CreateProfile(network_properties,
+ kEncryptionTypeTKIP,
+ &tkip_profile_xml)) {
+ CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error);
+ return;
+ }
+
+ if (tkip_profile_xml != profile_xml) {
+ scoped_ptr<base::DictionaryValue> tkip_profile(new base::DictionaryValue());
+ tkip_profile->SetString(kProfileXmlKey, tkip_profile_xml);
+ tkip_profile->SetBoolean(kProfileSharedKey, shared);
+ created_profiles_.SetWithoutPathExpansion(network_properties.guid,
+ tkip_profile.release());
+ }
+
*network_guid = network_properties.guid;
}
@@ -779,11 +827,49 @@ void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
int attempt) {
- // If network didn't get connected in |kMaxAttempts|, then restore automatic
- // network change notifications and stop waiting.
+ // If network didn't get connected in |kMaxAttempts|, then try to connect
+ // using different profile if it was created recently.
if (attempt > kMaxAttempts) {
- DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
- << network_guid;
+ LOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
+ << network_guid;
+
+ base::DictionaryValue* created_profile = NULL;
+ // Check, whether this connection is using newly created profile.
+ if (created_profiles_.GetDictionaryWithoutPathExpansion(
+ network_guid, &created_profile)) {
+ std::string tkip_profile_xml;
+ bool shared = false;
+ // Check, if this connection there is alternative TKIP profile xml that
+ // should be tried. If there is, then set it up and try to connect again.
+ if (created_profile->GetString(kProfileXmlKey, &tkip_profile_xml) &&
+ created_profile->GetBoolean(kProfileSharedKey, &shared)) {
+ // Remove TKIP profile xml, so it will not be tried again.
+ created_profile->Remove(kProfileXmlKey, NULL);
+ created_profile->Remove(kProfileSharedKey, NULL);
+ DWORD error_code = SetProfile(shared, tkip_profile_xml, true);
+ if (error_code == ERROR_SUCCESS) {
+ // Try to connect with new profile.
+ error_code = Connect(network_guid,
+ GetFrequencyToConnect(network_guid));
+ if (error_code == ERROR_SUCCESS) {
+ // Start waiting again.
+ WaitForNetworkConnect(network_guid, 0);
+ return;
+ } else {
+ LOG(ERROR) << "Failed to set created profile for " << network_guid
+ << " error=" << error_code;
+ }
+ }
+ } else {
+ // Connection has failed, so delete bad created profile.
+ DWORD error_code = DeleteCreatedProfile(network_guid);
+ if (error_code != ERROR_SUCCESS) {
+ LOG(ERROR) << "Failed to delete created profile for " << network_guid
+ << " error=" << error_code;
+ }
+ }
+ }
+ // Restore automatic network change notifications and stop waiting.
enable_notify_network_changed_ = true;
RestoreNwCategoryWizard();
return;
@@ -796,6 +882,8 @@ void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
// e.g. after Chromecast device reset. Reset DHCP on wireless network to
// work around this issue.
error = ResetDHCP();
+ // There is no need to keep created profile as network is connected.
+ created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
// Restore previously suppressed notifications.
enable_notify_network_changed_ = true;
RestoreNwCategoryWizard();
@@ -877,6 +965,9 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() {
WlanCloseHandle_function_ =
reinterpret_cast<WlanCloseHandleFunction>(
::GetProcAddress(wlan_api_library_, kWlanCloseHandle));
+ WlanDeleteProfile_function_ =
+ reinterpret_cast<WlanDeleteProfileFunction>(
+ ::GetProcAddress(wlan_api_library_, kWlanDeleteProfile));
WlanDisconnect_function_ =
reinterpret_cast<WlanDisconnectFunction>(
::GetProcAddress(wlan_api_library_, kWlanDisconnect));
@@ -916,6 +1007,7 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() {
if (!WlanConnect_function_ ||
!WlanCloseHandle_function_ ||
+ !WlanDeleteProfile_function_ ||
!WlanDisconnect_function_ ||
!WlanEnumInterfaces_function_ ||
!WlanFreeMemory_function_ ||
@@ -1088,6 +1180,7 @@ DWORD WiFiServiceImpl::CloseClientHandle() {
if (wlan_api_library_ != NULL) {
WlanConnect_function_ = NULL;
WlanCloseHandle_function_ = NULL;
+ WlanDeleteProfile_function_ = NULL;
WlanDisconnect_function_ = NULL;
WlanEnumInterfaces_function_ = NULL;
WlanFreeMemory_function_ = NULL;
@@ -1467,9 +1560,6 @@ DWORD WiFiServiceImpl::Connect(const std::string& network_guid,
error = WlanConnect_function_(
client_, &interface_guid_, &wlan_params, NULL);
} else {
- // TODO(mef): wlan_connection_mode_discovery_unsecure is not available on
- // XP. If XP support is needed, then temporary profile will have to be
- // created.
WLAN_CONNECTION_PARAMETERS wlan_params = {
wlan_connection_mode_discovery_unsecure,
NULL,
@@ -1552,14 +1642,59 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
return error;
}
+DWORD WiFiServiceImpl::SetProfile(bool shared,
+ const std::string& profile_xml,
+ bool overwrite) {
+ DWORD error_code = ERROR_SUCCESS;
+
+ base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml));
+ DWORD reason_code = 0u;
+
+ error_code = WlanSetProfile_function_(client_,
+ &interface_guid_,
+ shared ? 0 : WLAN_PROFILE_USER,
+ profile_xml16.c_str(),
+ NULL,
+ overwrite,
+ NULL,
+ &reason_code);
+ return error_code;
+}
+
bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
DWORD error = ERROR_SUCCESS;
std::string profile_xml;
return GetProfile(network_guid, false, &profile_xml) == ERROR_SUCCESS;
}
+
+DWORD WiFiServiceImpl::DeleteCreatedProfile(const std::string& network_guid) {
+ base::DictionaryValue* created_profile = NULL;
+ DWORD error_code = ERROR_SUCCESS;
+ // Check, whether this connection is using new created profile, and remove it.
+ if (created_profiles_.GetDictionaryWithoutPathExpansion(
+ network_guid, &created_profile)) {
+ // Connection has failed, so delete it.
+ base::string16 profile_name = ProfileNameFromGUID(network_guid);
+ error_code = WlanDeleteProfile_function_(client_,
+ &interface_guid_,
+ profile_name.c_str(),
+ NULL);
+ created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
+ }
+ return error_code;
+}
+
+std::string WiFiServiceImpl::WpaEncryptionFromEncryptionType(
+ EncryptionType encryption_type) const {
+ if (encryption_type == kEncryptionTypeTKIP)
+ return kEncryptionTKIP;
+ return kEncryptionAES;
+}
+
bool WiFiServiceImpl::AuthEncryptionFromSecurity(
const std::string& security,
+ EncryptionType encryption_type,
std::string* authentication,
std::string* encryption,
std::string* key_type) const {
@@ -1572,15 +1707,11 @@ bool WiFiServiceImpl::AuthEncryptionFromSecurity(
*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;
+ *encryption = WpaEncryptionFromEncryptionType(encryption_type);
*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;
+ *encryption = WpaEncryptionFromEncryptionType(encryption_type);
*key_type = kKeyTypePassphrase;
} else {
return false;
@@ -1590,12 +1721,14 @@ bool WiFiServiceImpl::AuthEncryptionFromSecurity(
bool WiFiServiceImpl::CreateProfile(
const NetworkProperties& network_properties,
+ EncryptionType encryption_type,
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,
+ encryption_type,
&authentication,
&encryption,
&key_type);