mirror of
https://github.com/reactos/wine.git
synced 2024-12-12 05:45:56 +00:00
advapi32: Make it possible to free data buffer returned from LsaLookupSids().
This commit is contained in:
parent
cf195437c6
commit
af641dc94c
@ -32,4 +32,22 @@ BOOL lookup_local_user_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LP
|
||||
WCHAR *SERV_dup(const char *str) DECLSPEC_HIDDEN;
|
||||
NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD) DECLSPEC_HIDDEN;
|
||||
|
||||
/* heap allocation helpers */
|
||||
static void *heap_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
|
||||
static inline void *heap_alloc( size_t len )
|
||||
{
|
||||
return HeapAlloc( GetProcessHeap(), 0, len );
|
||||
}
|
||||
|
||||
static void *heap_realloc( void *mem, size_t len ) __WINE_ALLOC_SIZE(2);
|
||||
static inline void *heap_realloc( void *mem, size_t len )
|
||||
{
|
||||
return HeapReAlloc( GetProcessHeap(), 0, mem, len );
|
||||
}
|
||||
|
||||
static inline BOOL heap_free( void *mem )
|
||||
{
|
||||
return HeapFree( GetProcessHeap(), 0, mem );
|
||||
}
|
||||
|
||||
#endif /* __WINE_ADVAPI32MISC_H */
|
||||
|
@ -344,6 +344,56 @@ static INT build_domain(PLSA_REFERENCED_DOMAIN_LIST currentList, PLSA_UNICODE_ST
|
||||
return currentList->Entries-1;
|
||||
}
|
||||
|
||||
/* Adds domain info to referenced domain list.
|
||||
Domain list is stored as plain buffer, layout is:
|
||||
|
||||
LSA_REFERENCED_DOMAIN_LIST,
|
||||
LSA_TRUST_INFORMATION array,
|
||||
domain data array of
|
||||
{
|
||||
domain name data (WCHAR buffer),
|
||||
SID data
|
||||
}
|
||||
|
||||
Parameters:
|
||||
list [I] referenced list pointer
|
||||
domain [I] domain name string
|
||||
data [IO] pointer to domain data array
|
||||
*/
|
||||
static LONG lsa_reflist_add_domain(LSA_REFERENCED_DOMAIN_LIST *list, LSA_UNICODE_STRING *domain, char **data)
|
||||
{
|
||||
ULONG sid_size = 0,domain_size = 0;
|
||||
BOOL handled = FALSE;
|
||||
SID_NAME_USE use;
|
||||
LONG i;
|
||||
|
||||
for (i = 0; i < list->Entries; i++)
|
||||
{
|
||||
/* try to reuse index */
|
||||
if ((list->Domains[i].Name.Length == domain->Length) &&
|
||||
(!strncmpiW(list->Domains[i].Name.Buffer, domain->Buffer, (domain->Length / sizeof(WCHAR)))))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* no matching domain found, store name */
|
||||
list->Domains[list->Entries].Name.Length = domain->Length;
|
||||
list->Domains[list->Entries].Name.MaximumLength = domain->MaximumLength;
|
||||
list->Domains[list->Entries].Name.Buffer = (WCHAR*)*data;
|
||||
memcpy(list->Domains[list->Entries].Name.Buffer, domain->Buffer, domain->MaximumLength);
|
||||
*data += domain->MaximumLength;
|
||||
|
||||
/* get and store SID data */
|
||||
list->Domains[list->Entries].Sid = *data;
|
||||
lookup_name(domain, NULL, &sid_size, NULL, &domain_size, &use, &handled);
|
||||
domain_size = 0;
|
||||
lookup_name(domain, list->Domains[list->Entries].Sid, &sid_size, NULL, &domain_size, &use, &handled);
|
||||
*data += sid_size;
|
||||
|
||||
return list->Entries++;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* LsaLookupNames2 [ADVAPI32.@]
|
||||
*
|
||||
@ -450,70 +500,127 @@ NTSTATUS WINAPI LsaLookupNames2( LSA_HANDLE policy, ULONG flags, ULONG count,
|
||||
* Failure: STATUS_NONE_MAPPED or NTSTATUS code.
|
||||
*/
|
||||
NTSTATUS WINAPI LsaLookupSids(
|
||||
IN LSA_HANDLE PolicyHandle,
|
||||
IN ULONG Count,
|
||||
IN PSID *Sids,
|
||||
OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
|
||||
OUT PLSA_TRANSLATED_NAME *Names )
|
||||
LSA_HANDLE PolicyHandle,
|
||||
ULONG Count,
|
||||
PSID *Sids,
|
||||
LSA_REFERENCED_DOMAIN_LIST **ReferencedDomains,
|
||||
LSA_TRANSLATED_NAME **Names)
|
||||
{
|
||||
ULONG i, mapped, size;
|
||||
ULONG i, mapped, name_fullsize, domain_fullsize;
|
||||
ULONG name_size, domain_size;
|
||||
LSA_UNICODE_STRING domain;
|
||||
WCHAR *name_buffer;
|
||||
char *domain_data;
|
||||
SID_NAME_USE use;
|
||||
|
||||
TRACE("(%p,%u,%p,%p,%p) stub\n", PolicyHandle, Count, Sids,
|
||||
ReferencedDomains, Names);
|
||||
TRACE("(%p, %u, %p, %p, %p)\n", PolicyHandle, Count, Sids, ReferencedDomains, Names);
|
||||
|
||||
size = sizeof(LSA_TRANSLATED_NAME) * Count;
|
||||
if (!(*Names = HeapAlloc( GetProcessHeap(), 0, size) )) return STATUS_NO_MEMORY;
|
||||
if (!(*ReferencedDomains = HeapAlloc( GetProcessHeap(), 0, sizeof(LSA_REFERENCED_DOMAIN_LIST)) ))
|
||||
/* this length does not include actual string length yet */
|
||||
name_fullsize = sizeof(LSA_TRANSLATED_NAME) * Count;
|
||||
if (!(*Names = heap_alloc(name_fullsize))) return STATUS_NO_MEMORY;
|
||||
/* maximum count of stored domain infos is Count, allocate it like that cause really needed
|
||||
count could only be computed after sid data is retrieved */
|
||||
domain_fullsize = sizeof(LSA_REFERENCED_DOMAIN_LIST) + sizeof(LSA_TRUST_INFORMATION)*Count;
|
||||
if (!(*ReferencedDomains = heap_alloc(domain_fullsize)))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, *Names);
|
||||
heap_free(*Names);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
(*ReferencedDomains)->Entries = 0;
|
||||
(*ReferencedDomains)->Domains = NULL;
|
||||
(*ReferencedDomains)->Domains = (LSA_TRUST_INFORMATION*)((char*)*ReferencedDomains + sizeof(LSA_REFERENCED_DOMAIN_LIST));
|
||||
|
||||
/* Get full names data length and full length needed to store domain name and SID */
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
(*Names)[i].Use = SidTypeUnknown;
|
||||
(*Names)[i].DomainIndex = -1;
|
||||
(*Names)[i].Name.Buffer = NULL;
|
||||
|
||||
memset(&(*ReferencedDomains)->Domains[i], 0, sizeof(LSA_TRUST_INFORMATION));
|
||||
|
||||
name_size = domain_size = 0;
|
||||
if (!LookupAccountSidW(NULL, Sids[i], NULL, &name_size, NULL, &domain_size, &use) &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
if (name_size)
|
||||
{
|
||||
(*Names)[i].Name.Length = (name_size - 1) * sizeof(WCHAR);
|
||||
(*Names)[i].Name.MaximumLength = name_size * sizeof(WCHAR);
|
||||
name_fullsize += (*Names)[i].Name.MaximumLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*Names)[i].Name.Length = 0;
|
||||
(*Names)[i].Name.MaximumLength = 0;
|
||||
}
|
||||
|
||||
/* This potentially allocates more than needed, cause different names will reuse same domain index.
|
||||
Also it's not possible to store domain name length right here for the same reason. */
|
||||
if (domain_size)
|
||||
{
|
||||
ULONG sid_size = 0;
|
||||
BOOL handled = FALSE;
|
||||
WCHAR *name;
|
||||
|
||||
domain_fullsize += domain_size * sizeof(WCHAR);
|
||||
|
||||
/* get domain SID size too */
|
||||
name = heap_alloc(domain_size * sizeof(WCHAR));
|
||||
*name = 0;
|
||||
LookupAccountSidW(NULL, Sids[i], NULL, &name_size, name, &domain_size, &use);
|
||||
|
||||
domain.Buffer = name;
|
||||
domain.Length = domain_size * sizeof(WCHAR);
|
||||
domain.MaximumLength = domain_size * sizeof(WCHAR);
|
||||
|
||||
lookup_name(&domain, NULL, &sid_size, NULL, &domain_size, &use, &handled);
|
||||
domain_fullsize += sid_size;
|
||||
|
||||
heap_free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now we have full length needed for both */
|
||||
*Names = heap_realloc(*Names, name_fullsize);
|
||||
name_buffer = (WCHAR*)((char*)*Names + sizeof(LSA_TRANSLATED_NAME)*Count);
|
||||
|
||||
*ReferencedDomains = heap_realloc(*ReferencedDomains, domain_fullsize);
|
||||
/* fix pointer after reallocation */
|
||||
(*ReferencedDomains)->Domains = (LSA_TRUST_INFORMATION*)((char*)*ReferencedDomains + sizeof(LSA_REFERENCED_DOMAIN_LIST));
|
||||
domain_data = (char*)(*ReferencedDomains)->Domains + sizeof(LSA_TRUST_INFORMATION)*Count;
|
||||
|
||||
mapped = 0;
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
name_size = domain_size = 0;
|
||||
(*Names)[i].Use = SidTypeUnknown;
|
||||
(*Names)[i].DomainIndex = -1;
|
||||
(*Names)[i].Name.Length = 0;
|
||||
(*Names)[i].Name.MaximumLength = 0;
|
||||
(*Names)[i].Name.Buffer = NULL;
|
||||
|
||||
if (!LookupAccountSidW(NULL, Sids[i], NULL, &name_size, NULL, &domain_size, &use) &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
LSA_UNICODE_STRING domain;
|
||||
|
||||
mapped++;
|
||||
|
||||
if (domain_size)
|
||||
{
|
||||
domain.Length = (domain_size - 1) * sizeof(WCHAR);
|
||||
domain.MaximumLength = domain_size*sizeof(WCHAR);
|
||||
domain.Buffer = HeapAlloc(GetProcessHeap(),0,domain.MaximumLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
domain.Length = 0;
|
||||
domain.MaximumLength = 0;
|
||||
domain.Buffer = NULL;
|
||||
domain.MaximumLength = domain_size * sizeof(WCHAR);
|
||||
domain.Buffer = heap_alloc(domain.MaximumLength);
|
||||
}
|
||||
|
||||
(*Names)[i].Name.Length = (name_size - 1) * sizeof(WCHAR);
|
||||
(*Names)[i].Name.MaximumLength = name_size * sizeof(WCHAR);
|
||||
(*Names)[i].Name.Buffer = HeapAlloc(GetProcessHeap(), 0, name_size * sizeof(WCHAR));
|
||||
(*Names)[i].Name.Buffer = name_buffer;
|
||||
LookupAccountSidW(NULL, Sids[i], (*Names)[i].Name.Buffer, &name_size, domain.Buffer, &domain_size, &use);
|
||||
(*Names)[i].Use = use;
|
||||
|
||||
if (domain_size)
|
||||
(*Names)[i].DomainIndex = build_domain(*ReferencedDomains, &domain);
|
||||
{
|
||||
(*Names)[i].DomainIndex = lsa_reflist_add_domain(*ReferencedDomains, &domain, &domain_data);
|
||||
heap_free(domain.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
name_buffer += name_size;
|
||||
}
|
||||
TRACE("mapped %u out of %u\n",mapped,Count);
|
||||
TRACE("mapped %u out of %u\n", mapped, Count);
|
||||
|
||||
if (mapped == Count) return STATUS_SUCCESS;
|
||||
if (mapped) return STATUS_SOME_NOT_MAPPED;
|
||||
|
@ -43,6 +43,7 @@ static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBU
|
||||
static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
|
||||
static BOOL (WINAPI *pConvertSidToStringSidA)(PSID,LPSTR*);
|
||||
static NTSTATUS (WINAPI *pLsaLookupNames2)(LSA_HANDLE,ULONG,ULONG,PLSA_UNICODE_STRING,PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_SID2*);
|
||||
static NTSTATUS (WINAPI *pLsaLookupSids)(LSA_HANDLE,ULONG,PSID*,LSA_REFERENCED_DOMAIN_LIST**,LSA_TRANSLATED_NAME**);
|
||||
|
||||
static BOOL init(void)
|
||||
{
|
||||
@ -55,6 +56,7 @@ static BOOL init(void)
|
||||
pLsaQueryInformationPolicy = (void*)GetProcAddress(hadvapi32, "LsaQueryInformationPolicy");
|
||||
pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
|
||||
pLsaLookupNames2 = (void*)GetProcAddress(hadvapi32, "LsaLookupNames2");
|
||||
pLsaLookupSids = (void*)GetProcAddress(hadvapi32, "LsaLookupSids");
|
||||
|
||||
if (pLsaClose && pLsaEnumerateAccountRights && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA)
|
||||
return TRUE;
|
||||
@ -351,6 +353,55 @@ static void test_LsaLookupNames2(void)
|
||||
ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
|
||||
}
|
||||
|
||||
static void test_LsaLookupSids(void)
|
||||
{
|
||||
LSA_REFERENCED_DOMAIN_LIST *list;
|
||||
LSA_OBJECT_ATTRIBUTES attrs;
|
||||
LSA_TRANSLATED_NAME *names;
|
||||
LSA_HANDLE policy;
|
||||
TOKEN_USER *user;
|
||||
NTSTATUS status;
|
||||
HANDLE token;
|
||||
DWORD size;
|
||||
BOOL ret;
|
||||
|
||||
memset(&attrs, 0, sizeof(attrs));
|
||||
attrs.Length = sizeof(attrs);
|
||||
|
||||
status = pLsaOpenPolicy(NULL, &attrs, POLICY_LOOKUP_NAMES, &policy);
|
||||
ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
|
||||
|
||||
ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
|
||||
ok(ret, "got %d\n", ret);
|
||||
|
||||
ret = GetTokenInformation(token, TokenUser, NULL, 0, &size);
|
||||
ok(!ret, "gotr %d\n", ret);
|
||||
|
||||
user = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
ret = GetTokenInformation(token, TokenUser, user, size, &size);
|
||||
ok(ret, "got %d\n", ret);
|
||||
|
||||
status = pLsaLookupSids(policy, 1, &user->User.Sid, &list, &names);
|
||||
ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
|
||||
|
||||
ok(list->Entries > 0, "got %d\n", list->Entries);
|
||||
if (list->Entries)
|
||||
{
|
||||
ok((char*)list->Domains - (char*)list > 0, "%p, %p\n", list, list->Domains);
|
||||
ok((char*)list->Domains[0].Sid - (char*)list->Domains > 0, "%p, %p\n", list->Domains, list->Domains[0].Sid);
|
||||
}
|
||||
|
||||
pLsaFreeMemory(names);
|
||||
pLsaFreeMemory(list);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, user);
|
||||
|
||||
CloseHandle(token);
|
||||
|
||||
status = pLsaClose(policy);
|
||||
ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
|
||||
}
|
||||
|
||||
START_TEST(lsa)
|
||||
{
|
||||
if (!init()) {
|
||||
@ -360,4 +411,5 @@ START_TEST(lsa)
|
||||
|
||||
test_lsa();
|
||||
test_LsaLookupNames2();
|
||||
test_LsaLookupSids();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user