ОБНОВЛЕНИЕ: Ниже приведен обновленный код для исправления моей ошибки.Проведя дальнейшие исследования, я узнал, что проблема была в том, что я не указал размер буфера для 2 переменных: namelen и domainnamelen в моем исходном коде (спасибо@RbMm и @jwdonahue для указания).
DWORD getSACLinfo(HANDLE rToken, SE_OBJECT_TYPE objectType, ACEVALUE*& aceRef, int* count)
{
size_t len;
int arrSize = 0;
wchar_t* buf;
wchar_t* sidName = NULL;
wchar_t* domainName = NULL;
PSID sid;
PSID sidOwner;
PACL sacl = NULL;
DWORD retValue;
DWORD dwRevision;
DWORD namelen;
DWORD domainnamelen;
SYSTEM_AUDIT_ACE* ace = NULL;
PSECURITY_DESCRIPTOR pSS = NULL;
SECURITY_DESCRIPTOR_CONTROL sdControl;
/* Get SACL security descriptor */
retValue = GetSecurityInfo(rToken, objectType,
OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
&sidOwner, NULL, NULL, &sacl, &pSS);
if (retValue == ERROR_SUCCESS)
{
if (GetSecurityDescriptorControl(pSS, &sdControl, &dwRevision) == FALSE)
{
retValue = ERROR_INVALID_FUNCTION;
}
else if (sacl != NULL && (sdControl & SE_SACL_PRESENT) == SE_SACL_PRESENT)
{
for (int i = 0; i < sacl->AceCount; i++)
{
GetAce(sacl, i, (PVOID*)&ace);
/* Get SID from Ace */
sid = (PSID)&ace->SidStart;
if (IsValidSid(sid) && ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE)
{
arrSize++;
}
}
// Allocate memory for the data structures to be exported
aceRef = (ACEVALUE*)malloc(arrSize * sizeof(ACEVALUE));
if (arrSize > 0 && aceRef != NULL)
{
for (int i = 0; i < sacl->AceCount; i++)
{
GetAce(sacl, i, (PVOID*)&ace);
sid = (PSID)&ace->SidStart;
if (IsValidSid(sid) && ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE)
{
// ADDED TO FIX THE PROBLEM
getNameBySID(sid, sidName, &namelen, domainName, &domainnamelen);
wprintf(L"size = %d, Owner = %s\n", namelen, sidName);
len = wcslen(sidName) + 1;
buf = (wchar_t*)malloc(len * sizeof(wchar_t));
if (buf != NULL)
{
wcscpy_s(buf, len, sidName);
aceRef[i].Name = buf;
}
aceRef[i].AceMask = ace->Mask;
aceRef[i].AceType = ace->Header.AceType;
aceRef[i].AceFlags = ace->Header.AceFlags;
}
}
}
}
}
else
{
retValue = GetLastError();
}
*count = arrSize;
// Memory deallocations
free(sidName);
free(domainName);
LocalFree((HLOCAL)pSS);
wprintf(L"FREED!\n");
return retValue;
}
Чтобы исправить, я добавил новую функцию getNameBySID
, чтобы она обеспечивала правильное пространство памяти для буферов sidName и Домен .Логика просто включает цикл do-while для продолжения итерации, пока она не удовлетворяет требованию LookupAccountSid
, где размер буфера является правильным для этих 2 буферов.Если предыдущий размер буфера слишком мал для заполнения буфера, он освобождает ранее выделенный буфер, а затем перераспределяется с правильным размером и пытается снова.
DWORD getNameBySID(PSID sid, wchar_t *&oNameBuf, DWORD *owNameSize, wchar_t *&dNameBuf, DWORD *dnNameSize)
{
const DWORD DEFAULT_SIZE = 256;
const wchar_t NONAME[] = L"Unknown";
bool status;
SID_NAME_USE peUse;
DWORD retValue;
DWORD ownerBufSize = *owNameSize;
DWORD domainBufSize = *dnNameSize;
// Create buffers that may be large enough
if (oNameBuf == NULL || dNameBuf == NULL)
{
ownerBufSize = domainBufSize = DEFAULT_SIZE;
oNameBuf = (wchar_t*)malloc(ownerBufSize * sizeof(wchar_t));
dNameBuf = (wchar_t*)malloc(domainBufSize * sizeof(wchar_t));
if (oNameBuf == NULL)
{
return ERROR_INSUFFICIENT_BUFFER;
}
if (dNameBuf == NULL)
{
free(oNameBuf);
return ERROR_INSUFFICIENT_BUFFER;
}
*owNameSize = ownerBufSize;
*dnNameSize = domainBufSize;
memset(oNameBuf, 0, ownerBufSize * sizeof(wchar_t));
memset(dNameBuf, 0, domainBufSize * sizeof(wchar_t));
}
do
{
status = (LookupAccountSid(NULL, sid, oNameBuf, owNameSize, dNameBuf, dnNameSize, &peUse) == TRUE);
if (!status)
{
retValue = GetLastError();
if (*owNameSize > ownerBufSize)
{
// Reallocate memory for the buffer and try again.
//wprintf(L"The account name buffer was too small. It will be reallocated.\n");
free(oNameBuf);
oNameBuf = (wchar_t*)malloc(*owNameSize * sizeof(wchar_t));
if (oNameBuf == NULL)
{
return ERROR_INSUFFICIENT_BUFFER;
}
ownerBufSize = *owNameSize;
memset(oNameBuf, 0, ownerBufSize * sizeof(wchar_t));
}
else if (*dnNameSize > domainBufSize)
{
// Reallocate memory for the buffer and try again.
//wprintf(L"The domain name buffer was too small. It will be reallocated.\n");
free(dNameBuf);
dNameBuf = (wchar_t*)malloc(*dnNameSize * sizeof(wchar_t));
if (dNameBuf == NULL)
{
return ERROR_INSUFFICIENT_BUFFER;
}
domainBufSize = *dnNameSize;
memset(dNameBuf, 0, domainBufSize * sizeof(wchar_t));
}
else if (retValue == ERROR_NONE_MAPPED)
{
// A name could not be found for the SID due to an unexpected error occurred.
if (ownerBufSize > wcslen(NONAME))
{
wcscpy_s(oNameBuf, wcslen(NONAME) + 1, NONAME);
oNameBuf[wcslen(NONAME)] = L'\0';
}
dNameBuf[0] = L'\0';
break;
}
else
{
wprintf(L"LookupAccountSid failed. GetLastError returned: %d\n", retValue);
break;
}
}
} while (!status);
*owNameSize = ownerBufSize;
*dnNameSize = domainBufSize;
return (status ? ERROR_SUCCESS : retValue);
}
По сути, моя getSACLinfo
функция остается практически неизменной, за исключением вызова getNameBySID
для получения буферов правильного размера для этих 2 имен.
Ниже приводится ожидаемая информация.