You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1606 lines
40 KiB
1606 lines
40 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
misc.cpp
|
|
|
|
Abstract:
|
|
|
|
SCE Engine miscellaneous APIs
|
|
|
|
Author:
|
|
|
|
Jin Huang (jinhuang) 23-Jun-1997 created
|
|
|
|
--*/
|
|
#include "headers.h"
|
|
#include "serverp.h"
|
|
#include <ntregapi.h>
|
|
#include <userenv.h>
|
|
#include <ntlsa.h>
|
|
#include <io.h>
|
|
#pragma hdrstop
|
|
|
|
extern "C" {
|
|
#include "dumpnt.h"
|
|
|
|
}
|
|
|
|
//#define SCE_DBG 1
|
|
|
|
NTSTATUS
|
|
ScepGetLsaDomainInfo(
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
|
|
PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
|
|
);
|
|
|
|
DWORD
|
|
ScepGetEnvVarsFromProfile(
|
|
IN PWSTR UserProfileName,
|
|
IN PCWSTR VarName1,
|
|
IN PCWSTR VarName2 OPTIONAL,
|
|
OUT PWSTR *StrValue
|
|
);
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ScepOpenSamDomain(
|
|
IN ACCESS_MASK ServerAccess,
|
|
IN ACCESS_MASK DomainAccess,
|
|
OUT PSAM_HANDLE pServerHandle,
|
|
OUT PSAM_HANDLE pDomainHandle,
|
|
OUT PSID *DomainSid,
|
|
OUT PSAM_HANDLE pBuiltinDomainHandle OPTIONAL,
|
|
OUT PSID *BuiltinDomainSid OPTIONAL
|
|
)
|
|
/*
|
|
Routine Description
|
|
|
|
This routine opens the local SAM server for account domain and builtin
|
|
domain. The domain handles and their SIDs are returned.
|
|
|
|
*/
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
|
|
PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo=NULL;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
if ( !pServerHandle || !pDomainHandle || !DomainSid ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// initialize output buffers
|
|
//
|
|
*pServerHandle = NULL;
|
|
*pDomainHandle = NULL;
|
|
*DomainSid = NULL;
|
|
|
|
if ( pBuiltinDomainHandle ) {
|
|
*pBuiltinDomainHandle = NULL;
|
|
}
|
|
if ( BuiltinDomainSid ) {
|
|
*BuiltinDomainSid = NULL;
|
|
}
|
|
|
|
//
|
|
// Get information for the account domain
|
|
//
|
|
|
|
NtStatus = ScepGetLsaDomainInfo(
|
|
&PolicyAccountDomainInfo,
|
|
&PolicyPrimaryDomainInfo
|
|
);
|
|
|
|
if (!NT_SUCCESS(NtStatus)) {
|
|
return( NtStatus );
|
|
}
|
|
|
|
//
|
|
// Connect to the local SAM server
|
|
//
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
|
|
|
|
NtStatus = SamConnect(
|
|
NULL, // ServerName (Local machine)
|
|
pServerHandle,
|
|
ServerAccess,
|
|
&ObjectAttributes
|
|
);
|
|
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
//
|
|
// copy the SID to output buffer
|
|
//
|
|
DWORD SidLen = RtlLengthSid(PolicyAccountDomainInfo->DomainSid);
|
|
|
|
*DomainSid = (PSID)ScepAlloc(0, SidLen);
|
|
|
|
if ( *DomainSid != NULL ) {
|
|
|
|
NtStatus = RtlCopySid(SidLen, *DomainSid, PolicyAccountDomainInfo->DomainSid);
|
|
|
|
} else {
|
|
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
//
|
|
// open the account domain
|
|
//
|
|
NtStatus = SamOpenDomain(
|
|
*pServerHandle,
|
|
DomainAccess,
|
|
PolicyAccountDomainInfo->DomainSid,
|
|
pDomainHandle
|
|
);
|
|
|
|
if ( NT_SUCCESS(NtStatus) && BuiltinDomainSid != NULL ) {
|
|
//
|
|
// build the builtin domain sid
|
|
//
|
|
NtStatus = RtlAllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
BuiltinDomainSid
|
|
);
|
|
|
|
if ( NT_SUCCESS(NtStatus) && pBuiltinDomainHandle != NULL ) {
|
|
//
|
|
// open the builtin domain
|
|
//
|
|
NtStatus = SamOpenDomain(
|
|
*pServerHandle,
|
|
DomainAccess,
|
|
*BuiltinDomainSid,
|
|
pBuiltinDomainHandle
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// free memory and clean up
|
|
//
|
|
if ( PolicyAccountDomainInfo != NULL ) {
|
|
LsaFreeMemory( PolicyAccountDomainInfo );
|
|
}
|
|
if ( PolicyPrimaryDomainInfo != NULL ) {
|
|
LsaFreeMemory( PolicyPrimaryDomainInfo );
|
|
}
|
|
|
|
if ( !NT_SUCCESS(NtStatus)) {
|
|
|
|
SamCloseHandle( *pDomainHandle );
|
|
*pDomainHandle = NULL;
|
|
|
|
if ( pBuiltinDomainHandle ) {
|
|
SamCloseHandle( *pBuiltinDomainHandle );
|
|
*pBuiltinDomainHandle = NULL;
|
|
}
|
|
SamCloseHandle( *pServerHandle );
|
|
*pServerHandle = NULL;
|
|
|
|
ScepFree(*DomainSid);
|
|
*DomainSid = NULL;
|
|
|
|
if ( BuiltinDomainSid ) {
|
|
SamFreeMemory(*BuiltinDomainSid);
|
|
*BuiltinDomainSid = NULL;
|
|
}
|
|
|
|
}
|
|
return(NtStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ScepLookupNamesInDomain(
|
|
IN SAM_HANDLE DomainHandle,
|
|
IN PSCE_NAME_LIST NameList,
|
|
OUT PUNICODE_STRING *Names,
|
|
OUT PULONG *RIDs,
|
|
OUT PSID_NAME_USE *Use,
|
|
OUT PULONG CountOfName
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine looks up one or more names in the SAM account domain and
|
|
returns the relative IDs for each name in the list. The name list may
|
|
be user list, group list, or alias list.
|
|
|
|
Arguments:
|
|
|
|
DomainHandle - SAM handle to the account domain
|
|
|
|
NameList -- The list of names
|
|
|
|
Names - Translated UNICODE_STRING names. The name list must be freed by
|
|
|
|
RIDs -- List of relative IDs for each name
|
|
|
|
Use -- List of type for each name
|
|
|
|
CoutnOfName - The number of names in the list
|
|
|
|
Return value:
|
|
|
|
NTSTATUS
|
|
-- */
|
|
{
|
|
PSCE_NAME_LIST pUser;
|
|
ULONG cnt;
|
|
NTSTATUS NtStatus=ERROR_SUCCESS;
|
|
PUNICODE_STRING pUnicodeName=NULL;
|
|
|
|
|
|
UNICODE_STRING uName;
|
|
LPTSTR pTemp;
|
|
|
|
//
|
|
// Count how many names in the list
|
|
//
|
|
|
|
for (pUser=NameList, cnt=0;
|
|
pUser != NULL;
|
|
pUser = pUser->Next) {
|
|
|
|
if ( pUser->Name == NULL ) {
|
|
continue;
|
|
}
|
|
//
|
|
// note, this may be bigger than supposed to
|
|
//
|
|
cnt++;
|
|
}
|
|
|
|
if ( cnt > 0 ) {
|
|
//
|
|
// Allocate memory for UNICODE_STRING names
|
|
//
|
|
pUnicodeName = (PUNICODE_STRING)RtlAllocateHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
cnt * sizeof (UNICODE_STRING)
|
|
);
|
|
if ( pUnicodeName == NULL ) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
cnt = 0;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Initialize each UNICODE_STRING
|
|
//
|
|
for (pUser=NameList, cnt=0;
|
|
pUser != NULL;
|
|
pUser = pUser->Next) {
|
|
|
|
if ( pUser->Name == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
pTemp = wcschr(pUser->Name, L'\\');
|
|
|
|
if ( pTemp ) {
|
|
|
|
uName.Buffer = pUser->Name;
|
|
uName.Length = ((USHORT)(pTemp-pUser->Name))*sizeof(TCHAR);
|
|
|
|
if ( !ScepIsDomainLocal(&uName) ) {
|
|
ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pUser->Name);
|
|
continue;
|
|
}
|
|
pTemp++;
|
|
} else {
|
|
pTemp = pUser->Name;
|
|
}
|
|
|
|
RtlInitUnicodeString(&(pUnicodeName[cnt]), pTemp);
|
|
|
|
cnt++;
|
|
}
|
|
|
|
// lookup
|
|
NtStatus = SamLookupNamesInDomain(
|
|
DomainHandle,
|
|
cnt,
|
|
pUnicodeName,
|
|
RIDs,
|
|
Use
|
|
);
|
|
if ( !NT_SUCCESS(NtStatus) ) {
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pUnicodeName);
|
|
pUnicodeName = NULL;
|
|
}
|
|
}
|
|
Done:
|
|
|
|
*CountOfName = cnt;
|
|
*Names = pUnicodeName;
|
|
|
|
return(NtStatus);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ScepGetLsaDomainInfo(
|
|
PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
|
|
PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retrieves ACCOUNT domain information from the LSA
|
|
policy database.
|
|
|
|
|
|
Arguments:
|
|
|
|
PolicyAccountDomainInfo - Receives a pointer to a
|
|
POLICY_ACCOUNT_DOMAIN_INFO structure containing the account
|
|
domain info.
|
|
|
|
PolicyPrimaryDomainInfo - Receives a pointer to a
|
|
POLICY_PRIMARY_DOMAIN_INFO structure containing the Primary
|
|
domain info.
|
|
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - Succeeded.
|
|
|
|
Other status values that may be returned from:
|
|
|
|
LsaOpenPolicy()
|
|
LsaQueryInformationPolicy()
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status, IgnoreStatus;
|
|
|
|
LSA_HANDLE PolicyHandle;
|
|
OBJECT_ATTRIBUTES PolicyObjectAttributes;
|
|
|
|
//
|
|
// Open the policy database
|
|
//
|
|
|
|
InitializeObjectAttributes( &PolicyObjectAttributes,
|
|
NULL, // Name
|
|
0, // Attributes
|
|
NULL, // Root
|
|
NULL ); // Security Descriptor
|
|
|
|
Status = LsaOpenPolicy( NULL,
|
|
&PolicyObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&PolicyHandle );
|
|
if ( NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// Query the account domain information
|
|
//
|
|
|
|
Status = LsaQueryInformationPolicy( PolicyHandle,
|
|
PolicyAccountDomainInformation,
|
|
(PVOID *)PolicyAccountDomainInfo );
|
|
|
|
if ( NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// Query the Primary domain information
|
|
//
|
|
|
|
Status = LsaQueryInformationPolicy( PolicyHandle,
|
|
PolicyPrimaryDomainInformation,
|
|
(PVOID *)PolicyPrimaryDomainInfo );
|
|
}
|
|
|
|
IgnoreStatus = LsaClose( PolicyHandle );
|
|
ASSERT(NT_SUCCESS(IgnoreStatus));
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ScepConvertLogonHours(
|
|
IN PSCE_LOGON_HOUR pLogonHours,
|
|
OUT PUCHAR LogonHourBitMask
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine converted the logon hour range in hours (for example, 7-20)
|
|
to logon hour bit mask (for example, 0001 1111 1111 1111 1000 0000,
|
|
for one day).
|
|
|
|
|
|
Arguments:
|
|
|
|
pLogonHours - The logon hour range (in hours)
|
|
|
|
LogonHourBitMask - The converted logon hour bit mask. Each bit represents
|
|
an hour. There are total 21 bytes (21*8 bits in this
|
|
argument, which represents a week (7 * 24 = 21 * 8).
|
|
Return value:
|
|
|
|
None
|
|
-- */
|
|
{ PSCE_LOGON_HOUR pTemp;
|
|
CHAR BitMask[3]={0,0,0};
|
|
ULONG j;
|
|
|
|
for ( pTemp=pLogonHours; pTemp != NULL; pTemp=pTemp->Next ) {
|
|
|
|
for (j=pTemp->Start; j<pTemp->End; j++)
|
|
BitMask[j / 8] |= 1 << (j % 8);
|
|
}
|
|
|
|
for ( j=0; j<7; j++ )
|
|
strncpy((CHAR *)&(LogonHourBitMask[j*3]), BitMask,3);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepConvertToSceLogonHour(
|
|
IN PUCHAR LogonHourBitMask,
|
|
OUT PSCE_LOGON_HOUR *pLogonHours
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine converted the logon hour bit mask (for example,
|
|
0001 1111 1111 1111 1000 0000 for one day) to SCE_LOGON_HOUR type,
|
|
which stores the logon hour range (start, end).
|
|
|
|
|
|
Arguments:
|
|
|
|
LogonHourBitMask - The logon hour bit mask to convert. Each bit represents
|
|
an hour. There are total 21 bytes (21*8 bits in this
|
|
argument, which represents a week (7 * 24 = 21 * 8).
|
|
|
|
pLogonHours - The logon hour range (in hours)
|
|
|
|
Return value:
|
|
|
|
None
|
|
-- */
|
|
{
|
|
BOOL findStart = TRUE;
|
|
DWORD i, j, rc=NO_ERROR;
|
|
DWORD start=0,
|
|
end=0;
|
|
LONG value;
|
|
|
|
PSCE_LOGON_HOUR pLogon=NULL;
|
|
|
|
if (pLogonHours == NULL )
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
|
|
for ( i=3; i<6; i++)
|
|
for ( j=0; j<8; j++) {
|
|
if ( findStart )
|
|
value = 1;
|
|
else
|
|
value = 0;
|
|
|
|
if ( (LogonHourBitMask[i] & (1 << j)) == value ) {
|
|
|
|
if ( findStart ) {
|
|
start = (i-3)*8 + j;
|
|
findStart = FALSE;
|
|
} else {
|
|
end = (i-3)*8 + j;
|
|
findStart = TRUE;
|
|
}
|
|
if ( findStart ) {
|
|
//
|
|
// find a pair
|
|
//
|
|
pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR));
|
|
if ( pLogon == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
return(rc);
|
|
}
|
|
pLogon->Start = start;
|
|
pLogon->End = end;
|
|
pLogon->Next = *pLogonHours;
|
|
*pLogonHours = pLogon;
|
|
pLogon = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( findStart == FALSE ) {
|
|
// find start but not end, which means end=24
|
|
end = 24;
|
|
pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR));
|
|
if ( pLogon == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
return(rc);
|
|
}
|
|
pLogon->Start = start;
|
|
pLogon->End = end;
|
|
pLogon->Next = *pLogonHours;
|
|
*pLogonHours = pLogon;
|
|
pLogon = NULL;
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ScepGetGroupsForAccount(
|
|
IN SAM_HANDLE DomainHandle,
|
|
IN SAM_HANDLE BuiltinDomainHandle,
|
|
IN SAM_HANDLE UserHandle,
|
|
IN PSID AccountSid,
|
|
OUT PSCE_NAME_LIST *GroupList
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine queries the user's group membership.
|
|
|
|
Arguments:
|
|
|
|
DomainHandle - The SAM handle of the SAM account domain
|
|
|
|
BuiltindomainHandle - The SAM builtin domain handle
|
|
|
|
UserHandle - The SAM account handle for the user
|
|
|
|
AccountSid - The SID for the user
|
|
|
|
GroupList - The list of groups the user belongs to
|
|
|
|
Return value:
|
|
|
|
NTSTATUS
|
|
|
|
-- */
|
|
{
|
|
NTSTATUS NtStatus=ERROR_SUCCESS;
|
|
|
|
ULONG GroupCount=0,
|
|
AliasCount=0;
|
|
PULONG Aliases=NULL;
|
|
PGROUP_MEMBERSHIP GroupAttributes=NULL;
|
|
PULONG GroupIds=NULL;
|
|
PUNICODE_STRING Names=NULL;
|
|
PSID_NAME_USE Use=NULL;
|
|
|
|
DWORD i;
|
|
|
|
|
|
NtStatus = SamGetGroupsForUser(
|
|
UserHandle,
|
|
&GroupAttributes,
|
|
&GroupCount
|
|
);
|
|
|
|
if ( GroupCount == 0 )
|
|
NtStatus = ERROR_SUCCESS;
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
goto Done;
|
|
|
|
//
|
|
// See what local groups the account belongs to.
|
|
// account domain
|
|
//
|
|
|
|
NtStatus = SamGetAliasMembership(
|
|
DomainHandle,
|
|
1,
|
|
&AccountSid,
|
|
&AliasCount,
|
|
&Aliases );
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
goto Done;
|
|
|
|
if ( AliasCount != 0 || GroupCount != 0 ) {
|
|
|
|
//
|
|
// process each group's name in account domain
|
|
//
|
|
|
|
GroupIds = (PULONG)ScepAlloc((UINT)0,
|
|
(GroupCount+AliasCount)*sizeof(ULONG));
|
|
|
|
if ( GroupIds == NULL ) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
for ( i=0; i<GroupCount; i++)
|
|
GroupIds[i] = GroupAttributes[i].RelativeId;
|
|
|
|
for ( i=0; i<AliasCount; i++)
|
|
GroupIds[i+GroupCount] = Aliases[i];
|
|
|
|
}
|
|
|
|
SamFreeMemory(GroupAttributes);
|
|
GroupAttributes = NULL;
|
|
|
|
SamFreeMemory(Aliases);
|
|
Aliases = NULL;
|
|
|
|
if ( AliasCount != 0 || GroupCount != 0 ) {
|
|
|
|
// lookup names
|
|
NtStatus = SamLookupIdsInDomain(
|
|
DomainHandle,
|
|
GroupCount+AliasCount,
|
|
GroupIds,
|
|
&Names,
|
|
&Use
|
|
);
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
goto Done;
|
|
}
|
|
|
|
for ( i=0; i<GroupCount+AliasCount; i++) {
|
|
if ( GroupIds[i] == DOMAIN_GROUP_RID_USERS )
|
|
continue;
|
|
switch (Use[i]) {
|
|
case SidTypeGroup:
|
|
case SidTypeAlias:
|
|
case SidTypeWellKnownGroup:
|
|
if ( ScepAddToNameList(GroupList, Names[i].Buffer, Names[i].Length/2) != NO_ERROR) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( GroupIds ) {
|
|
ScepFree(GroupIds);
|
|
GroupIds = NULL;
|
|
}
|
|
|
|
if ( Names ) {
|
|
SamFreeMemory(Names);
|
|
Names = NULL;
|
|
}
|
|
|
|
if ( Use ) {
|
|
SamFreeMemory(Use);
|
|
Use = NULL;
|
|
}
|
|
|
|
//
|
|
// check the builtin domain for alias membership
|
|
//
|
|
|
|
AliasCount=0;
|
|
NtStatus = SamGetAliasMembership(
|
|
BuiltinDomainHandle,
|
|
1,
|
|
&AccountSid,
|
|
&AliasCount,
|
|
&Aliases );
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
goto Done;
|
|
|
|
if ( AliasCount > 0 ) {
|
|
|
|
NtStatus = SamLookupIdsInDomain(
|
|
BuiltinDomainHandle,
|
|
AliasCount,
|
|
Aliases,
|
|
&Names,
|
|
&Use
|
|
);
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
goto Done;
|
|
}
|
|
|
|
for ( i=0; i<AliasCount; i++) {
|
|
if ( Aliases[i] == DOMAIN_GROUP_RID_USERS )
|
|
continue;
|
|
|
|
switch (Use[i]) {
|
|
case SidTypeGroup:
|
|
case SidTypeAlias:
|
|
case SidTypeWellKnownGroup:
|
|
if ( ScepAddToNameList(GroupList, Names[i].Buffer, Names[i].Length/2) != NO_ERROR) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( GroupAttributes != NULL )
|
|
SamFreeMemory(GroupAttributes);
|
|
|
|
if ( Aliases != NULL )
|
|
SamFreeMemory(Aliases);
|
|
|
|
if ( GroupIds != NULL )
|
|
ScepFree(GroupIds);
|
|
|
|
if ( Names != NULL )
|
|
SamFreeMemory(Names);
|
|
|
|
if ( Use != NULL )
|
|
SamFreeMemory(Use);
|
|
|
|
return(NtStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
ACCESS_MASK
|
|
ScepGetDesiredAccess(
|
|
IN SECURITY_OPEN_TYPE OpenType,
|
|
IN SECURITY_INFORMATION SecurityInfo
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Gets the access required to open object to be able to set or get the
|
|
specified security info.
|
|
|
|
Arguments:
|
|
|
|
OpenType - Flag indicating if the object is to be opened to read or
|
|
write the DACL
|
|
|
|
SecurityInfo - The Security information to read/write.
|
|
|
|
Return value:
|
|
|
|
Access mask
|
|
|
|
-- */
|
|
{
|
|
ACCESS_MASK DesiredAccess = 0;
|
|
|
|
if ( (SecurityInfo & OWNER_SECURITY_INFORMATION) ||
|
|
(SecurityInfo & GROUP_SECURITY_INFORMATION) )
|
|
{
|
|
switch (OpenType)
|
|
{
|
|
case READ_ACCESS_RIGHTS:
|
|
DesiredAccess |= READ_CONTROL;
|
|
break;
|
|
case WRITE_ACCESS_RIGHTS:
|
|
DesiredAccess |= WRITE_OWNER;
|
|
break;
|
|
case MODIFY_ACCESS_RIGHTS:
|
|
DesiredAccess |= READ_CONTROL | WRITE_OWNER;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SecurityInfo & DACL_SECURITY_INFORMATION)
|
|
{
|
|
switch (OpenType)
|
|
{
|
|
case READ_ACCESS_RIGHTS:
|
|
DesiredAccess |= READ_CONTROL;
|
|
break;
|
|
case WRITE_ACCESS_RIGHTS:
|
|
DesiredAccess |= WRITE_DAC;
|
|
break;
|
|
case MODIFY_ACCESS_RIGHTS:
|
|
DesiredAccess |= READ_CONTROL | WRITE_DAC;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SecurityInfo & SACL_SECURITY_INFORMATION)
|
|
{
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
}
|
|
|
|
return (DesiredAccess);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetProfileOneArea(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN DWORD dwAccountFormat,
|
|
OUT PSCE_PROFILE_INFO *ppInfoBuffer
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
A wrapper routine for GetDatabaseInfo except it get information
|
|
for one area at a call. This routine also logs the errors occur inside
|
|
GetSecrityProfileInfo
|
|
|
|
Arguments:
|
|
|
|
hProfile - Handle to a profile
|
|
|
|
ProfileType - The type of the profile
|
|
|
|
Area - The security area to read info from
|
|
|
|
ppInfoBuffer - output buffer for the info
|
|
|
|
Return value:
|
|
|
|
SCESTATUS returned from GetDatabaseInfo
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
PSCE_ERROR_LOG_INFO pErrlog=NULL;
|
|
|
|
|
|
rc = ScepGetDatabaseInfo(
|
|
hProfile,
|
|
ProfileType,
|
|
Area,
|
|
dwAccountFormat,
|
|
ppInfoBuffer,
|
|
&pErrlog
|
|
);
|
|
|
|
ScepLogWriteError( pErrlog, 1 );
|
|
ScepFreeErrorLog( pErrlog );
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetOneSection(
|
|
IN PSCECONTEXT hProfile,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR Name,
|
|
IN SCETYPE ProfileType,
|
|
OUT PVOID *ppInfo
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine reads information for one or more Area and logs errors to
|
|
the log file. This routine should be only used by the SCP engine and
|
|
the SAP engine.
|
|
|
|
Arguments:
|
|
|
|
hProfile - Handle to a profile
|
|
|
|
ProfileType - The type of the profile
|
|
|
|
Area - The security area to read info from
|
|
|
|
Subarea - The subarea to read info from
|
|
|
|
ppInfo - output buffer for the info
|
|
|
|
Return value:
|
|
|
|
SCESTATUS
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
PSCE_ERROR_LOG_INFO pErrlog=NULL;
|
|
|
|
if ( Name == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( Area == AREA_REGISTRY_SECURITY ||
|
|
Area == AREA_FILE_SECURITY ||
|
|
Area == AREA_DS_OBJECTS ) {
|
|
|
|
rc = ScepGetObjectChildren(
|
|
hProfile,
|
|
ProfileType,
|
|
Area,
|
|
Name,
|
|
SCE_ALL_CHILDREN,
|
|
ppInfo,
|
|
&pErrlog
|
|
);
|
|
} else {
|
|
rc = ScepGetUserSection(
|
|
hProfile,
|
|
ProfileType,
|
|
Name,
|
|
ppInfo,
|
|
&pErrlog
|
|
);
|
|
}
|
|
|
|
ScepLogWriteError( pErrlog, 1 );
|
|
ScepFreeErrorLog( pErrlog );
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ScepGetUserAccessAddress(
|
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN PSID AccountSid,
|
|
OUT PACCESS_MASK *pUserAccess,
|
|
OUT PACCESS_MASK *pEveryone
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
PACL pAcl;
|
|
BOOLEAN aclPresent, tFlag;
|
|
DWORD i;
|
|
PVOID pAce;
|
|
PSID pSid;
|
|
ACCESS_MASK access;
|
|
SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
|
|
PSID EveryoneSid=NULL;
|
|
|
|
|
|
if ( AccountSid == NULL || pUserAccess == NULL || pEveryone == NULL )
|
|
return(STATUS_INVALID_PARAMETER);
|
|
|
|
*pUserAccess = NULL;
|
|
*pEveryone = NULL;
|
|
|
|
if ( pSecurityDescriptor == NULL )
|
|
return(STATUS_SUCCESS);
|
|
|
|
NtStatus = RtlGetDaclSecurityDescriptor(
|
|
pSecurityDescriptor,
|
|
&aclPresent,
|
|
&pAcl,
|
|
&tFlag);
|
|
|
|
if ( NT_SUCCESS(NtStatus) )
|
|
|
|
NtStatus = RtlAllocateAndInitializeSid(
|
|
&WorldAuth,
|
|
1,
|
|
SECURITY_CREATOR_OWNER_RID,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&EveryoneSid );
|
|
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
if ( pAcl != NULL && aclPresent ) {
|
|
|
|
for ( i=0; i < pAcl->AceCount; i++) {
|
|
NtStatus = RtlGetAce( pAcl, i, &pAce );
|
|
if ( !NT_SUCCESS( NtStatus ) )
|
|
break;
|
|
|
|
access = 0;
|
|
pSid = NULL;
|
|
|
|
switch ( ((PACE_HEADER)pAce)->AceType ) {
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
pSid = (PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
|
|
access = ((PACCESS_ALLOWED_ACE)pAce)->Mask;
|
|
|
|
if ( EqualSid( AccountSid, pSid ) )
|
|
*pUserAccess = &(((PACCESS_ALLOWED_ACE)pAce)->Mask);
|
|
|
|
else if ( EqualSid( EveryoneSid, pSid) )
|
|
*pEveryone = &(((PACCESS_ALLOWED_ACE)pAce)->Mask);
|
|
|
|
break;
|
|
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
// do not look for denied ace type because it is not used here
|
|
// pSid = (PSID)&((PACCESS_DENIED_ACE)pAce)->SidStart;
|
|
// access = ((PACCESS_DENIED_ACE)pAce)->Mask;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( *pUserAccess != NULL && *pEveryone != NULL )
|
|
// stop the loop because both are found
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// free EveryoneSid
|
|
//
|
|
if (EveryoneSid) {
|
|
RtlFreeSid(EveryoneSid);
|
|
EveryoneSid = NULL;
|
|
}
|
|
return(NtStatus);
|
|
}
|
|
|
|
BOOL
|
|
ScepLastBackSlash(
|
|
IN PWSTR Name
|
|
)
|
|
{
|
|
if (Name == NULL )
|
|
return(FALSE);
|
|
|
|
if ( Name[wcslen(Name)-1] == L'\\')
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepGetUsersHomeDirectory(
|
|
IN UNICODE_STRING AssignedHomeDir,
|
|
IN PWSTR UserProfileName,
|
|
OUT PWSTR *UserHomeDir
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine gets user's default home directory. The home directory is
|
|
determined 1) if it is assigned in the user's object (user profile), 2)
|
|
if there is a HomePath environment variable defined for the user, and
|
|
3). Harcoded.
|
|
|
|
Arguments:
|
|
|
|
AssignedHomeDir - The home directory explicitly assigned in the user's
|
|
object.
|
|
|
|
UserProfileName - The user's environment profile name
|
|
|
|
UserHomeDir - The returned home directory for the user
|
|
|
|
Return Value:
|
|
|
|
Win32 error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32rc=NO_ERROR;
|
|
PWSTR StrValue=NULL;
|
|
|
|
PWSTR SystemRoot=NULL;
|
|
DWORD DirSize=0;
|
|
|
|
*UserHomeDir = NULL;
|
|
|
|
//
|
|
// if there is a home directory assigned in the user profile, use it.
|
|
//
|
|
if ( AssignedHomeDir.Length > 0 && AssignedHomeDir.Buffer != NULL ) {
|
|
*UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, AssignedHomeDir.Length+2);
|
|
if ( *UserHomeDir == NULL )
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
wcsncpy(*UserHomeDir, AssignedHomeDir.Buffer, AssignedHomeDir.Length/2);
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
//
|
|
// Home directory is NULL in user profile, the HomePath environment
|
|
// is searched.
|
|
//
|
|
|
|
Win32rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR );
|
|
if ( Win32rc != NO_ERROR ) {
|
|
ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%");
|
|
return(Win32rc);
|
|
}
|
|
|
|
Win32rc = ScepGetEnvVarsFromProfile(
|
|
UserProfileName,
|
|
L"HomePath",
|
|
NULL,
|
|
&StrValue
|
|
);
|
|
|
|
if ( Win32rc == NO_ERROR && StrValue != NULL ) {
|
|
*UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (wcslen(StrValue)+3)*sizeof(WCHAR));
|
|
if ( *UserHomeDir == NULL )
|
|
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
else {
|
|
swprintf(*UserHomeDir+1, L":%s", StrValue);
|
|
**UserHomeDir = SystemRoot[0];
|
|
}
|
|
} else
|
|
Win32rc = NO_ERROR; // do not care if can't get environment variable's value
|
|
|
|
if ( SystemRoot != NULL )
|
|
ScepFree(SystemRoot);
|
|
|
|
if ( StrValue != NULL )
|
|
ScepFree( StrValue );
|
|
|
|
return(Win32rc);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepGetEnvVarsFromProfile(
|
|
IN PWSTR UserProfileName,
|
|
IN PCWSTR VarName1,
|
|
IN PCWSTR VarName2 OPTIONAL,
|
|
OUT PWSTR *StrValue
|
|
)
|
|
{
|
|
DWORD rc;
|
|
DWORD RegType;
|
|
|
|
|
|
rc = SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, NULL);
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
rc = RegLoadKey(HKEY_USERS, L"TEMP", UserProfileName);
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
rc = ScepRegQueryValue(
|
|
HKEY_USERS,
|
|
L"TEMP\\Environment",
|
|
VarName1,
|
|
(PVOID *)StrValue,
|
|
&RegType,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != ERROR_SUCCESS && VarName2 != NULL ) {
|
|
rc = ScepRegQueryValue(
|
|
HKEY_USERS,
|
|
L"TEMP\\Environment",
|
|
VarName2,
|
|
(PVOID *)StrValue,
|
|
&RegType,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
RegUnLoadKey(HKEY_USERS, L"TEMP");
|
|
|
|
} else { //if ( rc == ERROR_ALREADY_IN_USE) {
|
|
//
|
|
// this profile already in use. Open the one in HKEY_CURRENT_USER
|
|
//
|
|
rc = ScepRegQueryValue(
|
|
HKEY_CURRENT_USER,
|
|
L"Environment",
|
|
VarName1,
|
|
(PVOID *)StrValue,
|
|
&RegType,
|
|
NULL
|
|
);
|
|
|
|
if ( rc != ERROR_SUCCESS && VarName2 != NULL ) {
|
|
rc = ScepRegQueryValue(
|
|
HKEY_CURRENT_USER,
|
|
L"Environment",
|
|
VarName2,
|
|
(PVOID *)StrValue,
|
|
&RegType,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
}
|
|
SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, FALSE, NULL);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepGetUsersTempDirectory(
|
|
IN PWSTR UserProfileName,
|
|
OUT PWSTR *UserTempDir
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine returns the user's temp directory. Temp directory for a
|
|
user is determined 1) environment variable "TEMP" or "TMP" defined
|
|
in the user's environment profile, or 2) Harcoded to %systemDrive%\TEMP
|
|
|
|
Arguments:
|
|
|
|
UserProfileName - The user's environment profile name
|
|
|
|
UserTempDir - The returned temp directory for the user
|
|
|
|
Return Value:
|
|
|
|
Win32 error code
|
|
|
|
--*/
|
|
{
|
|
DWORD rc=NO_ERROR;
|
|
PWSTR StrValue=NULL;
|
|
|
|
PWSTR SystemRoot=NULL;
|
|
DWORD DirSize=0;
|
|
|
|
|
|
//
|
|
// query the TEMP/TMP environment variable(s)
|
|
//
|
|
if ( UserProfileName != NULL ) {
|
|
ScepGetEnvVarsFromProfile(
|
|
UserProfileName,
|
|
L"TEMP",
|
|
L"TMP",
|
|
&StrValue
|
|
);
|
|
}
|
|
if ( StrValue != NULL ) {
|
|
//
|
|
// find the setting for temp dir
|
|
//
|
|
|
|
if ( wcsstr(_wcsupr(StrValue), L"%") != NULL ) {
|
|
|
|
rc = ScepTranslateFileDirName( StrValue, UserTempDir );
|
|
}
|
|
if ( rc == NO_ERROR ) {
|
|
ScepFree(StrValue);
|
|
} else
|
|
*UserTempDir = StrValue;
|
|
|
|
StrValue = NULL;
|
|
|
|
} else {
|
|
//
|
|
// hardcoded to %SystemDrive%\TEMP
|
|
//
|
|
rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR );
|
|
if ( rc != NO_ERROR ) {
|
|
ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%");
|
|
return(rc);
|
|
}
|
|
*UserTempDir = (PWSTR)ScepAlloc( 0, 8*sizeof(WCHAR));
|
|
if ( *UserTempDir == NULL )
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
else {
|
|
swprintf(*UserTempDir+1, L":\\TEMP");
|
|
**UserTempDir = SystemRoot[0];
|
|
}
|
|
}
|
|
|
|
if (SystemRoot != NULL )
|
|
ScepFree(SystemRoot);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetRegKeyCase(
|
|
IN PWSTR ObjName,
|
|
IN DWORD BufOffset,
|
|
IN DWORD BufLen
|
|
)
|
|
{
|
|
DWORD Win32rc;
|
|
HKEY hKey=NULL;
|
|
|
|
PWSTR Buffer=NULL;
|
|
TCHAR Buffer1[MAX_PATH];
|
|
DWORD BufSize, index;
|
|
FILETIME LastWriteTime;
|
|
|
|
|
|
if ( BufOffset <= 0 || BufLen <= 0 ) {
|
|
_wcsupr(ObjName);
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
Buffer = (PWSTR)ScepAlloc(LMEM_ZEROINIT, BufOffset*sizeof(WCHAR));
|
|
|
|
if ( Buffer != NULL ) {
|
|
|
|
wcsncpy(Buffer, ObjName, BufOffset-1);
|
|
|
|
Win32rc = ScepOpenRegistryObject(
|
|
SE_REGISTRY_KEY,
|
|
Buffer,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
if ( Win32rc == NO_ERROR ) {
|
|
|
|
index = 0;
|
|
//
|
|
// enumerate all subkeys of the key
|
|
//
|
|
do {
|
|
memset(Buffer1, '\0', MAX_PATH*sizeof(WCHAR));
|
|
BufSize = MAX_PATH;
|
|
|
|
Win32rc = RegEnumKeyEx(hKey,
|
|
index,
|
|
Buffer1,
|
|
&BufSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&LastWriteTime);
|
|
|
|
if ( Win32rc == ERROR_SUCCESS ) {
|
|
index++;
|
|
//
|
|
// find if the subkey matches the object name
|
|
//
|
|
if ( _wcsicmp(ObjName+BufOffset, Buffer1) == 0 )
|
|
break;
|
|
}
|
|
|
|
} while ( Win32rc != ERROR_NO_MORE_ITEMS );
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
if ( Win32rc == ERROR_SUCCESS ) {
|
|
//
|
|
// find it
|
|
//
|
|
if ( BufSize > BufLen )
|
|
BufSize = BufLen;
|
|
|
|
wcsncpy(ObjName+BufOffset, Buffer1, BufSize);
|
|
*(ObjName+BufOffset+BufSize) = L'\0';
|
|
|
|
} else if ( Win32rc == ERROR_NO_MORE_ITEMS) {
|
|
//
|
|
// does not find it
|
|
//
|
|
Win32rc = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
}
|
|
ScepFree(Buffer);
|
|
|
|
} else
|
|
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
if ( Win32rc != NO_ERROR ) {
|
|
//
|
|
// convert everything to uppercase
|
|
//
|
|
_wcsupr(ObjName+BufOffset);
|
|
}
|
|
|
|
return(ScepDosErrorToSceStatus(Win32rc));
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetFileCase(
|
|
IN PWSTR ObjName,
|
|
IN DWORD BufOffset,
|
|
IN DWORD BufLen
|
|
)
|
|
{
|
|
|
|
intptr_t hFile;
|
|
struct _wfinddata_t FileInfo;
|
|
|
|
hFile = _wfindfirst(ObjName, &FileInfo);
|
|
|
|
if ( hFile != -1 ) {
|
|
|
|
wcsncpy(ObjName+BufOffset, FileInfo.name, BufLen);
|
|
|
|
_findclose(hFile);
|
|
|
|
} else
|
|
return(ScepDosErrorToSceStatus(GetLastError()));
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetGroupCase(
|
|
IN OUT PWSTR GroupName,
|
|
IN DWORD Length
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
SAM_HANDLE ServerHandle=NULL,
|
|
DomainHandle=NULL,
|
|
BuiltinDomainHandle=NULL,
|
|
ThisDomain=NULL,
|
|
GroupHandle=NULL;
|
|
|
|
PSID DomainSid=NULL,
|
|
BuiltinDomainSid=NULL;
|
|
UNICODE_STRING Name;
|
|
PULONG GrpId=NULL;
|
|
PSID_NAME_USE GrpUse=NULL;
|
|
PVOID pNameInfo=NULL;
|
|
|
|
NtStatus = ScepOpenSamDomain(
|
|
SAM_SERVER_READ | SAM_SERVER_EXECUTE,
|
|
DOMAIN_READ | DOMAIN_EXECUTE,
|
|
&ServerHandle,
|
|
&DomainHandle,
|
|
&DomainSid,
|
|
&BuiltinDomainHandle,
|
|
&BuiltinDomainSid
|
|
);
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
RtlInitUnicodeString(&Name, GroupName);
|
|
|
|
NtStatus = SamLookupNamesInDomain(
|
|
DomainHandle,
|
|
1,
|
|
&Name,
|
|
&GrpId,
|
|
&GrpUse
|
|
);
|
|
ThisDomain = DomainHandle;
|
|
|
|
if ( NtStatus == STATUS_NONE_MAPPED ) {
|
|
//
|
|
// not found in account domain. Lookup in the builtin domain
|
|
//
|
|
NtStatus = SamLookupNamesInDomain(
|
|
BuiltinDomainHandle,
|
|
1,
|
|
&Name,
|
|
&GrpId,
|
|
&GrpUse
|
|
);
|
|
ThisDomain=BuiltinDomainHandle;
|
|
}
|
|
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
switch ( GrpUse[0] ) {
|
|
case SidTypeGroup:
|
|
NtStatus = SamOpenGroup(
|
|
ThisDomain,
|
|
GROUP_READ | GROUP_EXECUTE,
|
|
GrpId[0],
|
|
&GroupHandle
|
|
);
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
NtStatus = SamQueryInformationGroup(
|
|
GroupHandle,
|
|
GroupNameInformation,
|
|
&pNameInfo
|
|
);
|
|
}
|
|
|
|
break;
|
|
case SidTypeAlias:
|
|
NtStatus = SamOpenAlias(
|
|
ThisDomain,
|
|
ALIAS_READ | ALIAS_EXECUTE,
|
|
GrpId[0],
|
|
&GroupHandle
|
|
);
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
|
|
NtStatus = SamQueryInformationAlias(
|
|
GroupHandle,
|
|
AliasNameInformation,
|
|
&pNameInfo
|
|
);
|
|
}
|
|
break;
|
|
default:
|
|
NtStatus = STATUS_NONE_MAPPED;
|
|
break;
|
|
}
|
|
|
|
if ( NT_SUCCESS(NtStatus) ) {
|
|
//
|
|
// get name information
|
|
//
|
|
if ( ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer != NULL &&
|
|
((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length > 0 ) {
|
|
|
|
if ( Length > (DWORD)(((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2) ) {
|
|
|
|
wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer,
|
|
((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2);
|
|
} else {
|
|
wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer,
|
|
Length);
|
|
}
|
|
|
|
} else
|
|
NtStatus = STATUS_NONE_MAPPED;
|
|
|
|
SamFreeMemory(pNameInfo);
|
|
}
|
|
|
|
if (GroupHandle)
|
|
SamCloseHandle(GroupHandle);
|
|
|
|
SamFreeMemory(GrpId);
|
|
SamFreeMemory(GrpUse);
|
|
}
|
|
SamCloseHandle( DomainHandle );
|
|
SamCloseHandle( BuiltinDomainHandle );
|
|
SamCloseHandle( ServerHandle );
|
|
|
|
SamFreeMemory(DomainSid);
|
|
RtlFreeSid(BuiltinDomainSid);
|
|
}
|
|
|
|
return(ScepDosErrorToSceStatus( RtlNtStatusToDosError(NtStatus) ));
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ScepPrintSecurityDescriptor(
|
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN BOOL ToDumpSD
|
|
)
|
|
{
|
|
if (pSecurityDescriptor != NULL) {
|
|
|
|
if ( ToDumpSD )
|
|
DumpSECURITY_DESCRIPTOR(pSecurityDescriptor);
|
|
else
|
|
printf("Security Descriptor\n");
|
|
}
|
|
}
|
|
|
|
|