Commit c5527552 authored by mef@chromium.org's avatar mef@chromium.org

Add method GetKeyFromSystem to WiFiService on Windows and Mac.

BUG=328960

Review URL: https://codereview.chromium.org/156943002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251131 0039d316-1c4b-4281-b951-d872f2087c98
parent 29e871c3
...@@ -254,6 +254,12 @@ class FakeWiFiService : public WiFiService { ...@@ -254,6 +254,12 @@ class FakeWiFiService : public WiFiService {
} }
} }
virtual void GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) OVERRIDE {
*error = "not-found";
}
virtual void SetEventObservers( virtual void SetEventObservers(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy, scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const NetworkGuidListCallback& networks_changed_observer, const NetworkGuidListCallback& networks_changed_observer,
......
...@@ -100,6 +100,14 @@ class WIFI_EXPORT WiFiService { ...@@ -100,6 +100,14 @@ class WIFI_EXPORT WiFiService {
virtual void StartDisconnect(const std::string& network_guid, virtual void StartDisconnect(const std::string& network_guid,
std::string* error) = 0; std::string* error) = 0;
// Get WiFi Key for network identified by |network_guid| from the
// system (if it has one) and store it in |key_data|. User privilege elevation
// may be required, and function will fail if user privileges are not
// sufficient. Populates |error| on failure.
virtual void GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) = 0;
// Set observers to run when |NetworksChanged| and |NetworksListChanged| // Set observers to run when |NetworksChanged| and |NetworksListChanged|
// events needs to be sent. Notifications are posted on |message_loop_proxy|. // events needs to be sent. Notifications are posted on |message_loop_proxy|.
virtual void SetEventObservers( virtual void SetEventObservers(
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#import <SystemConfiguration/SystemConfiguration.h> #import <SystemConfiguration/SystemConfiguration.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
...@@ -97,6 +98,10 @@ class WiFiServiceMac : public WiFiService { ...@@ -97,6 +98,10 @@ class WiFiServiceMac : public WiFiService {
virtual void StartDisconnect(const std::string& network_guid, virtual void StartDisconnect(const std::string& network_guid,
std::string* error) OVERRIDE; std::string* error) OVERRIDE;
virtual void GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) OVERRIDE;
virtual void SetEventObservers( virtual void SetEventObservers(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy, scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const NetworkGuidListCallback& networks_changed_observer, const NetworkGuidListCallback& networks_changed_observer,
...@@ -367,6 +372,33 @@ void WiFiServiceMac::StartDisconnect(const std::string& network_guid, ...@@ -367,6 +372,33 @@ void WiFiServiceMac::StartDisconnect(const std::string& network_guid,
} }
} }
void WiFiServiceMac::GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) {
static const char kAirPortServiceName[] = "AirPort";
UInt32 password_length = 0;
void *password_data = NULL;
OSStatus status = SecKeychainFindGenericPassword(NULL,
strlen(kAirPortServiceName),
kAirPortServiceName,
network_guid.length(),
network_guid.c_str(),
&password_length,
&password_data,
NULL);
if (status != errSecSuccess) {
*error = kErrorNotFound;
return;
}
if (password_data) {
*key_data = std::string(reinterpret_cast<char*>(password_data),
password_length);
SecKeychainItemFreeContent(NULL, password_data);
}
}
void WiFiServiceMac::SetEventObservers( void WiFiServiceMac::SetEventObservers(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy, scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const NetworkGuidListCallback& networks_changed_observer, const NetworkGuidListCallback& networks_changed_observer,
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
namespace { namespace {
const char kWiFiServiceError[] = "Error.WiFiService"; const char kWiFiServiceError[] = "Error.WiFiService";
const char kWiFiServiceErrorNotImplemented[] =
"Error.WiFiService.NotImplemented";
const wchar_t kNwCategoryWizardRegKey[] = const wchar_t kNwCategoryWizardRegKey[] =
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\" L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\"
L"NwCategoryWizard"; L"NwCategoryWizard";
...@@ -208,6 +210,10 @@ class WiFiServiceImpl : public WiFiService { ...@@ -208,6 +210,10 @@ class WiFiServiceImpl : public WiFiService {
virtual void StartDisconnect(const std::string& network_guid, virtual void StartDisconnect(const std::string& network_guid,
std::string* error) OVERRIDE; std::string* error) OVERRIDE;
virtual void GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) OVERRIDE;
virtual void SetEventObservers( virtual void SetEventObservers(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy, scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const NetworkGuidListCallback& networks_changed_observer, const NetworkGuidListCallback& networks_changed_observer,
...@@ -360,7 +366,11 @@ class WiFiServiceImpl : public WiFiService { ...@@ -360,7 +366,11 @@ class WiFiServiceImpl : public WiFiService {
DWORD SaveTempProfile(const std::string& network_guid); DWORD SaveTempProfile(const std::string& network_guid);
// Get previously stored |profile_xml| for |network_guid|. // Get previously stored |profile_xml| for |network_guid|.
DWORD GetProfile(const std::string& network_guid, std::string* profile_xml); // If |get_plaintext_key| is true, and process has sufficient privileges, then
// <sharedKey> data in |profile_xml| will be unprotected.
DWORD GetProfile(const std::string& network_guid,
bool get_plaintext_key,
std::string* profile_xml);
// Return true if there is previously stored profile xml for |network_guid|. // Return true if there is previously stored profile xml for |network_guid|.
bool HaveProfile(const std::string& network_guid); bool HaveProfile(const std::string& network_guid);
...@@ -637,6 +647,58 @@ void WiFiServiceImpl::StartDisconnect(const std::string& network_guid, ...@@ -637,6 +647,58 @@ void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
CheckError(error_code, kWiFiServiceError, error); CheckError(error_code, kWiFiServiceError, error);
} }
void WiFiServiceImpl::GetKeyFromSystem(const std::string& network_guid,
std::string* key_data,
std::string* error) {
DWORD error_code = EnsureInitialized();
if (CheckError(error_code, kWiFiServiceError, error))
return;
std::string profile_xml;
error_code = GetProfile(network_guid, true, &profile_xml);
if (CheckError(error_code, kWiFiServiceError, error))
return;
const char kSharedKeyElement[] = "sharedKey";
const char kProtectedElement[] = "protected";
const char kKeyMaterialElement[] = "keyMaterial";
// Quick check to verify presence of <sharedKey> element.
if (profile_xml.find(kSharedKeyElement) == std::string::npos) {
*error = kWiFiServiceError;
return;
}
XmlReader reader;
if (reader.Load(profile_xml)) {
while (reader.Read()) {
reader.SkipToElement();
if (reader.NodeName() == kSharedKeyElement) {
while (reader.Read()) {
reader.SkipToElement();
if (reader.NodeName() == kKeyMaterialElement) {
reader.ReadElementContent(key_data);
} else if (reader.NodeName() == kProtectedElement) {
std::string protected_data;
reader.ReadElementContent(&protected_data);
// Without UAC privilege escalation call to |GetProfile| with
// |WLAN_PROFILE_GET_PLAINTEXT_KEY| flag returns success, but has
// protected keyMaterial. Report an error in this case.
if (protected_data != "false") {
*error = kWiFiServiceError;
break;
}
}
}
return;
}
}
}
// Did not find passphrase in the profile.
*error = kWiFiServiceError;
}
void WiFiServiceImpl::SetEventObservers( void WiFiServiceImpl::SetEventObservers(
scoped_refptr<base::MessageLoopProxy> message_loop_proxy, scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const NetworkGuidListCallback& networks_changed_observer, const NetworkGuidListCallback& networks_changed_observer,
...@@ -755,7 +817,7 @@ DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork( ...@@ -755,7 +817,7 @@ DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork(
if (error == ERROR_SUCCESS) { if (error == ERROR_SUCCESS) {
SaveTempProfile(*connected_network_guid); SaveTempProfile(*connected_network_guid);
std::string profile_xml; std::string profile_xml;
error = GetProfile(*connected_network_guid, &profile_xml); error = GetProfile(*connected_network_guid, false, &profile_xml);
if (error == ERROR_SUCCESS) { if (error == ERROR_SUCCESS) {
saved_profiles_xml_[*connected_network_guid] = profile_xml; saved_profiles_xml_[*connected_network_guid] = profile_xml;
} }
...@@ -1442,6 +1504,7 @@ DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) { ...@@ -1442,6 +1504,7 @@ DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) {
} }
DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid, DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
bool get_plaintext_key,
std::string* profile_xml) { std::string* profile_xml) {
if (client_ == NULL) { if (client_ == NULL) {
NOTREACHED(); NOTREACHED();
...@@ -1450,13 +1513,14 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid, ...@@ -1450,13 +1513,14 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
DWORD error = ERROR_SUCCESS; DWORD error = ERROR_SUCCESS;
base::string16 profile_name = ProfileNameFromGUID(network_guid); base::string16 profile_name = ProfileNameFromGUID(network_guid);
DWORD flags = get_plaintext_key ? WLAN_PROFILE_GET_PLAINTEXT_KEY : 0;
LPWSTR str_profile_xml = NULL; LPWSTR str_profile_xml = NULL;
error = WlanGetProfile_function_(client_, error = WlanGetProfile_function_(client_,
&interface_guid_, &interface_guid_,
profile_name.c_str(), profile_name.c_str(),
NULL, NULL,
&str_profile_xml, &str_profile_xml,
NULL, &flags,
NULL); NULL);
if (error == ERROR_SUCCESS && str_profile_xml != NULL) { if (error == ERROR_SUCCESS && str_profile_xml != NULL) {
...@@ -1473,7 +1537,7 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid, ...@@ -1473,7 +1537,7 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) { bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
DWORD error = ERROR_SUCCESS; DWORD error = ERROR_SUCCESS;
std::string profile_xml; std::string profile_xml;
return GetProfile(network_guid, &profile_xml) == ERROR_SUCCESS; return GetProfile(network_guid, false, &profile_xml) == ERROR_SUCCESS;
} }
bool WiFiServiceImpl::AuthEncryptionFromSecurity( bool WiFiServiceImpl::AuthEncryptionFromSecurity(
......
...@@ -66,6 +66,7 @@ WiFiTest::Result WiFiTest::Main(int argc, const char* argv[]) { ...@@ -66,6 +66,7 @@ WiFiTest::Result WiFiTest::Main(int argc, const char* argv[]) {
if (!ParseCommandLine(argc, argv)) { if (!ParseCommandLine(argc, argv)) {
VLOG(0) << "Usage: " << argv[0] << VLOG(0) << "Usage: " << argv[0] <<
" [--list]" " [--list]"
" [--get_key]"
" [--get_properties]" " [--get_properties]"
" [--create]" " [--create]"
" [--connect]" " [--connect]"
...@@ -190,6 +191,18 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) { ...@@ -190,6 +191,18 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) {
} }
} }
if (parsed_command_line.HasSwitch("get_key")) {
if (network_guid.length() > 0) {
std::string error;
std::string key_data;
wifi_service->GetKeyFromSystem(network_guid,
&key_data,
&error);
VLOG(0) << key_data << error;
return true;
}
}
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment