Search code examples
c++securitynetwork-programmingwifi

c++ - Correctly implement WlanSetSecuritySettings for WlanHostedNetwork-functions


As the title says I'm not quite sure how I correctly implement the WlanSetSecuritySettings function in order to get full access from the system for editing the WlanHostedNetwork from the native wlanapi (-> as I get an error on some systems, which is saying that I do not have the access and that I require elevation!). In the MSDN doc there is the following manual how to do this - I tried to follow it as far as possible:

The WlanHostedNetworkForceStart function could fail if Hosted Network state is wlan_hosted_network_unavailable or the caller does not have sufficient privileges. This function to force the start of the Hosted Network can only be called if the user has the appropriate associated privilege. Permissions are stored in a discretionary access control list (DACL) associated with a WLAN_SECURABLE_OBJECT. To call the WlanHostedNetworkForceStart, the client access token of the caller must have elevated privileges exposed by the following enumeration in WLAN_SECURABLE_OBJECT: wlan_secure_hosted_network_elevated_access

and therefore:

A successful call to the WlanSetSecuritySettings function overrides the default permissions associated with an object. For more information about default permissions, see Native Wifi API Permissions. The following describes the procedure for creating a security descriptor object and parsing it as a string. Call InitializeSecurityDescriptor to create a security descriptor in memory. Call SetSecurityDescriptorOwner to set the owner information for the security descriptor. Call InitializeAcl to create a discretionary access control list (DACL) in memory. Call AddAccessAllowedAce or AddAccessDeniedAce to add access control entries (ACEs) to the DACL. Set the AccessMask parameter to one of the following bitwise OR combinations as appropriate: WLAN_READ_ACCESS WLAN_READ_ACCESS | WLAN_EXECUTE_ACCESS WLAN_READ_ACCESS | WLAN_EXECUTE_ACCESS | WLAN_WRITE_ACCESS Call SetSecurityDescriptorDacl to add the DACL to the security descriptor. Call ConvertSecurityDescriptorToStringSecurityDescriptor to convert the descriptor to string. The string returned by ConvertSecurityDescriptorToStringSecurityDescriptor can then be used as the strModifiedSDDL parameter value when calling WlanSetSecuritySettings.

So this is my Code first of all (WifiClass is a static class and elevateAccess() is static too) - I did all the steps from the manual above:

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;

}

MY PROBLEM: Everything seems to work, all the isValid-functions always return 'true'. The only part which does not work is

ConvertSecurityDescriptorToStringSecurityDescriptor(securityDescriptor,
            SDDL_REVISION_1,
            DACL_SECURITY_INFORMATION,
            pStringSecurityDescriptor,
            NULL
        );

This part returns L"D:NO_ACCESS_CONTROL" in pStringSecurityDescriptor. And as expected the next function WlanSetSecuritySettings(wlanHandle, wso, (LPCWSTR)pStringSecurityDescriptor) returns 87:INVALID_PARAMETER as the String is obviously not valid.

QUESTION: Did I something wrong following this manual? Do I need something else to initialize or other values? How do I fix the code?


Solution

  • It's because SetSecurityDescriptorDacl() is being passed null for the DACL so it's saying there's a NULL DACL. It should be passed pAcl instead of NULL, which works for me.