C++ - правильно реализовать WlanSetSecuritySettings для WlanHostedNetwork-функций
Как видно из названия, я не совсем уверен, как правильно реализовать функцию WlanSetSecuritySettings, чтобы получить полный доступ из системы для редактирования WlanHostedNetwork из родного wlanapi (- >, так как я получаю сообщение об ошибке в некоторых системах, которое говорит, что У меня нет доступа и что мне требуются возвышения!). В документе MSDN есть следующее руководство, как это сделать - я старался следовать ему, насколько это возможно:
Функция WlanHostedNetworkForceStart может завершиться ошибкой, если состояние размещенной сети равно wlan_hosted_network_unavailable или у вызывающей стороны недостаточно прав. Эта функция для принудительного запуска размещенной сети может быть вызвана только в том случае, если у пользователя есть соответствующие связанные привилегии. Разрешения хранятся в списке управления доступом по усмотрению (DACL), связанном с WLAN_SECURABLE_OBJECT. Чтобы вызвать WlanHostedNetworkForceStart, маркер клиентского доступа вызывающей стороны должен иметь повышенные привилегии, предоставляемые следующим перечислением в WLAN_SECURABLE_OBJECT: wlan_secure_hosted_network_elevated_access
и поэтому:
Успешный вызов функции WlanSetSecuritySettings переопределяет разрешения по умолчанию, связанные с объектом. Для получения дополнительной информации о разрешениях по умолчанию см. Разрешения API-интерфейса Wifi. Далее описывается процедура создания объекта дескриптора безопасности и его анализа в виде строки. Вызовите InitializeSecurityDescriptor, чтобы создать дескриптор безопасности в памяти. Вызовите SetSecurityDescriptorOwner, чтобы установить информацию о владельце для дескриптора безопасности. Вызовите InitializeAcl, чтобы создать дискреционный список контроля доступа (DACL) в памяти. Вызовите AddAccessAllowedAce или AddAccessDeniedAce, чтобы добавить записи управления доступом (ACE) в DACL. Задайте для параметра AccessMask одну из следующих побитовых комбинаций ИЛИ в зависимости от ситуации: WLAN_READ_ACCESS WLAN_READ_ACCESS | WLAN_EXECUTE_ACCESS WLAN_READ_ACCESS | WLAN_EXECUTE_ACCESS | WLAN_WRITE_ACCESS Вызовите SetSecurityDescriptorDacl, чтобы добавить DACL в дескриптор безопасности. Вызовите ConvertSecurityDescriptorToStringSecurityDescriptor, чтобы преобразовать дескриптор в строку. Строка, возвращаемая ConvertSecurityDescriptorToStringSecurityDescriptor, может затем использоваться в качестве значения параметра strModifiedSDDL при вызове WlanSetSecuritySettings.
Итак, это мой код в первую очередь (WifiClass является статическим классом и elevateAccess() тоже статическим) - я выполнил все шаги из руководства выше:
bool WifiClass::elevateAccess() {
PSECURITY_DESCRIPTOR securityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, sizeof(PACL));
PACL pAcl = (PACL)LocalAlloc(LMEM_FIXED, sizeof(PACL));
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
PSID pEveryoneSID = NULL;
bool bRet, bRes = true;
DWORD dRet;
bRet = InitializeSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION);
if (!bRet)
{
bRes = false;
}
bRet = IsValidSecurityDescriptor(securityDescriptor);
bRet = AllocateAndInitializeSid(&SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pEveryoneSID);
if (!bRet)
{
bRes = false;
}
bRet = IsValidSecurityDescriptor(securityDescriptor);
bRet = SetSecurityDescriptorOwner(securityDescriptor, pEveryoneSID, TRUE);
if (!bRet)
{
bRes = false;
}
bRet = IsValidSecurityDescriptor(securityDescriptor);
DWORD cbAcl = sizeof(ACL) +
(sizeof(ACCESS_ALLOWED_ACE)) + (GetLengthSid(securityDescriptor) - sizeof(DWORD));
bRet = InitializeAcl(pAcl, cbAcl, ACL_REVISION);
if (!bRet)
{
bRes = false;
}
bRet = IsValidAcl(pAcl);
bRet = AddAccessAllowedAce(pAcl, ACL_REVISION, WLAN_READ_ACCESS | WLAN_EXECUTE_ACCESS | WLAN_WRITE_ACCESS, securityDescriptor);
if (!bRet)
{
bRes = false;
}
bRet = IsValidSecurityDescriptor(securityDescriptor);
bRet = SetSecurityDescriptorDacl(securityDescriptor, TRUE, NULL, FALSE);
if (!bRet)
{
bRes = false;
}
bRet = IsValidSecurityDescriptor(securityDescriptor);
LPWSTR* pStringSecurityDescriptor = new LPWSTR;
bRet = ConvertSecurityDescriptorToStringSecurityDescriptor(securityDescriptor,
SDDL_REVISION_1,
DACL_SECURITY_INFORMATION,
pStringSecurityDescriptor,
NULL
);
if (!bRet)
{
bRes = false;
}
WLAN_SECURABLE_OBJECT wso = wlan_secure_hosted_network_elevated_access;
dRet = WlanSetSecuritySettings(wlanHandle, wso, (LPCWSTR)pStringSecurityDescriptor);
if (dRet != ERROR_SUCCESS)
{
bRes = false;
}
return bRes;
}
МОЯ ПРОБЛЕМА: Кажется, все работает, все функции isValid всегда возвращают 'true'. Единственная часть, которая не работает
ConvertSecurityDescriptorToStringSecurityDescriptor(securityDescriptor,
SDDL_REVISION_1,
DACL_SECURITY_INFORMATION,
pStringSecurityDescriptor,
NULL
);
Эта часть возвращается L"D:NO_ACCESS_CONTROL"
в pStringSecurityDescriptor
, И, как ожидается, следующая функция WlanSetSecuritySettings(wlanHandle, wso, (LPCWSTR)pStringSecurityDescriptor)
возвращается 87:INVALID_PARAMETER
поскольку строка явно не действительна.
ВОПРОС: Неужели я что-то не так после этого руководства? Нужно ли что-то еще для инициализации или другие значения? Как мне исправить код?
1 ответ
Это потому, что SetSecurityDescriptorDacl() передается нулевым для DACL, поэтому он говорит, что есть NULL DACL. Должен быть передан pAcl вместо NULL, который работает для меня.