Sergio Calderon
Sergio Calderon

Reputation: 867

NetLocalGroupAddMembers returns success, but It is not working as expected

I had a problem with LookupAccountName, wrote a question and figured it out I had to use LookupAccountName twice to work. Now I am trying to use NetLocalGroupAddMembers with the SID that I got from LookupAccountName, it returns success, but the newly created users won't be added to Users group.

I am getting the Users group from the CreateWellKnownSid, translating it to string using LookupAccountSid and sending the account SID to NetLocalGroupAddMembers by translating the first argument (the new account name) to SID with LookupAccountName.

EDIT:

This is a testable set of code:

#include <Windows.h>
#include <tchar.h>
#include <wchar.h>
#include <LM.h>
#include <sddl.h>

#pragma comment(lib, "Netapi32.lib")
#define MAX_NAME 256

VOID ShowError(DWORD errorCode)
{
    //FormatMessageW
    DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS;
    LPWSTR errorMessage;
    DWORD size = 0;

    if (!FormatMessageW(flags, NULL, errorCode, 0, (LPWSTR)&errorMessage, size, NULL))
    {
        fwprintf(stderr, L"Could not get the format message, error code: %u\n", GetLastError());
        exit(1);
    }

    wprintf(L"\n%s\n", errorMessage);

    LocalFree(errorMessage);
}


int wmain(int argc, WCHAR **argv)
{
    //NetUserAdd function
    NET_API_STATUS addUser;
    DWORD infoLevel = 1;        //USER_INFO_1
    USER_INFO_1 userData;
    DWORD paramError = 0;

    //LocalAlloc
    UINT memAttributes = LMEM_FIXED;
    DWORD sidSize = SECURITY_MAX_SID_SIZE;

    //CreateWellKnownSid
    WELL_KNOWN_SID_TYPE sidType = WinBuiltinUsersSid;
    PSID groupSID;

    //LookupAccountSid
    WCHAR name[MAX_NAME];
    DWORD nameSize = MAX_NAME;
    WCHAR domainName[MAX_NAME];
    DWORD domainNameSize = MAX_NAME;
    SID_NAME_USE accountType;

    //LookupAccountName
    LPCWSTR machine = NULL;
    BYTE accountSIDBuf[SECURITY_MAX_SID_SIZE];
    PSID accountSID = (PSID)accountSIDBuf;
    DWORD cbSid = 0;
    SID_NAME_USE typeOfAccount;
    /*WCHAR refDomain[MAX_NAME];*/
    DWORD cchRefDomain = 0;

    //NetLocalGroupAddMembers
    NET_API_STATUS localGroupAdd;
    DWORD levelOfData = 0;  //LOCALGROUP_MEMBERS_INFO_0
    LOCALGROUP_MEMBERS_INFO_0 localMembers;
    DWORD totalEntries = 0;


    if (argc != 2)
    {
        fwprintf(stderr, L"\nUsage: %s [UserName]\n", *argv);
        return 1;

    }

    //Set up USER_INFO_1 structure
    userData.usri1_name = argv[1];
    userData.usri1_password = NULL;
    userData.usri1_priv = USER_PRIV_USER;
    userData.usri1_home_dir = NULL;
    userData.usri1_comment = NULL;
    userData.usri1_flags = UF_SCRIPT;
    userData.usri1_script_path = NULL;

    addUser = NetUserAdd(NULL, infoLevel, (LPBYTE)&userData, &paramError);

    if (addUser != NERR_Success)
    {
        fwprintf(stderr, L"\nA system error has ocurred: %d\n", addUser);

        return 1;
    }
    else
    {

        //Let's allocate memory for the SID
        if (!(groupSID = LocalAlloc(memAttributes, sidSize)))   //if fails
        {
            ShowError(GetLastError());
            exit(1);

        }

        //Let's create a SID for Users group
        if (!CreateWellKnownSid(sidType, NULL, groupSID, &sidSize))
        {
            ShowError(GetLastError());
            exit(1);
        }
        else
        {

            if (!LookupAccountSidW(NULL, groupSID, name, &nameSize,
                domainName, &domainNameSize, &accountType))
            {
                ShowError(GetLastError());
                return 1;

            }

            if (!LookupAccountNameW(NULL, argv[1], NULL, &cbSid, NULL, &cchRefDomain, &typeOfAccount))
            {
                ShowError(GetLastError());
                /*exit(1);*/

            }

            PSID theSID;
            LPWSTR refDomainName = (LPWSTR)malloc(cchRefDomain * sizeof(WCHAR));

            if (!(theSID = LocalAlloc(memAttributes, cbSid)))
            {
                ShowError(GetLastError());
                exit(1);
            }

            if (refDomainName == NULL)
            {
                fwprintf(stderr, L"Error allocating memory for RefDomainName \n");
                exit(1);
            }

            //Here we go again! 
            if (!LookupAccountNameW(NULL, argv[1], theSID, &cbSid,
                refDomainName, &cchRefDomain, &typeOfAccount))
            {
                ShowError(GetLastError());
                exit(1);

            }

            //Here I should be able to use NetLocalGroupAddMembers
            //to add the user passed as argument to the Users group. 
            localMembers.lgrmi0_sid = theSID;

            localGroupAdd = NetLocalGroupAddMembers(NULL, name, levelOfData, (LPBYTE)&localMembers, totalEntries);

            if (localGroupAdd != NERR_Success)
            {
                ShowError(localGroupAdd);
                return 1;
            }
            else
            {

                ShowError(localGroupAdd);

            }

            LocalFree(theSID);
            free(refDomainName);

        }

        LocalFree(groupSID);
    }
    return 0;
}

This is the result I got, as expected:

The data area passed to a system call is too small.

The operation completed successfully.

But when I query the newly created user with Net User, It says:

Local Group Memberships

Global Group Membership *None

It should say Users in the Local Group Membership.

Any help?

Thanks!

Upvotes: 1

Views: 266

Answers (1)

Werner Henze
Werner Henze

Reputation: 16781

You are calling NetLocalGroupAddMembers with totalentries=0, but you should call it with 1.

Side notes:

Is there any good reason to put all variables at the top and not declare them where you need them? Locality might have helped you find the error.

usri1_password is not documented to be allowed to be NULL.

Are you sure you want to pass NULL everywhere as machine/system name. Sometimes this is something different than ".", see for example LookupAccountSidW.

Upvotes: 2

Related Questions