|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
srvutil.cpp
Abstract:
Server Service attachment APIs
Author:
Jin Huang (jinhuang) 23-Jun-1997
Revision History:
jinhuang 23-Jan-1998 splitted to client-server --*/ #include "serverp.h"
#include "srvutil.h"
#include "infp.h"
#include "pfp.h"
#include <io.h>
#pragma hdrstop
DWORD Thread gMaxRegTicks=0; DWORD Thread gMaxFileTicks=0; DWORD Thread gMaxDsTicks=0; WCHAR Thread theAcctDomName[MAX_PATH+1]; WCHAR Thread ComputerName[MAX_COMPUTERNAME_LENGTH+1]; CHAR Thread sidAuthBuf[32]; CHAR Thread sidBuiltinBuf[32]; DWORD Thread t_pebSize=0; LPVOID Thread t_pebClient=NULL;
SCESTATUS ScepQueryInfTicks( IN PWSTR TemplateName, IN AREA_INFORMATION Area, OUT PDWORD pTotalTicks );
SCESTATUS ScepGetObjectCount( IN PSCECONTEXT Context, IN PCWSTR SectionName, IN BOOL bPolicyProp, OUT PDWORD pTotalTicks );
LPTSTR ScepSearchClientEnv( IN LPTSTR varName, IN DWORD dwSize );
//
// implementations
//
SCESTATUS ScepGetTotalTicks( IN PCWSTR TemplateName, IN PSCECONTEXT Context, IN AREA_INFORMATION Area, IN SCEFLAGTYPE nFlag, OUT PDWORD pTotalTicks ) /*
Routine Description:
Retrieve the total count of objects from the inf template and/or the database for the area specified.
Arguments:
TemplateName - the INF template Name
Context - the database context
Area - the security area
nFlag - the flag to indicate operation which determines where the count is retrieved:
SCE_FLAG_CONFIG SCE_FLAG_CONFIG_APPEND SCE_FLAG_ANALYZE SCE_FLAG_ANALYZE_APPEND
pTotalTicks - the output count
Return Value:
SCE Status */ { if ( pTotalTicks == NULL || ( NULL == TemplateName && NULL == Context) ) {
return(SCESTATUS_INVALID_PARAMETER); }
SCESTATUS rc=SCESTATUS_SUCCESS; DWORD nTicks=0;
*pTotalTicks = 0; gMaxRegTicks=0; gMaxFileTicks=0; gMaxDsTicks=0;
if ( Area & (AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY) ) { // |
// AREA_DS_OBJECTS) ) {
switch ( nFlag ) { case SCE_FLAG_CONFIG: case SCE_FLAG_CONFIG_APPEND: case SCE_FLAG_CONFIG_SCP: case SCE_FLAG_CONFIG_SCP_APPEND:
if ( TemplateName != NULL ) {
//
// use the template if there is any
//
rc = ScepQueryInfTicks( (LPTSTR)TemplateName, Area & (AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY), // |
// AREA_DS_OBJECTS),
pTotalTicks ); } if ( Context != NULL && (nFlag == SCE_FLAG_CONFIG_APPEND || nFlag == SCE_FLAG_CONFIG_SCP_APPEND || TemplateName == NULL) ) {
//
// use the existing database
//
if ( Area & AREA_REGISTRY_SECURITY ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szRegistryKeys, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxRegTicks += nTicks; *pTotalTicks += nTicks; } } if ( rc == SCESTATUS_SUCCESS && (Area & AREA_FILE_SECURITY) ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szFileSecurity, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxFileTicks += nTicks; *pTotalTicks += nTicks; } } #if 0
if ( rc == SCESTATUS_SUCCESS && (Area & AREA_DS_OBJECTS) ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szDSSecurity, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxDsTicks += nTicks; *pTotalTicks += nTicks; } } #endif
}
break; case SCE_FLAG_ANALYZE: case SCE_FLAG_ANALYZE_APPEND:
if ( Context != NULL ) { //
// use the existing database
//
if ( Area & AREA_REGISTRY_SECURITY ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szRegistryKeys, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxRegTicks += nTicks; *pTotalTicks += nTicks; } } if ( rc == SCESTATUS_SUCCESS && Area & AREA_FILE_SECURITY ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szFileSecurity, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxFileTicks += nTicks; *pTotalTicks += nTicks; } } #if 0
if ( rc == SCESTATUS_SUCCESS && Area & AREA_DS_OBJECTS ) {
nTicks = 0; rc = ScepGetObjectCount(Context, szDSSecurity, (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE, &nTicks); if ( SCESTATUS_SUCCESS == rc ) { gMaxDsTicks += nTicks; *pTotalTicks += nTicks; } } #endif
}
if ( rc == SCESTATUS_SUCCESS && TemplateName != NULL && (nFlag == SCE_FLAG_ANALYZE_APPEND || Context == NULL) ) {
//
// get handle in template
//
DWORD nTempTicks=0;
rc = ScepQueryInfTicks( (LPTSTR)TemplateName, Area & (AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY), // |
// AREA_DS_OBJECTS),
&nTempTicks ); if ( rc == SCESTATUS_SUCCESS ) { *pTotalTicks += nTempTicks; } }
break; default: return SCESTATUS_INVALID_PARAMETER; } }
if ( rc == SCESTATUS_SUCCESS ) {
if ( Area & AREA_SECURITY_POLICY ) *pTotalTicks += TICKS_SECURITY_POLICY_DS + TICKS_SPECIFIC_POLICIES;
if ( Area & AREA_GROUP_MEMBERSHIP ) *pTotalTicks += TICKS_GROUPS;
if ( Area & AREA_PRIVILEGES ) *pTotalTicks += TICKS_PRIVILEGE;
if ( Area & AREA_SYSTEM_SERVICE ) *pTotalTicks += TICKS_GENERAL_SERVICES + TICKS_SPECIFIC_SERVICES; /*
if ( *pTotalTicks ) { *pTotalTicks += 10; // for jet engine initialization
} */ }
return(rc);
}
SCESTATUS ScepQueryInfTicks( IN PWSTR TemplateName, IN AREA_INFORMATION Area, OUT PDWORD pTotalTicks ) /*
Routine Description:
Query total number of objects in the inf template for the specified area.
Arguments:
Return:
*/ { LONG Count=0; HINF InfHandle;
SCESTATUS rc = SceInfpOpenProfile( TemplateName, &InfHandle );
if ( rc == SCESTATUS_SUCCESS ) {
if ( Area & AREA_REGISTRY_SECURITY ) {
Count = SetupGetLineCount(InfHandle, szRegistryKeys); gMaxRegTicks += Count;
} if ( Area & AREA_FILE_SECURITY ) {
Count += SetupGetLineCount(InfHandle, szFileSecurity); gMaxFileTicks += Count; } #if 0
if ( Area & AREA_DS_OBJECTS ) {
Count += SetupGetLineCount(InfHandle, szDSSecurity); gMaxDsTicks += Count; } #endif
SceInfpCloseProfile(InfHandle); }
*pTotalTicks = Count;
return(rc); }
SCESTATUS ScepGetObjectCount( IN PSCECONTEXT Context, IN PCWSTR SectionName, IN BOOL bPolicyProp, OUT PDWORD pTotalTicks ) { if ( Context == NULL || SectionName == NULL || pTotalTicks == NULL ) {
return(SCESTATUS_INVALID_PARAMETER); }
PSCESECTION hSection=NULL; SCESTATUS rc; DWORD count=0;
rc = ScepOpenSectionForName( Context, bPolicyProp ? SCE_ENGINE_SCP : SCE_ENGINE_SMP, SectionName, &hSection );
if ( rc == SCESTATUS_SUCCESS ) {
rc = SceJetGetLineCount( hSection, NULL, FALSE, &count );
if ( rc == SCESTATUS_SUCCESS ) *pTotalTicks += count;
SceJetCloseSection( &hSection, TRUE); }
if ( SCESTATUS_RECORD_NOT_FOUND == rc) rc = SCESTATUS_SUCCESS;
return(rc); }
BOOL ScepIsEngineRecovering() { TCHAR TempFileName[MAX_PATH]; PWSTR SysRoot=NULL; DWORD SysLen; DWORD rc; BOOL bFindIt=FALSE;
SysLen = 0; rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
if ( rc == NO_ERROR && SysRoot != NULL ) {
swprintf(TempFileName, L"%s\\Security\\tmp.edb", SysRoot); TempFileName[MAX_PATH-1] = L'\0';
if ( 0xFFFFFFFF != GetFileAttributes(TempFileName) ) {
bFindIt = TRUE; }
ScepFree(SysRoot);
}
return bFindIt;
}
SCESTATUS ScepSaveAndOffAuditing( OUT PPOLICY_AUDIT_EVENTS_INFO *ppAuditEvent, IN BOOL bTurnOffAuditing, IN LSA_HANDLE PolicyHandle OPTIONAL ) { LSA_HANDLE lsaHandle=NULL; NTSTATUS status; SCESTATUS rc; POLICY_AUDIT_EVENT_OPTIONS lSaveAudit;
//
// open Lsa policy for read/write
//
if ( PolicyHandle == NULL ) {
ACCESS_MASK access=0;
if ( bTurnOffAuditing ) { access = POLICY_SET_AUDIT_REQUIREMENTS | POLICY_AUDIT_LOG_ADMIN; }
status = ScepOpenLsaPolicy( POLICY_VIEW_AUDIT_INFORMATION | access, &lsaHandle, TRUE );
if (status != ERROR_SUCCESS) {
lsaHandle = NULL; rc = RtlNtStatusToDosError( status ); ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
return(ScepDosErrorToSceStatus(rc)); }
} else {
lsaHandle = PolicyHandle; } //
// Query audit event information
//
status = LsaQueryInformationPolicy( lsaHandle, PolicyAuditEventsInformation, (PVOID *)ppAuditEvent ); rc = RtlNtStatusToDosError( status );
if ( NT_SUCCESS( status ) && bTurnOffAuditing && (*ppAuditEvent)->AuditingMode ) {
//
// turn off object access auditing
//
if ( AuditCategoryObjectAccess < (*ppAuditEvent)->MaximumAuditEventCount ) { lSaveAudit = (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess]; (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = POLICY_AUDIT_EVENT_NONE;
status = LsaSetInformationPolicy( lsaHandle, PolicyAuditEventsInformation, (PVOID)(*ppAuditEvent) );
//
// restore the object access auditing mode
//
(*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = lSaveAudit;
}
rc = RtlNtStatusToDosError( status );
if ( rc == NO_ERROR ) ScepLogOutput3( 2, 0, SCEDLL_EVENT_IS_OFF); else ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
} else if ( rc != NO_ERROR) ScepLogOutput3( 1, rc, SCEDLL_ERROR_QUERY_EVENT_AUDITING);
//
// free LSA handle if it's opened in this function
//
if ( lsaHandle && (PolicyHandle == NULL) ) LsaClose( lsaHandle );
return(ScepDosErrorToSceStatus(rc)); }
NTSTATUS ScepGetAccountExplicitRight( IN LSA_HANDLE PolicyHandle, IN PSID AccountSid, OUT PDWORD PrivilegeLowRights, OUT PDWORD PrivilegeHighRights ) /* ++
Routine Description:
This routine queries the explicitly assigned privilege/rights to a account (referenced by AccountSid) and stores in a DWORD type variable PrivilegeRights, in which each bit represents a privilege/right.
Arguments:
PolicyHandle - Lsa Policy Domain handle
AccountSid - The SID for the account
PrivilegeRights - Privilege/Rights of this account
Return value:
NTSTATUS -- */ { NTSTATUS NtStatus;
DWORD CurrentPrivLowRights=0, CurrentPrivHighRights=0; LONG index; PUNICODE_STRING UserRightEnum=NULL; ULONG i, cnt=0; LUID LuidValue;
//
// Enumerate user privilege/rights
//
NtStatus = LsaEnumerateAccountRights( PolicyHandle, AccountSid, &UserRightEnum, &cnt ); if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE || NtStatus == STATUS_OBJECT_NAME_NOT_FOUND ) {
NtStatus = ERROR_SUCCESS; goto Done; }
if ( !NT_SUCCESS( NtStatus) ) { ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus), SCEDLL_SAP_ERROR_ENUMERATE, L"LsaEnumerateAccountRights"); goto Done; }
if (UserRightEnum != NULL)
for ( i=0; i < cnt; i++) { if ( UserRightEnum[i].Length == 0 ) continue;
NtStatus = LsaLookupPrivilegeValue( PolicyHandle, &UserRightEnum[i], &LuidValue );
if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE ) { index = ScepLookupPrivByName( UserRightEnum[i].Buffer ); NtStatus = ERROR_SUCCESS; } else if ( NT_SUCCESS(NtStatus) ) { index = ScepLookupPrivByValue( LuidValue.LowPart ); } else index = -1;
if ( index == -1 ) {
//
// not found
//
NtStatus = STATUS_NOT_FOUND; ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus), SCEDLL_USERRIGHT_NOT_DEFINED); goto Done;
} else { if ( index < 32 ) { CurrentPrivLowRights |= (1 << index); } else { CurrentPrivHighRights |= (1 << (index-32) ); } } }
Done:
*PrivilegeLowRights = CurrentPrivLowRights; *PrivilegeHighRights = CurrentPrivHighRights;
if (UserRightEnum != NULL) LsaFreeMemory(UserRightEnum);
return (NtStatus); }
NTSTATUS ScepGetMemberListSids( IN PSID DomainSid, IN LSA_HANDLE PolicyHandle, IN PSCE_NAME_LIST pMembers, OUT PUNICODE_STRING *MemberNames, OUT PSID** Sids, OUT PULONG MemberCount ) /*
Routine Description:
Lookup each account in the name list pMembers and return the lookup information in the output buffer - MemberNames, Sids, MemberCount.
if an account can't be resolved, the corresponding SID will be empty.
*/ { NTSTATUS NtStatus=STATUS_SUCCESS; PSCE_NAME_LIST pUser;
PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL; PLSA_TRANSLATED_SID2 MemberSids=NULL; DWORD i; PSID DomainSidToUse=NULL; ULONG Cnt=0;
//
// build a UNICODE_STRING for the member list to look up
//
for (pUser=pMembers; pUser != NULL; pUser = pUser->Next) {
if ( pUser->Name == NULL ) { continue; } Cnt++; }
if ( Cnt > 0 ) {
*MemberNames = (PUNICODE_STRING)RtlAllocateHeap( RtlProcessHeap(), 0, Cnt * sizeof (UNICODE_STRING) ); if ( *MemberNames == NULL ) return(STATUS_NO_MEMORY); *Sids = (PSID *)ScepAlloc( LMEM_ZEROINIT, Cnt*sizeof(PSID)); if ( *Sids == NULL ) { NtStatus = STATUS_NO_MEMORY; goto Done; } //
// Lookup each UNICODE_STRING
//
for (pUser=pMembers, Cnt=0; pUser != NULL; pUser = pUser->Next) {
if ( pUser->Name == NULL ) { continue; }
RtlInitUnicodeString(&((*MemberNames)[Cnt]), pUser->Name); NtStatus = ScepLsaLookupNames2( PolicyHandle, LSA_LOOKUP_ISOLATED_AS_LOCAL, pUser->Name, &ReferencedDomains, &MemberSids );
if ( !NT_SUCCESS(NtStatus) ) { ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus), SCEDLL_ERROR_LOOKUP); goto Done; } DWORD SidLength=0; //
// translate the LSA_TRANSLATED_SID into PSID
//
if ( MemberSids && MemberSids[0].Use != SidTypeInvalid && MemberSids[0].Use != SidTypeUnknown && MemberSids[0].Sid != NULL ) {
SidLength = RtlLengthSid(MemberSids[0].Sid);
if ( ((*Sids)[Cnt] = (PSID) ScepAlloc( (UINT)0, SidLength)) == NULL ) { NtStatus = STATUS_NO_MEMORY; } else {
//
// copy the SID
// if failed, memory will be freed at cleanup
//
NtStatus = RtlCopySid( SidLength, (*Sids)[Cnt], MemberSids[0].Sid );
}
if ( !NT_SUCCESS(NtStatus) ) { goto Done; } }
if ( ReferencedDomains != NULL ){ LsaFreeMemory(ReferencedDomains); ReferencedDomains = NULL; }
if ( MemberSids != NULL ){ LsaFreeMemory(MemberSids); MemberSids = NULL; } Cnt++; } } *MemberCount = Cnt; Done:
if (!NT_SUCCESS(NtStatus) ) { if ( *Sids != NULL ) { for ( i=0; i<Cnt; i++ ) if ( (*Sids)[i] != NULL ) ScepFree( (*Sids)[i] ); ScepFree( *Sids ); *Sids = NULL; } if ( *MemberNames != NULL ) RtlFreeHeap(RtlProcessHeap(), 0, *MemberNames); *MemberNames = NULL; } if ( ReferencedDomains != NULL ) LsaFreeMemory(ReferencedDomains);
if ( MemberSids != NULL ) LsaFreeMemory(MemberSids);
return(NtStatus); }
DWORD ScepOpenFileObject( IN LPWSTR pObjectName, IN ACCESS_MASK AccessMask, OUT PHANDLE Handle ) /*++
Routine Description:
opens the specified file (or directory) object
Arguments:
pObjectName - the name of the file object
AccessMask - Desired Access
Handle - the just opened handle to the object
Return value:
Win32 errro code */ { NTSTATUS NtStatus; DWORD Status = ERROR_SUCCESS; OBJECT_ATTRIBUTES Attributes; IO_STATUS_BLOCK Isb; UNICODE_STRING FileName; PVOID FreeBuffer;
//
// cut and paste code from windows\base\advapi\security.c SetFileSecurityW
//
if (RtlDosPathNameToNtPathName_U( pObjectName, &FileName, NULL, NULL )) { FreeBuffer = FileName.Buffer;
InitializeObjectAttributes( &Attributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL );
NtStatus = NtOpenFile( Handle, AccessMask, &Attributes, &Isb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_REPARSE_POINT); // bug 635098: set permissions on junction point,
// not on target directory
if (!NT_SUCCESS(NtStatus)) { Status = RtlNtStatusToDosError(NtStatus); }
RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer); } else { Status = ERROR_INVALID_NAME; }
return(Status); }
DWORD ScepOpenRegistryObject( IN SE_OBJECT_TYPE ObjectType, IN LPWSTR pObjectName, IN ACCESS_MASK AccessMask, OUT PHKEY Handle ) /*++
Routine Description:
opens the specified registry key object
Arguments:
pObjectName - the name of the object
AccessMask - Desired access
Handle - the just opened handle to the object
Return value:
Win32 error code
Note: The code is cut/pasted from windows\base\accctrl\src\registry.cxx and modified --*/ { DWORD status=NO_ERROR; HKEY basekey; LPWSTR usename, basekeyname, keyname;
if (pObjectName) {
//
// save a copy of the name since we must crack it.
//
if (NULL != (usename = (LPWSTR)ScepAlloc( LMEM_ZEROINIT, (wcslen(pObjectName) + 1) * sizeof(WCHAR)))) {
wcscpy(usename,pObjectName);
basekeyname = usename; keyname = wcschr(usename, L'\\'); if (keyname != NULL) { *keyname = L'\0'; keyname++; }
if (0 == _wcsicmp(basekeyname, L"MACHINE")) { basekey = HKEY_LOCAL_MACHINE; } else if (0 == _wcsicmp(basekeyname, L"USERS")) { basekey = HKEY_USERS; } else if ( 0 == _wcsicmp(basekeyname, L"CLASSES_ROOT")) { basekey = HKEY_CLASSES_ROOT; } else { status = ERROR_INVALID_PARAMETER; }
if (NO_ERROR == status) { if ( keyname == NULL ) { *Handle = basekey; } else { //
// open the key
//
#ifdef _WIN64
if (ObjectType == SE_REGISTRY_WOW64_32KEY) { AccessMask |= KEY_WOW64_32KEY; } #endif
status = RegOpenKeyEx( basekey, keyname, 0 , AccessMask, Handle ); } } ScepFree(usename); } else { status = ERROR_NOT_ENOUGH_MEMORY; } } else { status = ERROR_INVALID_NAME; }
return(status); }
SCESTATUS ScepGetNameInLevel( IN PCWSTR ObjectFullName, IN DWORD Level, IN WCHAR Delim, OUT PWSTR Buffer, OUT PBOOL LastOne ) /* ++
Routine Description:
This routine parses a full path name and returns the component for the level. For example, a object name "c:\winnt\system32" will return c: for level 1, winnt for level 2, and system32 for level 3. This routine is used when add a object to the security tree.
Arguments:
ObjectFullName - The full path name of the object
Level - the level of component to return
Delim - the deliminator to look for
Buffer - The address of buffer for the component name
LastOne - Flag to indicate if the component is the last one
Return value:
SCESTATUS
-- */ { PWSTR pTemp, pStart; DWORD i;
if ( ObjectFullName == NULL ) return(SCESTATUS_INVALID_PARAMETER);
//
// loop through the object name to find the level
// if there is no such level, return INVALID_PARAMETER
//
pStart = (PWSTR)ObjectFullName; for ( i=0; i<Level; i++) {
pTemp = wcschr(pStart, Delim);
if ( pTemp == pStart ) { return(SCESTATUS_INVALID_PARAMETER); }
if ( i == Level-1 ) { //
// find the right level
//
if ( pTemp == NULL ) { wcscpy(Buffer, pStart); *LastOne = TRUE; } else { wcsncpy(Buffer, pStart, (size_t)(pTemp - pStart)); if ( *(pTemp+1) == L'\0' ) *LastOne = TRUE; else *LastOne = FALSE; } } else { if ( pTemp == NULL ) return(SCESTATUS_INVALID_PARAMETER); else pStart = pTemp + 1; } }
return(SCESTATUS_SUCCESS);
}
SCESTATUS ScepTranslateFileDirName( IN PWSTR oldFileName, OUT PWSTR *newFileName ) /* ++
Routine Description:
This routine converts a generic file/directory name to a real used name for the current system. The following generic file/directory names are handled: %systemroot% - Windows NT root directory (e.g., c:\winnt) %systemDirectory% - Windows NT system32 directory (e.g., c:\winnt\system32)
Arguments:
oldFileName - the file name to convert, which includes "%" to represent some directory names
newFileName - the real file name, in which the "%" name is replaced with the real directory name
Return values:
Win32 error code
-- */ { PWSTR pTemp=NULL, pStart, TmpBuf, szVar; DWORD rc=NO_ERROR; DWORD newFileSize, cSize; BOOL bContinue;
//
// match for %systemroot%
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%SYSTEMROOT%", SCE_FLAG_WINDOWS_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
//
// match for %systemdirectory%
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%SYSTEMDIRECTORY%", SCE_FLAG_SYSTEM_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
//
// match for systemdrive
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%SYSTEMDRIVE%", SCE_FLAG_WINDOWS_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
//
// match for boot drive
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%BOOTDRIVE%", SCE_FLAG_BOOT_DRIVE, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
rc = ERROR_SUCCESS; //
// search for environment variable in the current process
//
pStart = wcschr(oldFileName, L'%');
if ( pStart ) { pTemp = wcschr(pStart+1, L'%'); if ( pTemp ) {
bContinue = TRUE; //
// find a environment variable to translate
//
TmpBuf = (PWSTR)ScepAlloc(0, ((UINT)(pTemp-pStart))*sizeof(WCHAR)); if ( TmpBuf ) {
wcsncpy(TmpBuf, pStart+1, (size_t)(pTemp-pStart-1)); TmpBuf[pTemp-pStart-1] = L'\0';
//
// try search in the client environment block
//
szVar = ScepSearchClientEnv(TmpBuf, (DWORD)(pTemp-pStart-1));
if ( szVar ) {
// ScepLogOutput2(3,0,L"\tFind client env %s=%s", TmpBuf, szVar);
//
// find it in the client's environment block, use it
// get info in szVar
//
bContinue = FALSE;
newFileSize = ((DWORD)(pStart-oldFileName))+wcslen(szVar)+wcslen(pTemp+1)+1;
*newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
if (*newFileName ) { if ( pStart != oldFileName ) { wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName)); }
swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
} else { rc = ERROR_NOT_ENOUGH_MEMORY; } //
// DO NOT free szVar because it's a ref pointer to the env block
//
} else {
cSize = GetEnvironmentVariable( TmpBuf, NULL, 0 );
if ( cSize > 0 ) { //
// does not find it in the client environment block,
// find it in the current server process environment, use it
//
szVar = (PWSTR)ScepAlloc(0, (cSize+1)*sizeof(WCHAR));
if ( szVar ) { cSize = GetEnvironmentVariable(TmpBuf, szVar, cSize); if ( cSize > 0 ) { //
// get info in szVar
//
bContinue = FALSE;
newFileSize = ((DWORD)(pStart-oldFileName))+cSize+wcslen(pTemp+1)+1;
*newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
if (*newFileName ) { if ( pStart != oldFileName ) wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName));
swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
} else rc = ERROR_NOT_ENOUGH_MEMORY; }
ScepFree(szVar);
} else rc = ERROR_NOT_ENOUGH_MEMORY;
} }
ScepFree(TmpBuf);
} else rc = ERROR_NOT_ENOUGH_MEMORY;
if ( NO_ERROR != rc || !bContinue ) { //
// if errored, or do not continue
//
return(rc); }
//
// not found in environment blob,
// continue to search for DSDIT/DSLOG/SYSVOL in registry
//
if ( ProductType == NtProductLanManNt ) {
//
// search for DSDIT
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%DSDIT%", SCE_FLAG_DSDIT_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
//
// search for DSLOG
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%DSLOG%", SCE_FLAG_DSLOG_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
//
// search for SYSVOL
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%SYSVOL%", SCE_FLAG_SYSVOL_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) { return rc; }
}
//
// search for PROFILES
//
rc = ScepExpandEnvironmentVariable(oldFileName, L"%PROFILES%", SCE_FLAG_PROFILES_DIR, newFileName);
if ( rc != ERROR_FILE_NOT_FOUND ) {
return rc;
}
}
} //
// Otherwise, just copy the old name to a new buffer and return ERROR_PATH_NOT_FOUND
//
*newFileName = (PWSTR)ScepAlloc(0, (wcslen(oldFileName)+1)*sizeof(TCHAR));
if (*newFileName != NULL) { wcscpy(*newFileName, _wcsupr(oldFileName) ); rc = ERROR_PATH_NOT_FOUND; } else rc = ERROR_NOT_ENOUGH_MEMORY;
return(rc);
}
LPTSTR ScepSearchClientEnv( IN LPTSTR varName, IN DWORD dwSize ) { if ( !varName || dwSize == 0 || !t_pebClient || t_pebSize == 0 ) { return NULL; }
LPTSTR pTemp = (LPTSTR)t_pebClient;
while ( pTemp && *pTemp != L'\0' ) {
if ( _wcsnicmp(varName, pTemp, dwSize) == 0 && L'=' == *(pTemp+dwSize) ) { //
// find the variable
//
return pTemp+dwSize+1; break; } DWORD Len = wcslen(pTemp); pTemp += Len+1; }
return NULL; }
SCESTATUS ScepConvertLdapToJetIndexName( IN PWSTR TempName, OUT PWSTR *OutName ) { PWSTR pTemp1; PWSTR pTemp2; INT i,j; DWORD Len;
//
// Ldap name are in the format of CN=,DC=,...O=
// Jet Index requires names in the O=,...DC=,CN= format
//
// semicolon is converted to , and spaces are stripped out
//
if ( TempName == NULL || OutName == NULL ) { return(SCESTATUS_INVALID_PARAMETER); }
Len = wcslen(TempName); pTemp1 = TempName + Len - 1;
//
// skip the trailing spaces, commas, or semicolons
//
while ( pTemp1 >= TempName && (*pTemp1 == L' ' || *pTemp1 == L';' || *pTemp1 == L',') ) { pTemp1--; }
if ( pTemp1 < TempName ) { //
// all spaces or ; in the name
//
return(SCESTATUS_INVALID_PARAMETER); }
//
// allocate output buffer
//
*OutName = (PWSTR)ScepAlloc(0, ((UINT)(pTemp1-TempName+2))*sizeof(WCHAR)); if ( *OutName != NULL ) {
pTemp2 = *OutName;
while ( pTemp1 >= TempName ) {
//
// find the previous ; or ,
//
i = 0; while ( pTemp1-i >= TempName && *(pTemp1-i) != L',' && *(pTemp1-i) != L';' ) { i++; } //
// either reach the head, or a ; or , is encountered
//
i--; // i must be >= 0
//
// skip the leading spaces
//
j = 0; while ( *(pTemp1-i+j) == L' ' && j <= i ) { j++; } //
// copy the component
//
if ( i >= j ) {
if ( pTemp2 != *OutName ) { *pTemp2++ = L','; } wcsncpy(pTemp2, pTemp1-i+j, i-j+1); pTemp2 += (i-j+1);
} else { //
// all spaces
//
} pTemp1 -= (i+1); //
// skip the trailing spaces, commas, or semicolons
//
while ( pTemp1 >= TempName && (*pTemp1 == L' ' || *pTemp1 == L';' || *pTemp1 == L',') ) { pTemp1--; } } if ( pTemp2 == *OutName ) { //
// nothing got copied to the output buffer, WRONG!!!
//
ScepFree(*OutName); *OutName = NULL; return(SCESTATUS_INVALID_PARAMETER);
} else { //
// teminate the string
//
*pTemp2 = L'\0'; _wcslwr(*OutName);
return(SCESTATUS_SUCCESS); }
} else return(SCESTATUS_NOT_ENOUGH_RESOURCE); }
SCESTATUS ScepRestoreAuditing( IN PPOLICY_AUDIT_EVENTS_INFO auditEvent, IN LSA_HANDLE PolicyHandle OPTIONAL ) { LSA_HANDLE lsaHandle=NULL; NTSTATUS status; SCESTATUS rc;
if ( auditEvent == NULL ) return(SCESTATUS_INVALID_PARAMETER);
if ( PolicyHandle == NULL ) {
// open Lsa policy for read/write
status = ScepOpenLsaPolicy( POLICY_VIEW_AUDIT_INFORMATION | POLICY_SET_AUDIT_REQUIREMENTS | POLICY_AUDIT_LOG_ADMIN, &lsaHandle, TRUE );
if (status != ERROR_SUCCESS) {
lsaHandle = NULL; rc = RtlNtStatusToDosError( status ); ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
return(ScepDosErrorToSceStatus(rc)); }
} else { lsaHandle = PolicyHandle; }
// restore
status = LsaSetInformationPolicy( lsaHandle, PolicyAuditEventsInformation, (PVOID)(auditEvent) ); rc = RtlNtStatusToDosError( status );
if ( rc == NO_ERROR ) ScepLogOutput3( 2, 0, SCEDLL_EVENT_RESTORED); else ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
if ( lsaHandle && (lsaHandle != PolicyHandle) ) LsaClose( lsaHandle );
return(ScepDosErrorToSceStatus(rc));
}
DWORD ScepGetDefaultDatabase( IN LPCTSTR JetDbName OPTIONAL, IN DWORD LogOptions, IN LPCTSTR LogFileName OPTIONAL, OUT PBOOL pAdminLogon OPTIONAL, OUT PWSTR *ppDefDatabase ) /*
Routine Description:
Get the default SCE database for the current logged on user.
Arguments:
JetDbName - optional jet database name
LogOptions - options for the log, if there is any
LogFileName - the log file
pAdminLogon - output flag to indicate if administrative privileged user logged on
ppDefDatabase - the default database name
Return Value:
SCESTATUS */ { if ( !ppDefDatabase ) { return(ERROR_INVALID_PARAMETER); }
if ( LogOptions & SCE_DISABLE_LOG) {
ScepEnableDisableLog(FALSE); } else { ScepEnableDisableLog(TRUE); }
if ( LogOptions & SCE_DEBUG_LOG ) {
ScepSetVerboseLog(3);
} else if ( LogOptions & SCE_VERBOSE_LOG ) { //
// by default it's not verbose
//
ScepSetVerboseLog(2);
} else { ScepSetVerboseLog(-1); }
if ( ScepLogInitialize( LogFileName ) == ERROR_INVALID_NAME ) { ScepLogOutput3(1,0, SCEDLL_LOGFILE_INVALID, LogFileName ); }
DWORD rc=ERROR_SUCCESS; BOOL bAdminLogon=FALSE;
//
// determine if admin logs on
//
if ( pAdminLogon || !JetDbName || wcslen(JetDbName) < 1) {
rc = ScepIsAdminLoggedOn(&bAdminLogon, TRUE); if ( rc != NO_ERROR ) { ScepLogOutput3(1, rc, SCEDLL_UNKNOWN_LOGON_USER); }
if ( bAdminLogon ) { ScepLogOutput3(3, 0, SCEDLL_ADMIN_LOGON); } }
//
// find the databae name
//
if ( JetDbName && wcslen(JetDbName) > 0 ) {
*ppDefDatabase = (LPTSTR)JetDbName;
} else {
//
// query if the profile name (or the default ) in registry
//
rc = ScepGetProfileSetting( L"DefaultProfile", bAdminLogon, ppDefDatabase );
if ( rc != NO_ERROR || *ppDefDatabase == NULL ) { // return is Win32 error code
ScepLogOutput3(1,rc, SCEDLL_UNKNOWN_DBLOCATION); } }
if ( pAdminLogon ) { *pAdminLogon = bAdminLogon; }
return(rc);
}
BOOL ScepIsDomainLocal( IN PUNICODE_STRING pDomainName OPTIONAL ) /* ++
Routine Description:
This routine checks if the domain is on the local machine by comparing the domain name with the local machine's computer name.
Arguments:
pDomainName - the domain's name to check
Return Value:
TRUE if it is local
-- */ { NTSTATUS NtStatus; OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle; DWORD NameLen=MAX_COMPUTERNAME_LENGTH;
if ( pDomainName == NULL ) { //
// reset the buffer
//
ComputerName[0] = L'\0'; theAcctDomName[0] = L'\0'; sidBuiltinBuf[0] = '\0'; sidAuthBuf[0] = '\0';
return(TRUE); }
if ( pDomainName->Length <= 0 || pDomainName->Buffer == NULL ) return(TRUE);
if ( ComputerName[0] == L'\0' ) { memset(ComputerName, '\0', (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR)); GetComputerName(ComputerName, &NameLen); }
NameLen = wcslen(ComputerName);
if ( _wcsnicmp(ComputerName, pDomainName->Buffer, pDomainName->Length/2 ) == 0 && (LONG)NameLen == pDomainName->Length/2 ) return(TRUE);
if ( theAcctDomName[0] == L'\0' ) {
//
// query the current account domain name (for DC case)
//
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
//
// Open the policy database
//
InitializeObjectAttributes( &ObjectAttributes, NULL, // Name
0, // Attributes
NULL, // Root
NULL ); // Security Descriptor
NtStatus = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle ); if ( NT_SUCCESS(NtStatus) ) {
//
// Query the account domain information
//
NtStatus = LsaQueryInformationPolicy( PolicyHandle, PolicyAccountDomainInformation, (PVOID *)&PolicyAccountDomainInfo );
LsaClose( PolicyHandle ); }
if ( NT_SUCCESS(NtStatus) ) {
if ( PolicyAccountDomainInfo->DomainName.Buffer ) {
wcsncpy(theAcctDomName, PolicyAccountDomainInfo->DomainName.Buffer, PolicyAccountDomainInfo->DomainName.Length/2);
theAcctDomName[PolicyAccountDomainInfo->DomainName.Length/2] = L'\0';
} LsaFreeMemory(PolicyAccountDomainInfo); } }
NameLen = wcslen(theAcctDomName);
if ( _wcsnicmp(theAcctDomName, pDomainName->Buffer, pDomainName->Length/2) == 0 && (LONG)NameLen == pDomainName->Length/2 ) return(TRUE); else return(FALSE);
}
BOOL ScepIsDomainLocalBySid( PSID pSidLookup ) {
if ( pSidLookup == NULL ) { return FALSE; }
NTSTATUS NtStatus; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
//
// search for "NT Authority" name
//
if ( sidAuthBuf[0] == '\0' ) { // sid revision can't be 0
//
// build the NT authority sid
//
NtStatus = RtlInitializeSid( (PSID)sidAuthBuf, &NtAuthority, 0 );
if ( !NT_SUCCESS(NtStatus) ) {
sidAuthBuf[0] = '\0'; }
}
if ( sidAuthBuf[0] != '\0' && RtlEqualSid((PSID)sidAuthBuf, pSidLookup) ) {
return(TRUE); }
if ( sidBuiltinBuf[0] == '\0' ) { //
// build the builtin domain sid
//
NtStatus = RtlInitializeSid( (PSID)sidBuiltinBuf, &NtAuthority, 1 );
if ( NT_SUCCESS(NtStatus) ) {
*(RtlSubAuthoritySid((PSID)sidBuiltinBuf, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
} else {
sidBuiltinBuf[0] = '\0'; } }
if ( sidBuiltinBuf[0] != '\0' && RtlEqualSid((PSID)sidBuiltinBuf, pSidLookup) ) {
return(TRUE);
} else {
return(FALSE); }
}
NTSTATUS ScepAddAdministratorToThisList( IN SAM_HANDLE DomainHandle OPTIONAL, IN OUT PSCE_NAME_LIST *ppList ) { NTSTATUS NtStatus; SAM_HANDLE AccountDomain=NULL; SAM_HANDLE UserHandle=NULL; SAM_HANDLE ServerHandle=NULL; PSID DomainSid=NULL;
USER_NAME_INFORMATION *BufName=NULL; DOMAIN_NAME_INFORMATION *DomainName=NULL; PSCE_NAME_LIST pName=NULL;
if (!ppList ) { return(STATUS_INVALID_PARAMETER); }
if ( !DomainHandle ) {
//
// open the sam account domain
//
NtStatus = ScepOpenSamDomain( SAM_SERVER_ALL_ACCESS, MAXIMUM_ALLOWED, &ServerHandle, &AccountDomain, &DomainSid, NULL, NULL );
if ( !NT_SUCCESS(NtStatus) ) { ScepLogOutput3(1,RtlNtStatusToDosError(NtStatus), SCEDLL_ERROR_OPEN, L"SAM"); return(NtStatus); }
} else { AccountDomain = DomainHandle; }
//
// query account domain name
//
NtStatus = SamQueryInformationDomain( AccountDomain, DomainNameInformation, (PVOID *)&DomainName );
if ( NT_SUCCESS( NtStatus ) && DomainName && DomainName->DomainName.Length > 0 && DomainName->DomainName.Buffer ) {
NtStatus = SamOpenUser( AccountDomain, MAXIMUM_ALLOWED, DOMAIN_USER_RID_ADMIN, &UserHandle );
if ( NT_SUCCESS( NtStatus ) ) {
NtStatus = SamQueryInformationUser( UserHandle, UserNameInformation, (PVOID *)&BufName );
if ( NT_SUCCESS( NtStatus ) && BufName && BufName->UserName.Length > 0 && BufName->UserName.Buffer ) {
//
// add it to the members list, check duplicate
//
LONG NameLen; PWSTR pTemp;
for ( pName = *ppList; pName; pName=pName->Next ) {
if ( !pName->Name ) { continue; }
pTemp = wcschr( pName->Name, L'\\');
if ( pTemp ) { //
// has a domain prefix
//
pTemp++; } else { pTemp = pName->Name; } NameLen = wcslen(pTemp);
if ( NameLen == BufName->UserName.Length/2 && _wcsnicmp(pTemp, BufName->UserName.Buffer, BufName->UserName.Length/2) == 0 ) { //
// now, match the domain prefix
//
if ( pTemp != pName->Name ) {
if ( (pTemp-pName->Name-1) == DomainName->DomainName.Length/2 && _wcsnicmp(pName->Name, DomainName->DomainName.Buffer, DomainName->DomainName.Length/2) == 0 ) { break; } } else { break; } } }
if ( !pName ) {
//
// allocate a new node, if no resource, ignore the addition
//
pName = (PSCE_NAME_LIST)ScepAlloc( (UINT)0, sizeof(SCE_NAME_LIST));
if ( pName ) {
pName->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, BufName->UserName.Length+DomainName->DomainName.Length+4);
if ( pName->Name == NULL ) { ScepFree(pName); } else { //
// add the node to the front of the members list
//
NameLen = DomainName->DomainName.Length/2;
wcsncpy(pName->Name, DomainName->DomainName.Buffer, NameLen); pName->Name[NameLen] = L'\\';
wcsncpy(pName->Name+NameLen+1, BufName->UserName.Buffer, BufName->UserName.Length/2); pName->Name[NameLen+1+BufName->UserName.Length/2] = L'\0';
pName->Next = *ppList; *ppList = pName; } } } else { // else find it in the member list already, do nothing
}
}
//
// close the user handle
//
SamCloseHandle(UserHandle); UserHandle = NULL; } }
if ( AccountDomain != DomainHandle ) { //
// domain is opened
//
SamCloseHandle(AccountDomain);
SamCloseHandle( ServerHandle ); if ( DomainSid != NULL ) SamFreeMemory(DomainSid); }
if ( BufName ) { SamFreeMemory(BufName); }
if ( DomainName ) { SamFreeMemory(DomainName); }
return(NtStatus); }
DWORD ScepDatabaseAccessGranted( IN LPTSTR DatabaseName, IN DWORD DesiredAccess, IN BOOL bCreate ) {
if ( DatabaseName == NULL || DesiredAccess == 0 ) { return(SCESTATUS_INVALID_PARAMETER); }
HANDLE hToken = NULL, hNewToken = NULL; DWORD Win32rc = NO_ERROR;
//
// get current client token
//
if (!OpenThreadToken( GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE, TRUE, &hToken)) {
if(ERROR_NO_TOKEN == GetLastError()){
if(!OpenProcessToken( GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE, &hToken )){
return ( GetLastError() );
}
} else {
return( GetLastError() );
} }
//
// Duplicate it so it can be used for impersonation
//
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hNewToken)) { CloseHandle (hToken); return ( GetLastError() ); }
CloseHandle (hToken);
PSECURITY_DESCRIPTOR pCurrentSD=NULL; PRIVILEGE_SET PrivSet; DWORD PrivSetLength = sizeof(PRIVILEGE_SET); DWORD dwGrantedAccess; BOOL bAccessStatus = TRUE;
if ( !bCreate ) {
Win32rc = ScepGetNamedSecurityInfo( DatabaseName, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &pCurrentSD );
if ( Win32rc == ERROR_PATH_NOT_FOUND || Win32rc == ERROR_FILE_NOT_FOUND ) {
pCurrentSD = NULL;
Win32rc = NO_ERROR;
} }
if ( Win32rc == NO_ERROR ) {
if ( pCurrentSD == NULL ) { //
// either this database is to be overwritten (re-created)
// or it doesn't exist. In both cases, hand the call over to Jet
// which will do the right access checking.
//
} else {
if ( !AccessCheck ( pCurrentSD, hNewToken, DesiredAccess, &FileGenericMapping, &PrivSet, &PrivSetLength, &dwGrantedAccess, &bAccessStatus ) ) {
Win32rc = GetLastError();
} else {
if ( bAccessStatus && (dwGrantedAccess == DesiredAccess ) ) { Win32rc = NO_ERROR; } else { Win32rc = ERROR_ACCESS_DENIED; } } }
}
if ( pCurrentSD ) {
LocalFree(pCurrentSD); }
CloseHandle (hNewToken);
return( Win32rc ); }
DWORD ScepAddSidToNameList( OUT PSCE_NAME_LIST *pNameList, IN PSID pSid, IN BOOL bReuseBuffer, OUT BOOL *pbBufferUsed ) /* ++
Routine Description:
This routine adds a SID to the name list. The new added node is always placed as the head of the list for performance reason.
Arguments:
pNameList - The address of the name list to add to.
pSid - the Sid to add
Return value:
Win32 error code -- */ {
PSCE_NAME_LIST pList=NULL; ULONG Length;
//
// check arguments
//
if ( pNameList == NULL || pbBufferUsed == NULL ) return(ERROR_INVALID_PARAMETER);
*pbBufferUsed = FALSE;
if ( pSid == NULL ) return(NO_ERROR);
if ( !RtlValidSid(pSid) ) { return(ERROR_INVALID_PARAMETER); }
//
// check if the SID is already in the name list
//
for ( pList=*pNameList; pList!=NULL; pList=pList->Next ) { if ( pList->Name == NULL ) { continue; } if ( ScepValidSid( (PSID)(pList->Name) ) && RtlEqualSid( (PSID)(pList->Name), pSid ) ) { break; } }
if ( pList ) { //
// the SID is already in the list
//
return(NO_ERROR); }
//
// allocate a new node
//
pList = (PSCE_NAME_LIST)ScepAlloc( (UINT)0, sizeof(SCE_NAME_LIST));
if ( pList == NULL ) return(ERROR_NOT_ENOUGH_MEMORY);
if ( bReuseBuffer ) {
pList->Name = (PWSTR)pSid; *pbBufferUsed = TRUE;
} else {
Length = RtlLengthSid ( pSid );
pList->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length); if ( pList->Name == NULL ) { ScepFree(pList); return(ERROR_NOT_ENOUGH_MEMORY); }
//
// add the node to the front of the list and link its next to the old list
//
RtlCopySid( Length, (PSID)(pList->Name), pSid ); }
pList->Next = *pNameList; *pNameList = pList;
return(NO_ERROR); }
BOOL ScepValidSid( PSID Sid ) { if ( RtlValidSid(Sid) ) {
PISID Isid = (PISID) Sid;
if ( Isid->Revision == SID_REVISION ) { return(TRUE); } else { return(FALSE); } }
return(FALSE); }
BOOL ScepBinarySearch( IN PWSTR *aPszPtrs, IN DWORD dwSize_aPszPtrs, IN PWSTR pszNameToFind ) /* ++
Routine Description:
This routine determines if a string is found in a sorted array of strings. The complexity of this search is logarithmic (log(n)) in the size of the input array.
Arguments:
aPszPtrs - the array of string pointers to search in
dwSize_aPszPtrs - the size of the above array
pszNameToFind - the string to search for
Return value:
TRUE if string is found FALSE if string is not found
-- */ { if ( aPszPtrs == NULL || dwSize_aPszPtrs == 0 || pszNameToFind == NULL ) { return FALSE; }
int iLow = 0; int iHigh = dwSize_aPszPtrs - 1; int iMid; int iCmp;
while (iLow <= iHigh ) {
iMid = (iLow + iHigh ) / 2;
iCmp = _wcsicmp( aPszPtrs[iMid], pszNameToFind );
if ( iCmp == 0 ) return TRUE; else if ( iCmp < 0 ) iLow = iMid + 1; else iHigh = iMid - 1; }
return FALSE; }
/* ++
Routine Description:
This routine adds a relative SID to the SID list in the format "#-RSID", eg "#-512" for Domain Admins. Upon membership restore the groups stores as relative SIDs will be from the tattoo table, the full SID will be restored based on current domain.
Arguments:
aPszPtrs - the array of string pointers to search in
dwSize_aPszPtrs - the size of the above array
pszNameToFind - the string to search for
Return value:
TRUE if string is found FALSE if string is not found
-- */ DWORD ScepAddRelativeSidToNameList( IN OUT PSCE_NAME_LIST *pNameList, IN PSID pSid) { DWORD rc; PWSTR pwszSid = NULL; WCHAR *pchRelativeSid;
rc = ScepConvertSidToPrefixStringSid(pSid, &pwszSid); if(ERROR_SUCCESS == rc) { //
// find the relative SID suffix
//
pchRelativeSid = wcsrchr(pwszSid, STRING_SID_SUBAUTH_SEPARATOR); if(!pchRelativeSid || L'\0'==*(pchRelativeSid+1)) { rc = SCESTATUS_INVALID_DATA; } else { //
// Add the relative SID to list in format "#-RSID"
//
rc = ScepAddTwoNamesToNameList( pNameList, FALSE, RELATIVE_SID_PREFIX_SZ, 1, pchRelativeSid, wcslen(pchRelativeSid)); } }
if(pwszSid) { ScepFree(pwszSid); }
return rc; }
|