advapi32: Factor out lookup of local usernames and well-known SIDs.

Based on a patch by Aric Stewart.
This commit is contained in:
Hans Leidekker 2009-08-06 11:12:51 +02:00 committed by Alexandre Julliard
parent c0892c2f35
commit e5e40ef423
2 changed files with 147 additions and 67 deletions

View File

@ -24,4 +24,7 @@ const char * debugstr_sid(PSID sid);
BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName);
BOOL ADVAPI_GetComputerSid(PSID sid);
BOOL lookup_local_wellknown_name(LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*);
BOOL lookup_local_user_name(LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*);
#endif /* __WINE_ADVAPI32MISC_H */

View File

@ -2653,61 +2653,86 @@ static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR Referenc
return ret;
}
/******************************************************************************
* LookupAccountNameW [ADVAPI32.@]
*/
BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
LPDWORD cbSid, LPWSTR ReferencedDomainName,
LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
LSA_UNICODE_STRING *domain )
{
BOOL ret;
PSID pSid;
unsigned int i;
DWORD nameLen;
LPWSTR userName = NULL;
LPCWSTR domainName;
LPCWSTR lpAccountNamePtr;
LPCWSTR lpDomainNamePtr = NULL;
WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
FIXME("%s %s %p %p %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
while (p > str->Buffer && *p != '\\') p--;
if (!ADVAPI_IsLocalComputer(lpSystemName))
if (*p == '\\')
{
SetLastError(RPC_S_SERVER_UNAVAILABLE);
return FALSE;
}
domain->Buffer = str->Buffer;
domain->Length = (p - str->Buffer) * sizeof(WCHAR);
if (!lpAccountName || !strcmpW(lpAccountName, Blank))
{
lpAccountName = BUILTIN;
}
/* Check well known SIDs first */
if ((lpAccountNamePtr = strrchrW(lpAccountName,'\\')))
{
lpAccountNamePtr++;
lpDomainNamePtr = lpAccountName;
account->Buffer = p + 1;
account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
}
else
lpAccountNamePtr = lpAccountName;
{
domain->Buffer = NULL;
domain->Length = 0;
for (i = 0; i < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); i++)
account->Buffer = str->Buffer;
account->Length = str->Length;
}
}
static BOOL match_domain( ULONG idx, LSA_UNICODE_STRING *domain )
{
ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
return TRUE;
return FALSE;
}
static BOOL match_account( ULONG idx, LSA_UNICODE_STRING *account )
{
ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
return TRUE;
if (ACCOUNT_SIDS[idx].alias)
{
len = strlenW( ACCOUNT_SIDS[idx].alias );
if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
return TRUE;
}
return FALSE;
}
/*
* Helper function for LookupAccountNameW
*/
BOOL lookup_local_wellknown_name( LSA_UNICODE_STRING *account_and_domain,
PSID Sid, LPDWORD cbSid,
LPWSTR ReferencedDomainName,
LPDWORD cchReferencedDomainName,
PSID_NAME_USE peUse, BOOL *handled )
{
PSID pSid;
LSA_UNICODE_STRING account, domain;
BOOL ret = TRUE;
ULONG i;
*handled = FALSE;
split_domain_account( account_and_domain, &account, &domain );
for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
{
/* check domain first */
if (lpDomainNamePtr && (strncmpiW(lpDomainNamePtr, ACCOUNT_SIDS[i].domain, strlenW(ACCOUNT_SIDS[i].domain)) || lpDomainNamePtr[strlenW(ACCOUNT_SIDS[i].domain)]!='\\'))
continue;
if (domain.Buffer && !match_domain( i, &domain )) continue;
if (!strcmpiW(lpAccountNamePtr, ACCOUNT_SIDS[i].account) ||
(ACCOUNT_SIDS[i].alias && !strcmpiW(lpAccountNamePtr, ACCOUNT_SIDS[i].alias)))
if (match_account( i, &account ))
{
DWORD sidLen = SECURITY_MAX_SID_SIZE;
DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
pSid = HeapAlloc(GetProcessHeap(), 0, sidLen);
if (!(pSid = HeapAlloc( GetProcessHeap(), 0, sidLen ))) return FALSE;
ret = CreateWellKnownSid(ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen);
if (ret)
if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
{
if (*cbSid < sidLen)
{
@ -2718,47 +2743,57 @@ BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSI
{
CopySid(*cbSid, Sid, pSid);
}
*cbSid = sidLen;
}
domainName = ACCOUNT_SIDS[i].domain;
nameLen = strlenW(domainName);
if (*cchReferencedDomainName <= nameLen || !ret)
len = strlenW( ACCOUNT_SIDS[i].domain );
if (*cchReferencedDomainName <= len || !ret)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
nameLen += 1;
len++;
ret = FALSE;
}
else if (ReferencedDomainName)
{
strcpyW(ReferencedDomainName, domainName);
strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
}
*cchReferencedDomainName = nameLen;
*cchReferencedDomainName = len;
if (ret)
{
*peUse = ACCOUNT_SIDS[i].name_use;
}
HeapFree(GetProcessHeap(), 0, pSid);
*handled = TRUE;
return ret;
}
}
return ret;
}
BOOL lookup_local_user_name( LSA_UNICODE_STRING *account_and_domain,
PSID Sid, LPDWORD cbSid,
LPWSTR ReferencedDomainName,
LPDWORD cchReferencedDomainName,
PSID_NAME_USE peUse, BOOL *handled )
{
DWORD nameLen;
LPWSTR userName = NULL;
LSA_UNICODE_STRING account, domain;
BOOL ret = TRUE;
*handled = FALSE;
split_domain_account( account_and_domain, &account, &domain );
/* Let the current Unix user id masquerade as first Windows user account */
nameLen = UNLEN + 1;
if (!(userName = HeapAlloc( GetProcessHeap(), 0, nameLen * sizeof(WCHAR) ))) return FALSE;
userName = HeapAlloc(GetProcessHeap(), 0, nameLen*sizeof(WCHAR));
if (lpDomainNamePtr)
if (domain.Buffer)
{
/* check to make sure this account is on this computer */
if (GetComputerNameW(userName, &nameLen) && strcmpW(lpDomainNamePtr, userName))
if (GetComputerNameW( userName, &nameLen ) &&
(domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
{
SetLastError(ERROR_NONE_MAPPED);
ret = FALSE;
@ -2766,27 +2801,69 @@ BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSI
nameLen = UNLEN + 1;
}
if (GetUserNameW(userName, &nameLen) && !strcmpW(lpAccountNamePtr, userName))
ret = lookup_user_account_name(Sid, cbSid, ReferencedDomainName,
cchReferencedDomainName, peUse);
if (GetUserNameW( userName, &nameLen ) &&
account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
{
ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
*handled = TRUE;
}
else
{
nameLen = UNLEN + 1;
if (GetComputerNameW(userName, &nameLen) && !strcmpW(lpAccountNamePtr, userName))
ret = lookup_computer_account_name(Sid, cbSid, ReferencedDomainName,
cchReferencedDomainName, peUse);
else
if (GetComputerNameW( userName, &nameLen ) &&
account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
{
SetLastError(ERROR_NONE_MAPPED);
ret = FALSE;
ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
*handled = TRUE;
}
}
HeapFree(GetProcessHeap(), 0, userName);
return ret;
}
/******************************************************************************
* LookupAccountNameW [ADVAPI32.@]
*/
BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
LPDWORD cbSid, LPWSTR ReferencedDomainName,
LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
{
BOOL ret, handled;
LSA_UNICODE_STRING account;
FIXME("%s %s %p %p %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
if (!ADVAPI_IsLocalComputer( lpSystemName ))
{
SetLastError( RPC_S_SERVER_UNAVAILABLE );
return FALSE;
}
if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
{
lpAccountName = BUILTIN;
}
RtlInitUnicodeString( &account, lpAccountName );
/* Check well known SIDs first */
ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
cchReferencedDomainName, peUse, &handled );
if (handled)
return ret;
/* Check user names */
ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
cchReferencedDomainName, peUse, &handled);
if (handled)
return ret;
SetLastError( ERROR_NONE_MAPPED );
return FALSE;
}
/******************************************************************************
* PrivilegeCheck [ADVAPI32.@]
*/