diff --git a/.gitignore b/.gitignore index 754a65b6..9f71bc0e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ Testing/ vcpkg_installed*/ /vcpkg/ /packaging/vcpkg/ports/netremote/portfile.cmake + +# Debug logs. +*-LogNetRemote*.txt diff --git a/src/common/wifi/core/CMakeLists.txt b/src/common/wifi/core/CMakeLists.txt index 8be3e84c..8a2fe498 100644 --- a/src/common/wifi/core/CMakeLists.txt +++ b/src/common/wifi/core/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(wifi-core AccessPointController.cxx AccessPointOperationStatus.cxx AccessPointOperationStatusLogOnExit.cxx + Ieee80211.cxx Ieee80211AccessPointCapabilities.cxx PUBLIC FILE_SET HEADERS diff --git a/src/common/wifi/core/Ieee80211.cxx b/src/common/wifi/core/Ieee80211.cxx new file mode 100644 index 00000000..d975c0b2 --- /dev/null +++ b/src/common/wifi/core/Ieee80211.cxx @@ -0,0 +1,14 @@ + +#include +#include + +#include + +namespace Microsoft::Net::Wifi +{ +std::string +Ieee80211MacAddressToString(const Ieee80211MacAddress& macAddress) +{ + return std::format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]); +} +} // namespace Microsoft::Net::Wifi diff --git a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx index 14df9a37..ef91ab8c 100644 --- a/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx +++ b/src/common/wifi/core/include/microsoft/net/wifi/Ieee80211.hxx @@ -414,6 +414,15 @@ static constexpr auto MacAddressNumOctets = 6; */ using Ieee80211MacAddress = std::array; +/** + * @brief Convert a MAC address to a string. + * + * @param macAddress The MAC address to convert. + * @return std::string + */ +std::string +Ieee80211MacAddressToString(const Ieee80211MacAddress& macAddress); + /** * @brief Information about a BSS. */ diff --git a/src/linux/wifi/core/AccessPointControllerLinux.cxx b/src/linux/wifi/core/AccessPointControllerLinux.cxx index cbb0549d..601e1f73 100644 --- a/src/linux/wifi/core/AccessPointControllerLinux.cxx +++ b/src/linux/wifi/core/AccessPointControllerLinux.cxx @@ -276,7 +276,32 @@ AccessPointControllerLinux::SetAuthenticationData([[maybe_unused]] Ieee80211Auth AccessPointOperationStatus status{ GetInterfaceName() }; const AccessPointOperationStatusLogOnExit logStatusOnExit(&status); - // TODO: implement this + // Ensure at least one set of authentication data is requested. + if (!authenticationData.Psk.has_value() && !authenticationData.Sae.has_value()) { + status.Code = AccessPointOperationStatusCode::InvalidParameter; + status.Details = "no authentication data specified"; + return status; + } + + if (authenticationData.Psk.has_value()) { + status.Code = AccessPointOperationStatusCode::OperationNotSupported; + status.Details = "PSK authentication data is not yet implemented"; + return status; + } + + if (authenticationData.Sae.has_value()) { + const auto& ieee80211AuthenticationDataSae = authenticationData.Sae.value(); + std::vector wpaSaePasswords(std::size(ieee80211AuthenticationDataSae.Passwords)); + std::ranges::transform(ieee80211AuthenticationDataSae.Passwords, std::begin(wpaSaePasswords), Ieee80211RsnaPasswordToWpaSaePassword); + + try { + m_hostapd.SetSaePasswords(std::move(wpaSaePasswords), EnforceConfigurationChange::Now); + } catch (const HostapdException& ex) { + status.Code = AccessPointOperationStatusCode::InternalError; + status.Details = std::format("failed to set SAE passwords - {}", ex.what()); + return status; + } + } status.Code = AccessPointOperationStatusCode::Succeeded; diff --git a/src/linux/wifi/core/Ieee80211WpaAdapters.cxx b/src/linux/wifi/core/Ieee80211WpaAdapters.cxx index fb910ad0..07a4bd4b 100644 --- a/src/linux/wifi/core/Ieee80211WpaAdapters.cxx +++ b/src/linux/wifi/core/Ieee80211WpaAdapters.cxx @@ -1,11 +1,14 @@ +#include #include #include #include +#include #include #include #include +#include #include #include "Ieee80211WpaAdapters.hxx" @@ -222,4 +225,27 @@ Ieee80211CipherSuitesToWpaCipherSuites(const std::unordered_map +Ieee80211SharedKeyToWpaCredential(const Ieee80211SharedKey& ieee80211SharedKey) noexcept +{ + return ieee80211SharedKey.Data; +} + +SaePassword +Ieee80211RsnaPasswordToWpaSaePassword(const Ieee80211RsnaPassword& ieee80211RsnaPassword) noexcept +{ + SaePassword wpaSaePassword{}; + + wpaSaePassword.Credential = Ieee80211SharedKeyToWpaCredential(ieee80211RsnaPassword.Credential); + if (ieee80211RsnaPassword.PasswordId.has_value()) { + wpaSaePassword.PasswordId = *ieee80211RsnaPassword.PasswordId; + } + if (ieee80211RsnaPassword.PeerMacAddress.has_value()) { + wpaSaePassword.PeerMacAddress = Ieee80211MacAddressToString(ieee80211RsnaPassword.PeerMacAddress.value()); + } + + return wpaSaePassword; +} + } // namespace Microsoft::Net::Wifi diff --git a/src/linux/wifi/core/Ieee80211WpaAdapters.hxx b/src/linux/wifi/core/Ieee80211WpaAdapters.hxx index 9f775f9a..68611598 100644 --- a/src/linux/wifi/core/Ieee80211WpaAdapters.hxx +++ b/src/linux/wifi/core/Ieee80211WpaAdapters.hxx @@ -2,12 +2,15 @@ #ifndef IEEE_80211_WPA_ADAPTERS_HXX #define IEEE_80211_WPA_ADAPTERS_HXX +#include #include #include #include +#include #include #include +#include namespace Microsoft::Net::Wifi { @@ -82,6 +85,24 @@ Ieee80211CipherSuiteToWpaCipher(Ieee80211CipherSuite ieee80211CipherSuite) noexc */ std::unordered_map> Ieee80211CipherSuitesToWpaCipherSuites(const std::unordered_map>& ieee80211CipherSuiteConfigurations) noexcept; + +/** + * @brief Convert a Ieee80211SharedKey to a wpa credential. + * + * @param ieee80211SharedKey The Ieee80211SharedKey to convert. + * @return std::vector + */ +std::vector +Ieee80211SharedKeyToWpaCredential(const Ieee80211SharedKey& ieee80211SharedKey) noexcept; + +/** + * @brief Convert a Ieee80211RsnaPassword to a WpaSaePassword. + * + * @param ieee80211RsnaPassword The Ieee80211RsnaPassword to convert. + * @return Wpa::SaePassword + */ +Wpa::SaePassword +Ieee80211RsnaPasswordToWpaSaePassword(const Ieee80211RsnaPassword& ieee80211RsnaPassword) noexcept; } // namespace Microsoft::Net::Wifi #endif // IEEE_80211_WPA_ADAPTERS_HXX diff --git a/tests/unit/TestNetRemoteServiceClient.cxx b/tests/unit/TestNetRemoteServiceClient.cxx index 81ed51b6..88361ebc 100644 --- a/tests/unit/TestNetRemoteServiceClient.cxx +++ b/tests/unit/TestNetRemoteServiceClient.cxx @@ -1,4 +1,7 @@ +#include +#include +#include #include #include #include @@ -19,6 +22,7 @@ #include #include #include +#include #include #include @@ -28,6 +32,10 @@ namespace Microsoft::Net::Remote::Test { constexpr auto AllPhyTypes = magic_enum::enum_values(); constexpr auto AllBands = magic_enum::enum_values(); + +constexpr auto PasswordIdValid{ "someid" }; +constexpr std::initializer_list AsciiPasswordData{ 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64 }; +constexpr std::array MacAddressDefault{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; } // namespace Microsoft::Net::Remote::Test using Microsoft::Net::Remote::Test::RemoteServiceAddressHttp; @@ -124,6 +132,11 @@ TEST_CASE("WifiAccessPointEnable API", "[basic][rpc][client][remote]") dot11CipherSuiteConfigurationWpa1.set_securityprotocol(Dot11SecurityProtocol::Dot11SecurityProtocolWpa); dot11CipherSuiteConfigurationWpa1.mutable_ciphersuites()->Add(Dot11CipherSuite::Dot11CipherSuiteCcmp256); + Dot11RsnaPassword dot11RsnaPassword{}; + *dot11RsnaPassword.mutable_credential()->mutable_data() = { std::cbegin(AsciiPasswordData), std::cend(AsciiPasswordData) }; + *dot11RsnaPassword.mutable_peermacaddress()->mutable_value() = { std::cbegin(MacAddressDefault), std::cend(MacAddressDefault) }; + dot11RsnaPassword.set_passwordid(PasswordIdValid); + Dot11AccessPointConfiguration apConfiguration{}; apConfiguration.set_phytype(Dot11PhyType::Dot11PhyTypeA); apConfiguration.mutable_ssid()->set_name(SsidName); @@ -131,6 +144,7 @@ TEST_CASE("WifiAccessPointEnable API", "[basic][rpc][client][remote]") apConfiguration.mutable_authenticationalgorithms()->Add(Dot11AuthenticationAlgorithm::Dot11AuthenticationAlgorithmSharedKey); apConfiguration.mutable_frequencybands()->Add(Dot11FrequencyBand::Dot11FrequencyBand2_4GHz); apConfiguration.mutable_frequencybands()->Add(Dot11FrequencyBand::Dot11FrequencyBand5_0GHz); + apConfiguration.mutable_authenticationdata()->mutable_sae()->mutable_passwords()->Add(std::move(dot11RsnaPassword)); WifiAccessPointEnableRequest request{}; request.set_accesspointid(InterfaceName1);