10569 lines
321 KiB
C++
10569 lines
321 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
config.c
|
||
|
||
Abstract:
|
||
|
||
Routines to configure system to comply the security profile information
|
||
|
||
Author:
|
||
|
||
Jin Huang (jinhuang) 7-Nov-1996
|
||
|
||
Revision History:
|
||
|
||
jinhuang 27-Jan-1997 split for client-server
|
||
|
||
--*/
|
||
|
||
#include "headers.h"
|
||
#include "serverp.h"
|
||
#include "pfp.h"
|
||
#include "kerberos.h"
|
||
#include "regvalue.h"
|
||
#include "service.h"
|
||
#include <io.h>
|
||
#include <lmcons.h>
|
||
#include <secobj.h>
|
||
#include <netlib.h>
|
||
#include "infp.h"
|
||
#include "sddl.h"
|
||
#include "queue.h"
|
||
#include "splay.h"
|
||
#include "authz.h"
|
||
#include "seopaque.h"
|
||
|
||
#pragma hdrstop
|
||
|
||
//
|
||
// properties of SCP engine (thread safe variables)
|
||
//
|
||
|
||
BYTE Thread scpBuffer[sizeof(SCE_PROFILE_INFO)];
|
||
PSCE_PROFILE_INFO Thread pScpInfo=NULL;
|
||
PSCECONTEXT Thread hProfile=NULL;
|
||
LSA_HANDLE Thread LsaPrivatePolicy=NULL;
|
||
|
||
|
||
extern HINSTANCE MyModuleHandle;
|
||
extern AUTHZ_RESOURCE_MANAGER_HANDLE ghAuthzResourceManager;
|
||
|
||
|
||
#define SCE_PRIV_ADD TEXT("Add:")
|
||
#define SCE_PRIV_REMOVE TEXT("Remove:")
|
||
#define SCEP_NUM_LSA_QUERY_SIDS 2000
|
||
#define MAXDWORD 0xffffffff
|
||
|
||
#define SCEDCPOL_MIN_PASS_AGE 0
|
||
#define SCEDCPOL_MAX_PASS_AGE 42
|
||
#define SCEDCPOL_MIN_PASS_LEN 0
|
||
#define SCEDCPOL_PASS_SIZE 1
|
||
#define SCEDCPOL_PASS_COMP 0
|
||
#define SCEDCPOL_CLEAR_PASS 0
|
||
#define SCEDCPOL_REQUIRE_LOGON 0
|
||
#define SCEDCPOL_FORCE_LOGOFF 0
|
||
#define SCEDCPOL_ENABLE_ADMIN 1
|
||
#define SCEDCPOL_ENABLE_GUEST 0
|
||
#define SCEDCPOL_LOCK_COUNT 0
|
||
#define SCEDCPOL_LOCK_RESET 30
|
||
#define SCEDCPOL_LOCK_DURATION 30
|
||
#define SCEDCPOL_LSA_ANON_LOOKUP 1
|
||
|
||
DWORD
|
||
ScepConfigureLSAPolicyObject(
|
||
IN DWORD dwLSAAnonymousNameLookup,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
|
||
OUT BOOL *pbOldLSAPolicyDifferent
|
||
);
|
||
|
||
DWORD
|
||
ScepAddAceToSecurityDescriptor(
|
||
IN DWORD AceType,
|
||
IN ACCESS_MASK AccessMask,
|
||
IN PSID pSid,
|
||
IN OUT PSECURITY_DESCRIPTOR pSDAbsolute,
|
||
IN PSECURITY_DESCRIPTOR pSDSelfRelative,
|
||
OUT PACL *ppNewAcl
|
||
);
|
||
|
||
//
|
||
// this function is defined in inftojet.cpp
|
||
//
|
||
SCESTATUS
|
||
ScepBuildNewPrivilegeList(
|
||
IN LSA_HANDLE *pPolicyHandle,
|
||
IN PWSTR PrivName,
|
||
IN PWSTR mszUsers,
|
||
IN ULONG dwBuildOption,
|
||
OUT PWSTR *pmszNewUsers,
|
||
OUT DWORD *pNewLen
|
||
);
|
||
|
||
//
|
||
// forward references
|
||
//
|
||
|
||
SCESTATUS
|
||
ScepConfigureInitialize(
|
||
IN PCWSTR InfFileName OPTIONAL,
|
||
IN PWSTR DatabaseName,
|
||
IN BOOL bAdminLogon,
|
||
IN DWORD ConfigOptions,
|
||
IN AREA_INFORMATION Area
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureSystemAccess(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCE_ERROR_LOG_INFO *pErrLog,
|
||
IN DWORD QueueFlag
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepManageAdminGuestAccounts(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PWSTR NewName,
|
||
IN DWORD ControlFlag,
|
||
IN DWORD AccountType,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCESECTION hSectionDomain,
|
||
IN PSCESECTION hSectionTattoo
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivileges(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN BOOL bCreateBuiltinAccount,
|
||
IN DWORD Options,
|
||
IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepGetPrivilegeMask(
|
||
IN PSCECONTEXT hProfile,
|
||
IN SCETYPE ProfileType,
|
||
OUT PDWORD pdLowMask,
|
||
OUT PDWORD pdHighMask
|
||
);
|
||
|
||
DWORD
|
||
ScepCreateBuiltinAccountInLsa(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN LPTSTR AccountName,
|
||
OUT PSID AccountSid
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepAdjustAccountPrivilegesRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN PSID AccountSid,
|
||
IN DWORD PrivilegeLowRights,
|
||
IN DWORD PrivilegeLowMask,
|
||
IN DWORD PrivilegeHighRights,
|
||
IN DWORD PrivilegeHighMask,
|
||
IN DWORD Options
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepAddOrRemoveAccountRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN PSID AccountSid,
|
||
IN BOOL AddOrRemove,
|
||
IN DWORD PrivLowAdjust,
|
||
IN DWORD PrivHighAdjust
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepValidateUserInGroups(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN PSID DomainSid,
|
||
IN UNICODE_STRING UserName,
|
||
IN ULONG UserId,
|
||
IN PSCE_NAME_LIST pGroupsToCheck
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepAddUserToGroup(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN ULONG UserId,
|
||
IN PSID AccountSid,
|
||
IN PWSTR GroupName
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureGroupMembership(
|
||
IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepConfigureMembersOfGroup(
|
||
IN PSCESECTION hSectionDomain,
|
||
IN PSCESECTION hSectionTattoo,
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PSID ThisDomainSid,
|
||
IN ULONG GrpId,
|
||
IN PSID GrpSid,
|
||
IN PWSTR GrpName,
|
||
IN PWSTR GroupSidString,
|
||
IN PSCE_NAME_LIST pMembers,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
NTSTATUS
|
||
ScepConfigureMembersOfAlias(
|
||
IN PSCESECTION hSectionDomain,
|
||
IN PSCESECTION hSectionTattoo,
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PSID DomainSid,
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN ULONG GrpId,
|
||
IN PSID GrpSid,
|
||
IN PWSTR GrpName,
|
||
IN PWSTR GroupSidString,
|
||
IN PSCE_NAME_LIST pMembers,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepValidateGroupInAliases(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN PSID GrpSid,
|
||
IN PSCE_NAME_LIST pAliasList
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureObjectSecurity(
|
||
IN PSCE_OBJECT_LIST pSecurityObject,
|
||
IN AREA_INFORMATION Area,
|
||
IN BOOL bPolicyProp,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureSystemAuditing(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureAuditEvent(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN PPOLICY_AUDIT_EVENTS_INFO auditEvent,
|
||
IN DWORD Options,
|
||
IN LSA_HANDLE PolicyHandle
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigureDeInitialize(
|
||
IN SCESTATUS rc,
|
||
IN AREA_INFORMATION Area
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepMakePolicyIntoFile(
|
||
IN DWORD Options,
|
||
IN AREA_INFORMATION Area
|
||
);
|
||
|
||
DWORD
|
||
ScepWriteOneAttributeToFile(
|
||
IN LPCTSTR SectionName,
|
||
IN LPCTSTR FileName,
|
||
IN LPCTSTR KeyName,
|
||
IN DWORD dwValue
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepCopyPrivilegesIntoFile(
|
||
IN LPTSTR FileName,
|
||
IN BOOL bInUpgrade
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepCopyPrivilegesFromDatabase(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Keyname,
|
||
IN DWORD StrLength,
|
||
IN PWSTR StrValue OPTIONAL,
|
||
OUT PWSTR *pOldValue,
|
||
OUT DWORD *pOldLen
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepDeleteDomainPolicies();
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivilegesWithMask(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN BOOL bCreateBuiltinAccount,
|
||
IN DWORD Options,
|
||
IN DWORD LowMask,
|
||
IN DWORD HighMask,
|
||
IN OUT PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
|
||
IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivilegesByRight(
|
||
IN PSCE_PRIVILEGE_ASSIGNMENT pPrivAssign,
|
||
IN DWORD Options,
|
||
IN OUT PSCE_ERROR_LOG_INFO *pErrLog
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepTattooUpdatePrivilegeArrayStatus(
|
||
IN DWORD *pStatusArray,
|
||
IN DWORD rc,
|
||
IN DWORD PrivLowMask,
|
||
IN DWORD PrivHighMask
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepTattooRemovePrivilegeValues(
|
||
IN PSCECONTEXT hProfile,
|
||
IN DWORD *pStatusArray
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepTattooSavePrivilegeValues(
|
||
IN PSCECONTEXT hProfile,
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN DWORD PrivLowMask,
|
||
IN DWORD PrivHighMask,
|
||
IN DWORD ConfigOptions
|
||
);
|
||
|
||
DWORD
|
||
ScepTattooCurrentGroupMembers(
|
||
IN PSID ThisDomainSid,
|
||
IN SID_NAME_USE GrpUse,
|
||
IN PULONG MemberRids OPTIONAL,
|
||
IN PSID *MemberAliasSids OPTIONAL,
|
||
IN DWORD MemberCount,
|
||
OUT PSCE_NAME_LIST *ppNameList
|
||
);
|
||
|
||
VOID
|
||
ScepBuildDwMaskFromStrArray(
|
||
IN PUNICODE_STRING aUserRights,
|
||
IN ULONG uCountOfRights,
|
||
OUT DWORD *pdwPrivLowThisAccount,
|
||
OUT DWORD *pdwPrivHighThisAccount
|
||
);
|
||
|
||
|
||
#define SCEP_REMOVE_PRIV_BIT(b,pl,ph) \
|
||
if ( b < 32 ) { \
|
||
*pl &= ~(1 << b); \
|
||
} else if ( b >= 32 && b < 64 ) { \
|
||
*ph &= ~( 1 << (b-32)); \
|
||
}
|
||
|
||
#define SCEP_ADD_PRIV_BIT(b,l,h) \
|
||
if ( b < 32 ) { \
|
||
l |= (1 << b); \
|
||
} else if ( b >= 32 && b < 64 ) { \
|
||
h |= ( 1 << (b-32)); \
|
||
}
|
||
|
||
#define SCEP_CHECK_PRIV_BIT(i,pl,ph) \
|
||
( (i < 32) && ( pl & (1 << i)) ) || \
|
||
( (i >= 32) && ( ph & ( 1 << (i-32)) ) )
|
||
|
||
|
||
SCESTATUS
|
||
ScepCheckNetworkLogonRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN OUT DWORD *pLowMask,
|
||
IN OUT DWORD *pHighMask,
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned
|
||
);
|
||
|
||
SCESTATUS
|
||
ScepAddAccountRightToList(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppParent,
|
||
IN INT idxRight,
|
||
IN PSID AccountSid
|
||
);
|
||
|
||
|
||
//
|
||
// function implementations
|
||
//
|
||
SCESTATUS
|
||
ScepConfigureSystem(
|
||
IN PCWSTR InfFileName OPTIONAL,
|
||
IN PWSTR DatabaseName,
|
||
IN DWORD ConfigOptions,
|
||
IN BOOL bAdminLogon,
|
||
IN AREA_INFORMATION Area,
|
||
OUT PDWORD pdWarning OPTIONAL
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
This routine updates
|
||
This routine is the exported API to configure a system by applying a SCP
|
||
file (INF) to the system. I a INF template is provided, it is first parsed
|
||
and saved in the SAD database. Then the system is configured using the info
|
||
in the template.
|
||
|
||
If any error occurs when loading SCP information, configuration will stop,
|
||
and return the error code. If a error occurs when configure an area, it will
|
||
stop configuring the whole area but continue to configure other left areas.
|
||
All success and fail transactions will be logged to the logfile(or stdout).
|
||
|
||
Log is already initialized before this call
|
||
|
||
Arguments:
|
||
|
||
InfFileName - The SCP file name
|
||
|
||
DatabaseName - The file name of the JET (for future analysis) profile
|
||
|
||
ConfigOptions - if the template provided is to update the system, or overwrite
|
||
|
||
Area - one or more areas to configure.
|
||
AREA_SECURITY_POLICY
|
||
AREA_USER_SETTINGS // block out for beta1
|
||
AREA_GROUP_MEMBERSHIP
|
||
AREA_PRIVILEGES
|
||
AREA_REGISTRY_SECURITY
|
||
AREA_FILE_SECURITY
|
||
AREA_SYSTEM_SERVICE
|
||
|
||
pdWarning - the warning code
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_ALREADY_RUNNING
|
||
|
||
Status from ScepGetDatabaseInfo
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc, Saverc;
|
||
SCESTATUS PendingRc=SCESTATUS_SUCCESS;
|
||
PSCE_ERROR_LOG_INFO pErrlog=NULL;
|
||
PPOLICY_AUDIT_EVENTS_INFO auditEvent=NULL;
|
||
BOOL bAuditOff=FALSE;
|
||
PBYTE pFullAudit = NULL;
|
||
PSCEP_SPLAY_TREE pNotifyAccounts=NULL;
|
||
DWORD QueueFlag=0;
|
||
|
||
Saverc = ScepConfigureInitialize(
|
||
InfFileName,
|
||
DatabaseName,
|
||
bAdminLogon,
|
||
ConfigOptions,
|
||
Area );
|
||
|
||
if ( Saverc != SCESTATUS_SUCCESS ) {
|
||
|
||
ScepPostProgress(gTotalTicks, 0, NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_INIT_ERROR);
|
||
|
||
} else if ( !(ConfigOptions & SCE_NO_CONFIG) ) {
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_INIT_SUCCESS);
|
||
|
||
Area &= ~AREA_USER_SETTINGS;
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(ConfigOptions & SCE_NO_CONFIG_FILEKEY) ) {
|
||
//
|
||
// if within policy propagation (at reboot) and
|
||
// this is the foreground thread, do not configure
|
||
// file and registry sections. They will be configured
|
||
// in background thread separately.
|
||
//
|
||
Area &= ~(AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY);
|
||
}
|
||
|
||
//
|
||
// get information from the notification queue so that
|
||
// pending notifications are ignored
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( (Area & AREA_PRIVILEGES) ||
|
||
(Area & AREA_SECURITY_POLICY) ) ) {
|
||
//
|
||
// return error is ignored so policy prop will overwrite
|
||
//
|
||
|
||
__try {
|
||
|
||
//
|
||
// initialize the root TreeNode
|
||
//
|
||
if ( NULL == (pNotifyAccounts = ScepSplayInitialize(SplayNodeSidType)) ) {
|
||
|
||
rc = ERROR_NOT_ENOUGH_MEMORY;
|
||
ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_ERROR_SPLAY_INITIALIZE);
|
||
|
||
} else if ( ERROR_SUCCESS != (rc=ScepGetQueueInfo(&QueueFlag, pNotifyAccounts)) ) {
|
||
QueueFlag = 0;
|
||
|
||
ScepLogOutput3(1,rc, SCESRV_POLICY_PENDING_QUERY);
|
||
}
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
QueueFlag = 0;
|
||
rc = ERROR_IO_PENDING;
|
||
|
||
ScepLogOutput3(1,rc, SCESRV_POLICY_PENDING_QUERY);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS != rc ) {
|
||
|
||
PendingRc = ScepDosErrorToSceStatus(rc);
|
||
|
||
ScepPostProgress(gTotalTicks, 0, NULL);
|
||
|
||
goto Done;
|
||
}
|
||
}
|
||
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
//
|
||
// always resume the queue processing after queue info is queued
|
||
//
|
||
ScepNotificationQControl(0);
|
||
}
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_READ_PROFILE);
|
||
Saverc = ScepGetDatabaseInfo(
|
||
hProfile,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ?
|
||
SCE_ENGINE_SCP_INTERNAL : SCE_ENGINE_SMP_INTERNAL,
|
||
Area,
|
||
SCE_ACCOUNT_SID,
|
||
&pScpInfo,
|
||
&pErrlog
|
||
);
|
||
|
||
ScepLogWriteError( pErrlog, 1 );
|
||
ScepFreeErrorLog( pErrlog );
|
||
pErrlog = NULL;
|
||
|
||
if ( Saverc != SCESTATUS_SUCCESS ) {
|
||
|
||
ScepPostProgress(gTotalTicks, 0, NULL);
|
||
|
||
goto Done;
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// turn off object access auditing if file/key is to be configured
|
||
// in system context.
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( (Area & AREA_FILE_SECURITY) && pScpInfo->pFiles.pOneLevel ) ||
|
||
( (Area & AREA_REGISTRY_SECURITY) && pScpInfo->pRegistryKeys.pOneLevel ) )
|
||
|
||
bAuditOff = TRUE;
|
||
|
||
//
|
||
// if set, this regkey will decide to audit all
|
||
//
|
||
ScepRegQueryBinaryValue(
|
||
HKEY_LOCAL_MACHINE,
|
||
L"System\\CurrentControlSet\\Control\\Lsa",
|
||
L"fullprivilegeauditing",
|
||
&pFullAudit
|
||
);
|
||
|
||
if (pFullAudit) {
|
||
if (*pFullAudit & (BYTE)1)
|
||
bAuditOff = FALSE;
|
||
ScepFree(pFullAudit);
|
||
}
|
||
|
||
Saverc = ScepSaveAndOffAuditing(&auditEvent, bAuditOff, LsaPrivatePolicy);
|
||
|
||
// if ( Saverc != SCESTATUS_SUCCESS )
|
||
// goto Done;
|
||
// if auditing can't be turned on for some reason, e.g., access denied for
|
||
// normal user, just continue
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// User Settings area
|
||
//
|
||
Saverc = 0;
|
||
if ( Area & AREA_PRIVILEGES ) {
|
||
|
||
ScepPostProgress(0, AREA_PRIVILEGES, NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_PRIVILEGES);
|
||
|
||
rc = ScepConfigurePrivileges( &(pScpInfo->OtherInfo.scp.u.pPrivilegeAssignedTo),
|
||
(ConfigOptions & SCE_CREATE_BUILTIN_ACCOUNTS),
|
||
(bAdminLogon ?
|
||
ConfigOptions :
|
||
(ConfigOptions & ~SCE_SYSTEM_DB)),
|
||
(QueueFlag & SCE_QUEUE_INFO_RIGHTS) ? pNotifyAccounts : NULL
|
||
);
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
if ( rc != SCESTATUS_PENDING_IGNORE )
|
||
Saverc = rc;
|
||
else
|
||
PendingRc = rc;
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_PRIVILEGES_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_PRIVILEGES_SUCCESS);
|
||
}
|
||
}
|
||
|
||
if ( pNotifyAccounts ) {
|
||
ScepSplayFreeTree(&pNotifyAccounts, TRUE);
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// Group Membership area
|
||
//
|
||
if ( Area & AREA_GROUP_MEMBERSHIP) {
|
||
|
||
ScepPostProgress(0, AREA_GROUP_MEMBERSHIP, NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_GROUPMGMT);
|
||
|
||
#if _WIN32_WINNT>=0x0500
|
||
// need to support nested groups
|
||
|
||
if ( ProductType == NtProductLanManNt ) {
|
||
|
||
rc = ScepConfigDsGroups( pScpInfo->pGroupMembership, ConfigOptions );
|
||
|
||
//
|
||
// some groups (such as local groups) may not be configured in DS
|
||
// so try it in SAM
|
||
//
|
||
SCESTATUS rc2 = ScepConfigureGroupMembership(pScpInfo->pGroupMembership, ConfigOptions );
|
||
if ( rc2 != SCESTATUS_SUCCESS )
|
||
rc = rc2;
|
||
|
||
} else {
|
||
#endif
|
||
|
||
rc = ScepConfigureGroupMembership( pScpInfo->pGroupMembership, ConfigOptions );
|
||
|
||
#if _WIN32_WINNT>=0x0500
|
||
}
|
||
#endif
|
||
|
||
if ( rc != SCESTATUS_SUCCESS) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_GROUPMGMT_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_GROUPMGMT_SUCCESS);
|
||
}
|
||
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// Registry Security area
|
||
//
|
||
|
||
if ( Area & AREA_REGISTRY_SECURITY ) {
|
||
|
||
ScepPostProgress(0,
|
||
AREA_REGISTRY_SECURITY,
|
||
NULL);
|
||
|
||
rc = ScepConfigureObjectSecurity( pScpInfo->pRegistryKeys.pOneLevel,
|
||
AREA_REGISTRY_SECURITY,
|
||
(ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
|
||
ConfigOptions
|
||
);
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
}
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
//
|
||
// File Security area
|
||
//
|
||
|
||
if ( Area & AREA_FILE_SECURITY ) {
|
||
|
||
ScepPostProgress(0,
|
||
AREA_FILE_SECURITY,
|
||
NULL);
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_FILE);
|
||
|
||
rc = ScepConfigureObjectSecurity( pScpInfo->pFiles.pOneLevel,
|
||
AREA_FILE_SECURITY,
|
||
(ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
|
||
ConfigOptions
|
||
);
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_FILE_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_FILE_SUCCESS);
|
||
}
|
||
|
||
}
|
||
|
||
#if 0
|
||
#if _WIN32_WINNT>=0x0500
|
||
if ( (ProductType == NtProductLanManNt) && (Area & AREA_DS_OBJECTS) ) {
|
||
|
||
ScepPostProgress(0,
|
||
AREA_DS_OBJECTS,
|
||
NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_DS);
|
||
|
||
rc = ScepConfigureObjectSecurity( pScpInfo->pDsObjects.pOneLevel,
|
||
AREA_DS_OBJECTS,
|
||
(ConfigOptions & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
|
||
ConfigOptions
|
||
);
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_DS_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_DS_SUCCESS);
|
||
}
|
||
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// System Service area
|
||
//
|
||
|
||
if ( Area & AREA_SYSTEM_SERVICE ) {
|
||
|
||
ScepPostProgress(0,
|
||
AREA_SYSTEM_SERVICE,
|
||
NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_GENERALSVC);
|
||
|
||
rc = ScepConfigureGeneralServices( hProfile, pScpInfo->pServices, ConfigOptions );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_GENERALSVC_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_GENERALSVC_SUCCESS);
|
||
}
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_ATTACHMENT);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
rc = ScepInvokeSpecificServices( hProfile, TRUE, SCE_ATTACHMENT_SERVICE );
|
||
}
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_SUCCESS);
|
||
}
|
||
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
Saverc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// Security policy
|
||
//
|
||
|
||
if ( Area & AREA_SECURITY_POLICY ) {
|
||
|
||
ScepPostProgress(0,
|
||
AREA_SECURITY_POLICY,
|
||
NULL);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_POLICY);
|
||
|
||
if ( !(ConfigOptions & SCE_NO_DOMAIN_POLICY ) ) {
|
||
|
||
rc = ScepConfigureSystemAccess( pScpInfo, ConfigOptions, NULL, QueueFlag );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
if ( rc != SCESTATUS_PENDING_IGNORE )
|
||
Saverc = rc;
|
||
else
|
||
PendingRc = rc;
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ACCESS_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ACCESS_SUCCESS);
|
||
}
|
||
}
|
||
|
||
ScepPostProgress(TICKS_SYSTEM_ACCESS,
|
||
AREA_SECURITY_POLICY,
|
||
(LPTSTR)szSystemAccess);
|
||
//
|
||
// System Auditing area
|
||
//
|
||
rc = ScepConfigureSystemAuditing( pScpInfo, ConfigOptions );
|
||
|
||
if ( rc == SCESTATUS_SUCCESS && NULL != auditEvent ) {
|
||
|
||
//
|
||
// not in policy prop or
|
||
// no pending notify for audit
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(QueueFlag & SCE_QUEUE_INFO_AUDIT) ) {
|
||
|
||
|
||
rc = ERROR_IO_PENDING;
|
||
ScepLogOutput3(0, 0, SCESRV_POLICY_PENDING_AUDIT);
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
|
||
|
||
rc = ScepDosErrorToSceStatus(rc);
|
||
|
||
} else {
|
||
|
||
rc = ScepConfigureAuditEvent(pScpInfo,
|
||
auditEvent,
|
||
bAdminLogon ?
|
||
ConfigOptions :
|
||
(ConfigOptions & ~SCE_SYSTEM_DB),
|
||
LsaPrivatePolicy
|
||
);
|
||
}
|
||
}
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
if ( rc != SCESTATUS_PENDING_IGNORE )
|
||
Saverc = rc;
|
||
else
|
||
PendingRc = rc;
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_AUDIT_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_AUDIT_SUCCESS);
|
||
}
|
||
|
||
ScepPostProgress(TICKS_SYSTEM_AUDITING,
|
||
AREA_SECURITY_POLICY,
|
||
(LPTSTR)szAuditEvent);
|
||
|
||
#if _WIN32_WINNT>=0x0500
|
||
if ( ProductType == NtProductLanManNt &&
|
||
!(ConfigOptions & SCE_NO_DOMAIN_POLICY ) ) {
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Kerberos Policy
|
||
//
|
||
rc = ScepConfigureKerberosPolicy( hProfile,
|
||
pScpInfo->pKerberosInfo,
|
||
ConfigOptions );
|
||
}
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_KERBEROS_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_KERBEROS_SUCCESS);
|
||
}
|
||
|
||
}
|
||
#endif
|
||
ScepPostProgress(TICKS_KERBEROS,
|
||
AREA_SECURITY_POLICY,
|
||
(LPTSTR)szKerberosPolicy);
|
||
|
||
//
|
||
// registry values
|
||
//
|
||
rc = ScepConfigureRegistryValues( hProfile,
|
||
pScpInfo->aRegValues,
|
||
pScpInfo->RegValueCount,
|
||
NULL,
|
||
ConfigOptions,
|
||
NULL );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGVALUES_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGVALUES_SUCCESS);
|
||
}
|
||
|
||
ScepPostProgress(TICKS_REGISTRY_VALUES,
|
||
AREA_SECURITY_POLICY,
|
||
(LPTSTR)szRegistryValues);
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_ATTACHMENT);
|
||
|
||
//
|
||
// implemented in service.cpp
|
||
//
|
||
rc = ScepInvokeSpecificServices( hProfile, TRUE, SCE_ATTACHMENT_POLICY );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_ATTACHMENT_SUCCESS);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( pNotifyAccounts ) {
|
||
ScepSplayFreeTree(&pNotifyAccounts, TRUE);
|
||
}
|
||
|
||
if ( NULL != auditEvent ) {
|
||
if ( bAuditOff && auditEvent->AuditingMode ) {
|
||
|
||
rc = ScepRestoreAuditing(auditEvent, LsaPrivatePolicy);
|
||
}
|
||
LsaFreeMemory(auditEvent);
|
||
}
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_UNINIT);
|
||
|
||
if ( pdWarning ) {
|
||
*pdWarning = gWarningCode;
|
||
}
|
||
|
||
//
|
||
// return failure if invalid data is found in the template
|
||
//
|
||
if ( gbInvalidData ) {
|
||
Saverc = SCESTATUS_INVALID_DATA;
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
!(ConfigOptions & SCE_NO_CONFIG) ) {
|
||
//
|
||
// always resume the queue processing after configuration is done
|
||
//
|
||
ScepNotificationQControl(0);
|
||
}
|
||
|
||
if ( Saverc == SCESTATUS_SUCCESS ) Saverc = PendingRc;
|
||
|
||
ScepConfigureDeInitialize( Saverc, Area);
|
||
|
||
return(Saverc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureInitialize(
|
||
IN PCWSTR InfFileName OPTIONAL,
|
||
IN PWSTR DatabaseName,
|
||
IN BOOL bAdminLogon,
|
||
IN DWORD ConfigOptions,
|
||
IN AREA_INFORMATION Area
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the SCP engine.
|
||
|
||
Arguments:
|
||
|
||
InfFileName - The file name of a SCP file used to configure the sytem
|
||
|
||
DatabaseName - The JET (for future analysis) profile name
|
||
|
||
ConfigOptions - If the template is to update the system instead of overwriting
|
||
|
||
Area - security area to initialize
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_PROFILE_NOT_FOUND
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_ALREADY_RUNNING
|
||
|
||
-- */
|
||
{
|
||
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
PCHAR FileName=NULL;
|
||
DWORD MBLen=0;
|
||
NTSTATUS NtStatus;
|
||
LARGE_INTEGER CurrentTime;
|
||
PSCE_ERROR_LOG_INFO Errlog=NULL;
|
||
PSECURITY_DESCRIPTOR pSD=NULL;
|
||
SECURITY_INFORMATION SeInfo;
|
||
DWORD SDsize;
|
||
DWORD DbNameLen;
|
||
HKEY hCurrentUser=NULL;
|
||
|
||
//
|
||
// database name can't be NULL because it's already resolved
|
||
//
|
||
|
||
if ( !DatabaseName ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
return(SCESTATUS_SERVICE_NOT_SUPPORT);
|
||
}
|
||
|
||
//
|
||
// get other system values
|
||
//
|
||
if ( RtlGetNtProductType (&ProductType) == FALSE ) {
|
||
rc = ScepDosErrorToSceStatus(GetLastError());
|
||
goto Leave;
|
||
}
|
||
|
||
//
|
||
// Initialize globals
|
||
//
|
||
gTotalTicks = 0;
|
||
gCurrentTicks = 0;
|
||
gWarningCode = 0;
|
||
gbInvalidData = FALSE;
|
||
|
||
//
|
||
// Initialize engine buffer
|
||
//
|
||
|
||
cbClientFlag = (BYTE)( ConfigOptions & (SCE_CALLBACK_DELTA |
|
||
SCE_CALLBACK_TOTAL ));
|
||
|
||
pScpInfo = (PSCE_PROFILE_INFO)&scpBuffer;
|
||
pScpInfo->Type = SCE_ENGINE_SCP_INTERNAL;
|
||
|
||
//
|
||
// convert WCHAR into ANSI
|
||
//
|
||
|
||
DbNameLen = wcslen(DatabaseName);
|
||
|
||
NtStatus = RtlUnicodeToMultiByteSize(&MBLen, DatabaseName, DbNameLen*sizeof(WCHAR));
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
//
|
||
// cannot get the length, set default to 512
|
||
//
|
||
MBLen = 512;
|
||
}
|
||
|
||
FileName = (PCHAR)ScepAlloc(LPTR, MBLen+2);
|
||
|
||
if ( FileName == NULL ) {
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
goto Leave;
|
||
}
|
||
|
||
NtStatus = RtlUnicodeToMultiByteN(
|
||
FileName,
|
||
MBLen+1,
|
||
NULL,
|
||
DatabaseName,
|
||
DbNameLen*sizeof(WCHAR)
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_PROCESS_UNICODE, DatabaseName );
|
||
rc = ScepDosErrorToSceStatus(rc);
|
||
goto Leave;
|
||
}
|
||
|
||
if ( RegOpenCurrentUser(
|
||
KEY_READ | KEY_WRITE,
|
||
&hCurrentUser
|
||
) != ERROR_SUCCESS ) {
|
||
hCurrentUser = NULL;
|
||
}
|
||
|
||
if ( hCurrentUser == NULL ) {
|
||
hCurrentUser = HKEY_CURRENT_USER;
|
||
}
|
||
|
||
//
|
||
// delay registry filter (into database) is not needed anymore
|
||
//
|
||
|
||
if ( InfFileName != NULL ) { // || InfHandle != NULL ) {
|
||
|
||
//
|
||
// convert inf to jet
|
||
//
|
||
ScepLogOutput3(3, 0, SCEDLL_PROCESS_TEMPLATE, (PWSTR)InfFileName );
|
||
|
||
if ( bAdminLogon ) {
|
||
//
|
||
// make sure the directories exist for the file
|
||
//
|
||
rc = ConvertTextSecurityDescriptor (
|
||
L"D:P(A;CIOI;GRGW;;;WD)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
|
||
&pSD,
|
||
&SDsize,
|
||
&SeInfo
|
||
);
|
||
if ( rc != NO_ERROR )
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, DatabaseName );
|
||
}
|
||
|
||
//
|
||
// change revision to ACL_REVISION2 (from 4) because it's for files
|
||
//
|
||
|
||
ScepChangeAclRevision(pSD, ACL_REVISION);
|
||
|
||
ScepCreateDirectory(
|
||
DatabaseName,
|
||
FALSE, // a file name
|
||
pSD //NULL // take parent's security setting
|
||
);
|
||
if ( pSD ) {
|
||
ScepFree(pSD);
|
||
}
|
||
|
||
if ( ConfigOptions & SCE_OVERWRITE_DB ) {
|
||
//
|
||
// only delete existing jet files if jet engine is not running
|
||
// because other threads may use the same version storage
|
||
// for other database.
|
||
//
|
||
// if jet engine is not running, delete version storage files
|
||
// will not force a recovery because overwrite db option means
|
||
// overwrite all previous info in the database.
|
||
//
|
||
SceJetDeleteJetFiles(DatabaseName);
|
||
}
|
||
|
||
//
|
||
// copy the inf sections and data to the jet database SCP table
|
||
//
|
||
|
||
if ( InfFileName != NULL ) {
|
||
|
||
SCEJET_CREATE_TYPE TmpOption;
|
||
|
||
if ( ConfigOptions & SCE_UPDATE_DB ) {
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
TmpOption = SCEJET_OPEN_DUP;
|
||
} else {
|
||
TmpOption = SCEJET_OPEN_DUP_EXCLUSIVE;
|
||
}
|
||
} else {
|
||
TmpOption = SCEJET_OVERWRITE_DUP;
|
||
}
|
||
|
||
rc = SceJetConvertInfToJet(
|
||
InfFileName,
|
||
(LPSTR)FileName,
|
||
TmpOption,
|
||
bAdminLogon ? ConfigOptions : (ConfigOptions & ~SCE_SYSTEM_DB),
|
||
Area
|
||
);
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS error code
|
||
goto Leave;
|
||
}
|
||
} else if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(ConfigOptions & SCE_POLICY_FIRST) &&
|
||
(ConfigOptions & SCE_POLICY_LAST) ) {
|
||
//
|
||
// a policy refresh without any domain GPOs, do the local GPO only
|
||
//
|
||
|
||
rc = SceJetOpenFile(
|
||
(LPSTR)FileName,
|
||
SCEJET_OPEN_READ_WRITE, // SCEJET_OPEN_EXCLUSIVE,
|
||
SCE_TABLE_OPTION_MERGE_POLICY | SCE_TABLE_OPTION_TATTOO,
|
||
&hProfile
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
rc = ScepDeleteInfoForAreas(
|
||
hProfile,
|
||
SCE_ENGINE_SCP,
|
||
AREA_ALL
|
||
);
|
||
|
||
if ( ( rc == SCESTATUS_SUCCESS ) ||
|
||
( rc == SCESTATUS_RECORD_NOT_FOUND ) ) {
|
||
|
||
//
|
||
// delete GPO table to start over
|
||
//
|
||
|
||
SceJetDeleteAll( hProfile,
|
||
"SmTblGpo",
|
||
SCEJET_TABLE_GPO
|
||
);
|
||
|
||
//
|
||
// copy local table
|
||
//
|
||
PSCE_ERROR_LOG_INFO Errlog=NULL;
|
||
|
||
ScepLogOutput3(2, rc, SCEDLL_COPY_LOCAL);
|
||
|
||
rc = ScepCopyLocalToMergeTable( hProfile, ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0,
|
||
&Errlog );
|
||
|
||
ScepLogWriteError( Errlog,1 );
|
||
ScepFreeErrorLog( Errlog );
|
||
Errlog = NULL;
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
DWORD dwThisTable = hProfile->Type & 0xF0L;
|
||
|
||
if ( SCEJET_MERGE_TABLE_1 == dwThisTable ||
|
||
SCEJET_MERGE_TABLE_2 == dwThisTable ) {
|
||
|
||
rc = SceJetSetValueInVersion(
|
||
hProfile,
|
||
"SmTblVersion",
|
||
"LastUsedMergeTable",
|
||
(PWSTR)&dwThisTable,
|
||
4,
|
||
JET_prepReplace
|
||
);
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_COPY);
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_DELETE, L"SCP");
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_OPEN, DatabaseName );
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS error code
|
||
goto Leave;
|
||
}
|
||
}
|
||
|
||
//
|
||
// set the default profile into Reg
|
||
//
|
||
rc = ScepRegSetValue(
|
||
bAdminLogon ? HKEY_LOCAL_MACHINE : hCurrentUser,
|
||
SCE_ROOT_PATH,
|
||
L"LastUsedDatabase",
|
||
REG_SZ,
|
||
(BYTE *)DatabaseName,
|
||
DbNameLen*sizeof(WCHAR)
|
||
);
|
||
if ( rc != NO_ERROR ) // Win32 error code
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"LastUsedDatabase");
|
||
|
||
|
||
if ( InfFileName != NULL ) {
|
||
if ( bAdminLogon ) {
|
||
//
|
||
// only save the value if it's not coming from policy prop
|
||
//
|
||
if ( !(ConfigOptions & SCE_POLICY_TEMPLATE) ) {
|
||
|
||
rc = ScepRegSetValue(
|
||
HKEY_LOCAL_MACHINE,
|
||
SCE_ROOT_PATH,
|
||
L"TemplateUsed",
|
||
REG_SZ,
|
||
(BYTE *)InfFileName,
|
||
wcslen(InfFileName)*sizeof(WCHAR)
|
||
);
|
||
} else {
|
||
rc = NO_ERROR;
|
||
}
|
||
} else {
|
||
rc = ScepRegSetValue(
|
||
hCurrentUser, // HKEY_CURRENT_USER
|
||
SCE_ROOT_PATH,
|
||
L"TemplateUsed",
|
||
REG_SZ,
|
||
(BYTE *)InfFileName,
|
||
wcslen(InfFileName)*sizeof(WCHAR)
|
||
);
|
||
}
|
||
if ( rc != NO_ERROR ) // Win32 error code
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_SAVE_REGISTRY, L"TemplateUsed");
|
||
}
|
||
|
||
//
|
||
// if no configuration is requested, just return now.
|
||
//
|
||
|
||
if ( ConfigOptions & SCE_NO_CONFIG ) {
|
||
|
||
if ( !(ConfigOptions & SCE_COPY_LOCAL_POLICY) ) {
|
||
//
|
||
// if no policy template is requested
|
||
//
|
||
goto Leave;
|
||
}
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
goto Leave;
|
||
}
|
||
|
||
//
|
||
// open the database now to create some tables and time stamp
|
||
// tattoo is not needed unless it's in policy propagation
|
||
//
|
||
|
||
rc = SceJetOpenFile(
|
||
(LPSTR)FileName,
|
||
( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
|
||
&hProfile
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// sleep for some time and try open again
|
||
//
|
||
|
||
Sleep(2000); // 2 seconds
|
||
|
||
rc = SceJetOpenFile(
|
||
(LPSTR)FileName,
|
||
( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
|
||
&hProfile
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
|
||
Sleep(2000); // 2 seconds
|
||
|
||
rc = SceJetOpenFile(
|
||
(LPSTR)FileName,
|
||
( ConfigOptions & (SCE_POLICY_TEMPLATE | SCE_COPY_LOCAL_POLICY) ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_EXCLUSIVE,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0,
|
||
&hProfile
|
||
);
|
||
}
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
|
||
ScepLogOutput3(0, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_OPEN,
|
||
DatabaseName );
|
||
goto Leave;
|
||
}
|
||
|
||
SceJetStartTransaction( hProfile );
|
||
|
||
if ( ConfigOptions & SCE_COPY_LOCAL_POLICY ) {
|
||
//
|
||
// Copy domain policies (password, account, kerberos) to the special
|
||
// file %windir%\security\FirstDGPO.inf. The info in database will be
|
||
// deleted
|
||
//
|
||
//
|
||
// copy local policies (audit, and user rights) to the special file
|
||
// %windir%\security\FirstOGPO.inf. The local policy info in the
|
||
// database will still be left in.
|
||
//
|
||
rc = ScepMakePolicyIntoFile( ConfigOptions, Area);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS) {
|
||
|
||
SceJetRollback( hProfile, 0 );
|
||
goto Leave;
|
||
}
|
||
}
|
||
|
||
if ( (hProfile->JetSapID != JET_tableidNil) &&
|
||
!(ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
!(ConfigOptions & SCE_COPY_LOCAL_POLICY) &&
|
||
((ConfigOptions & SCE_NO_CONFIG) == 0) ) {
|
||
|
||
//
|
||
// analysis was performed before
|
||
// delete SAP info for the area
|
||
//
|
||
ScepLogOutput3(3,0, SCEDLL_DELETE_TABLE, L"SAP");
|
||
|
||
// bug 362120
|
||
// after each config, user must re-analyze the computer to get
|
||
// analysis information
|
||
//
|
||
// if ( (ConfigOptions & SCE_OVERWRITE_DB) &&
|
||
// (InfFileName != NULL /*|| InfHandle != NULL */) ) {
|
||
|
||
//
|
||
// if it's reconfigured with a new template, all SAP
|
||
// information is obselote, so delete the whole table
|
||
//
|
||
|
||
rc = SceJetDeleteTable(
|
||
hProfile,
|
||
"SmTblSap",
|
||
SCEJET_TABLE_SAP
|
||
);
|
||
/*
|
||
} else {
|
||
|
||
//
|
||
// the template is incremental, or use the original template
|
||
// just delete sap information for the area, assuming that
|
||
// everything in the area is matched after this configuration
|
||
//
|
||
|
||
rc = ScepDeleteInfoForAreas(
|
||
hProfile,
|
||
SCE_ENGINE_SAP,
|
||
Area
|
||
);
|
||
}
|
||
*/
|
||
if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND ) {
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_DELETE, L"SAP");
|
||
|
||
SceJetRollback( hProfile, 0 );
|
||
goto Leave;
|
||
}
|
||
}
|
||
|
||
//
|
||
// set time stamp for this configuration
|
||
//
|
||
|
||
if ( (ConfigOptions & SCE_NO_CONFIG) == 0 ) {
|
||
|
||
NtStatus = NtQuerySystemTime(&CurrentTime);
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
rc = SceJetSetTimeStamp(
|
||
hProfile,
|
||
FALSE,
|
||
CurrentTime
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_TIMESTAMP_ERROR,L"SMP");
|
||
|
||
// do not care the status of this call
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
} else
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_TIMESTAMP_ERROR, L"SMP");
|
||
}
|
||
|
||
//
|
||
// commit all changes to this database
|
||
// fatal errors won't get here
|
||
//
|
||
|
||
SceJetCommitTransaction( hProfile, 0 );
|
||
|
||
//
|
||
// now if NO_CONFIG is requested ( with MOVE_POLICY or COPY_POLICY flag )
|
||
// should return now
|
||
//
|
||
if ( ConfigOptions & SCE_NO_CONFIG ) {
|
||
goto Leave;
|
||
}
|
||
|
||
//
|
||
// close the exclusively opened database and
|
||
// open it for read only because config engine read from the database
|
||
// NOTE: SceJetOpenFile will close the previous database if the handle
|
||
// is not NULL. The SceJetCloseFile is called with (theHandle,FALSE,FALSE)
|
||
// so jet session and instance are not terminated
|
||
//
|
||
|
||
rc = SceJetOpenFile(
|
||
(LPSTR)FileName,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY, // tattoo table will be updated in policy
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ? SCE_TABLE_OPTION_TATTOO : 0, // by now the LastUsedMergeTable field is already set
|
||
&hProfile
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS ) { // SCESTATUS
|
||
ScepLogOutput3(0, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_OPEN,
|
||
DatabaseName );
|
||
goto Leave;
|
||
}
|
||
|
||
//
|
||
// query the total ticks of this configuration
|
||
//
|
||
|
||
rc = ScepGetTotalTicks(
|
||
NULL,
|
||
hProfile,
|
||
Area,
|
||
( ConfigOptions & SCE_POLICY_TEMPLATE ) ?
|
||
SCE_FLAG_CONFIG_SCP : SCE_FLAG_CONFIG,
|
||
&gTotalTicks
|
||
);
|
||
if ( SCESTATUS_SUCCESS != rc &&
|
||
SCESTATUS_RECORD_NOT_FOUND != rc ) {
|
||
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_TOTAL_TICKS_ERROR);
|
||
|
||
}
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
//
|
||
// reset memory buffer
|
||
//
|
||
memset( pScpInfo, '\0',sizeof(SCE_PROFILE_INFO) );
|
||
pScpInfo->Type = SCE_ENGINE_SCP_INTERNAL;
|
||
|
||
//
|
||
// open LSA private policy handle (to block other downlevel changes)
|
||
//
|
||
if ( ( ConfigOptions & SCE_POLICY_TEMPLATE ) &&
|
||
!( ConfigOptions & SCE_NO_CONFIG) &&
|
||
( (Area & AREA_PRIVILEGES) ||
|
||
(Area & AREA_SECURITY_POLICY) ) ) {
|
||
|
||
//
|
||
// enable TCB privilege
|
||
//
|
||
SceAdjustPrivilege( SE_TCB_PRIVILEGE, TRUE, NULL );
|
||
|
||
NTSTATUS NtStatus;
|
||
LSA_OBJECT_ATTRIBUTES attributes;
|
||
SECURITY_QUALITY_OF_SERVICE service;
|
||
|
||
|
||
memset( &attributes, 0, sizeof(attributes) );
|
||
attributes.Length = sizeof(attributes);
|
||
attributes.SecurityQualityOfService = &service;
|
||
service.Length = sizeof(service);
|
||
service.ImpersonationLevel= SecurityImpersonation;
|
||
service.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||
service.EffectiveOnly = TRUE;
|
||
|
||
//
|
||
// open the lsa policy first
|
||
//
|
||
|
||
NtStatus = LsaOpenPolicySce( // LsaOpenPolicySce
|
||
NULL,
|
||
&attributes,
|
||
MAXIMUM_ALLOWED,
|
||
&LsaPrivatePolicy
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) || NtStatus == STATUS_TIMEOUT) {
|
||
|
||
if ( STATUS_TIMEOUT == NtStatus ) {
|
||
rc = ERROR_TIMEOUT;
|
||
} else
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
LsaPrivatePolicy = NULL;
|
||
|
||
ScepLogOutput3(1, rc, SCESRV_ERROR_PRIVATE_LSA );
|
||
rc = ScepDosErrorToSceStatus(rc);
|
||
|
||
} else {
|
||
|
||
ScepNotifyLogPolicy(0, TRUE, L"Policy Prop: Private LSA handle is returned", 0, 0, NULL );
|
||
}
|
||
}
|
||
|
||
Leave:
|
||
|
||
if ( hCurrentUser && hCurrentUser != HKEY_CURRENT_USER ) {
|
||
RegCloseKey(hCurrentUser);
|
||
}
|
||
|
||
if ( FileName ) {
|
||
ScepFree(FileName);
|
||
}
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureSystemAccess(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCE_ERROR_LOG_INFO *pErrLog,
|
||
IN DWORD QueueFlag
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
This routine configure the system security in the area of system access
|
||
which includes account policy, rename admin/guest accounts, disable
|
||
no activity account, and some registry keys security, e.g., winlogon keys.
|
||
|
||
Arguments:
|
||
|
||
pScpInfo - The buffer which contains SCP info loaded from the profile
|
||
|
||
ConfigOptions - options in configuration
|
||
|
||
pErrLog - the output log for potential errors
|
||
|
||
QueueFlag - flags for the notification queue, which determines if SAM policy
|
||
should be configured.
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
DWORD rc,PendingRc=0;
|
||
DWORD SaveStat;
|
||
NTSTATUS NtStatus;
|
||
SAM_HANDLE DomainHandle=NULL,
|
||
ServerHandle=NULL,
|
||
UserHandle1=NULL;
|
||
PSID DomainSid=NULL;
|
||
PVOID Buffer=NULL;
|
||
DWORD RegData;
|
||
BOOL bFlagSet;
|
||
|
||
SCE_TATTOO_KEYS *pTattooKeys=NULL;
|
||
DWORD cTattooKeys=0;
|
||
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
|
||
#define MAX_PASS_KEYS 7
|
||
#define MAX_LOCKOUT_KEYS 3
|
||
|
||
//
|
||
// Open account domain
|
||
//
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
return(SCESTATUS_SERVICE_NOT_SUPPORT);
|
||
}
|
||
|
||
NtStatus = ScepOpenSamDomain(
|
||
MAXIMUM_ALLOWED, // SAM_SERVER_ALL_ACCESS,
|
||
DOMAIN_WRITE_PASSWORD_PARAMS | MAXIMUM_ALLOWED,
|
||
&ServerHandle,
|
||
&DomainHandle,
|
||
&DomainSid,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
SaveStat = rc;
|
||
|
||
if (!NT_SUCCESS(NtStatus)) {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_ACCOUNT_DOMAIN
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_ACCOUNT_DOMAIN);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_PASSWORD_INFO |
|
||
SCE_RSOP_LOCKOUT_INFO |
|
||
SCE_RSOP_LOGOFF_INFO |
|
||
SCE_RSOP_ADMIN_INFO |
|
||
SCE_RSOP_GUEST_INFO,
|
||
rc,
|
||
NULL,
|
||
0,
|
||
0);
|
||
|
||
return( ScepDosErrorToSceStatus(rc) );
|
||
}
|
||
|
||
//
|
||
// if this is policy propagation, we need to open the sections for
|
||
// updating undo settings if this is not domain controller
|
||
// *** on DCs, domain account policy can't be reset'ed to tattoo
|
||
// on each individual DC. So there is no point to query/save tattoo values
|
||
//
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szSystemAccess,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
}
|
||
|
||
//
|
||
// if there is pending notifications for SAM policy
|
||
// ignore policy prop for SAM
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(QueueFlag & SCE_QUEUE_INFO_SAM) ) {
|
||
|
||
ScepLogOutput3(0, 0, SCESRV_POLICY_PENDING_SAM);
|
||
|
||
rc = ERROR_IO_PENDING;
|
||
PendingRc = rc;
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_PASSWORD_INFO |
|
||
SCE_RSOP_LOCKOUT_INFO |
|
||
SCE_RSOP_LOGOFF_INFO,
|
||
rc,
|
||
NULL,
|
||
0,
|
||
0);
|
||
goto OtherSettings;
|
||
|
||
}
|
||
|
||
//
|
||
// Get the current password settings...
|
||
//
|
||
|
||
Buffer=NULL;
|
||
NtStatus = SamQueryInformationDomain(
|
||
DomainHandle,
|
||
DomainPasswordInformation,
|
||
&Buffer
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
rc = ERROR_SUCCESS;
|
||
|
||
// allocate buffer for the tattoo values if necessary
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_PASS_KEYS*sizeof(SCE_TATTOO_KEYS));
|
||
|
||
if ( !pTattooKeys ) {
|
||
ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
|
||
}
|
||
}
|
||
|
||
bFlagSet = FALSE;
|
||
|
||
if ( (pScpInfo->MinimumPasswordLength != SCE_NO_VALUE) ) {
|
||
|
||
//
|
||
// for domain controllers, always use hardcode value as the initial tattoo value
|
||
//
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"MinimumPasswordLength", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_MIN_PASS_LEN :
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength);
|
||
|
||
if ( ((USHORT)(pScpInfo->MinimumPasswordLength) != ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength) ) {
|
||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordLength = (USHORT)(pScpInfo->MinimumPasswordLength);
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
|
||
}
|
||
if ( (pScpInfo->PasswordHistorySize != SCE_NO_VALUE) ) {
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"PasswordHistorySize", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_PASS_SIZE : ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength);
|
||
|
||
if ( ((USHORT)(pScpInfo->PasswordHistorySize) != ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength ) ) {
|
||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordHistoryLength = (USHORT)(pScpInfo->PasswordHistorySize);
|
||
bFlagSet = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( pScpInfo->MaximumPasswordAge == SCE_FOREVER_VALUE ) {
|
||
|
||
RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart /
|
||
(LONGLONG)(10000000L)) );
|
||
RegData /= 3600;
|
||
RegData /= 24;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"MaximumPasswordAge", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_MAX_PASS_AGE : RegData);
|
||
|
||
if ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.HighPart != MINLONG ||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.LowPart != 0 ) {
|
||
|
||
//
|
||
// Maximum LARGE_INTEGER .ie. never
|
||
//
|
||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.HighPart = MINLONG;
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.LowPart = 0;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
|
||
} else if ( pScpInfo->MaximumPasswordAge != SCE_NO_VALUE ) {
|
||
|
||
RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart /
|
||
(LONGLONG)(10000000L)) );
|
||
RegData /= 3600;
|
||
RegData /= 24;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"MaximumPasswordAge", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_MAX_PASS_AGE : RegData);
|
||
|
||
if ( RegData != pScpInfo->MaximumPasswordAge ) {
|
||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MaxPasswordAge.QuadPart = -1 *
|
||
(LONGLONG)pScpInfo->MaximumPasswordAge*24*3600 * 10000000L;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
|
||
if ( pScpInfo->MinimumPasswordAge != SCE_NO_VALUE ) {
|
||
|
||
RegData = (DWORD) (-1 * (((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordAge.QuadPart /
|
||
(LONGLONG)(10000000L)) );
|
||
RegData /= 3600;
|
||
RegData /= 24;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"MinimumPasswordAge", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_MIN_PASS_AGE : RegData);
|
||
|
||
if ( RegData != pScpInfo->MinimumPasswordAge ) {
|
||
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->MinPasswordAge.QuadPart = -1 *
|
||
(LONGLONG)pScpInfo->MinimumPasswordAge*24*3600 * 10000000L;
|
||
bFlagSet = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( pScpInfo->PasswordComplexity != SCE_NO_VALUE ) {
|
||
|
||
RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_COMPLEX) ? 1 : 0;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"PasswordComplexity", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_PASS_COMP : RegData);
|
||
|
||
if ( pScpInfo->PasswordComplexity != RegData ) {
|
||
|
||
if ( RegData == 0 )
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_COMPLEX;
|
||
else
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_COMPLEX;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
|
||
if ( pScpInfo->RequireLogonToChangePassword != SCE_NO_VALUE ) {
|
||
|
||
RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_NO_ANON_CHANGE) ? 1 : 0;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"RequireLogonToChangePassword", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_REQUIRE_LOGON : RegData);
|
||
|
||
if ( pScpInfo->RequireLogonToChangePassword != RegData ) {
|
||
|
||
if ( RegData == 0 )
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_NO_ANON_CHANGE;
|
||
else
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_NO_ANON_CHANGE;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
|
||
#if _WIN32_WINNT>=0x0500
|
||
if ( pScpInfo->ClearTextPassword != SCE_NO_VALUE ) {
|
||
|
||
RegData = ( ((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) ? 1 : 0;
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"ClearTextPassword", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_CLEAR_PASS : RegData);
|
||
|
||
if ( pScpInfo->ClearTextPassword != RegData ) {
|
||
|
||
if ( RegData == 0 )
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties |= DOMAIN_PASSWORD_STORE_CLEARTEXT;
|
||
else
|
||
((DOMAIN_PASSWORD_INFORMATION *)Buffer)->PasswordProperties &= ~DOMAIN_PASSWORD_STORE_CLEARTEXT;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
#endif
|
||
if ( bFlagSet ) {
|
||
|
||
NtStatus = SamSetInformationDomain(
|
||
DomainHandle,
|
||
DomainPasswordInformation,
|
||
Buffer
|
||
);
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
pTattooKeys && cTattooKeys ) {
|
||
|
||
//
|
||
// even if there is no change,
|
||
// we still need to check if some tattoo values should be deleted
|
||
//
|
||
ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_ARRAY, cTattooKeys);
|
||
|
||
//
|
||
// some policy is different than the system setting
|
||
// check if we should save the existing setting as the tattoo value
|
||
// also remove reset'ed tattoo policy
|
||
//
|
||
ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
|
||
|
||
}
|
||
|
||
if ( pTattooKeys ) {
|
||
ScepFree(pTattooKeys);
|
||
pTattooKeys = NULL;
|
||
}
|
||
cTattooKeys = 0;
|
||
|
||
SamFreeMemory(Buffer);
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
//
|
||
// if error, just log it and continue
|
||
//
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_PASSWORD
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_PASSWORD);
|
||
}
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_PASSWORD);
|
||
}
|
||
|
||
} else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_ERROR_QUERY_PASSWORD
|
||
);
|
||
} else {
|
||
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_PASSWORD);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_PASSWORD_INFO, rc, NULL, 0, 0);
|
||
|
||
//
|
||
// Configure Lockout information
|
||
//
|
||
|
||
Buffer = NULL;
|
||
NtStatus = SamQueryInformationDomain(
|
||
DomainHandle,
|
||
DomainLockoutInformation,
|
||
&Buffer
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
rc = ERROR_SUCCESS;
|
||
|
||
// allocate buffer for the tattoo values if necessary
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_LOCKOUT_KEYS*sizeof(SCE_TATTOO_KEYS));
|
||
|
||
if ( !pTattooKeys ) {
|
||
ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
|
||
}
|
||
}
|
||
|
||
bFlagSet = FALSE;
|
||
if ( (pScpInfo->LockoutBadCount != SCE_NO_VALUE) ) {
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"LockoutBadCount", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_COUNT : ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold);
|
||
|
||
if ( ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold != (USHORT)(pScpInfo->LockoutBadCount) ) ) {
|
||
|
||
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold = (USHORT)(pScpInfo->LockoutBadCount);
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->ResetLockoutCount != SCE_NO_VALUE) &&
|
||
( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold > 0 ) ) {
|
||
|
||
RegData = (DWORD) (-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutObservationWindow.QuadPart /
|
||
(60 * 10000000L) );
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"ResetLockoutCount", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_RESET : RegData);
|
||
|
||
if ( RegData != pScpInfo->ResetLockoutCount ) {
|
||
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutObservationWindow.QuadPart = -1 *
|
||
(LONGLONG)pScpInfo->ResetLockoutCount * 60 * 10000000L;
|
||
bFlagSet = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutThreshold > 0 ) {
|
||
|
||
if ( pScpInfo->LockoutDuration != SCE_NO_VALUE ) {
|
||
|
||
RegData = (DWORD)(-1 * ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.QuadPart /
|
||
(60 * 10000000L) );
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"LockoutDuration", ConfigOptions,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_LOCK_DURATION : RegData);
|
||
|
||
}
|
||
|
||
if ( pScpInfo->LockoutDuration == SCE_FOREVER_VALUE ) {
|
||
|
||
if ( ((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.HighPart != MINLONG ||
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.LowPart != 0 ) {
|
||
//
|
||
// forever
|
||
//
|
||
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.HighPart = MINLONG;
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.LowPart = 0;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
|
||
} else if ( pScpInfo->LockoutDuration != SCE_NO_VALUE ) {
|
||
|
||
if ( RegData != pScpInfo->LockoutDuration ) {
|
||
|
||
((DOMAIN_LOCKOUT_INFORMATION *)Buffer)->LockoutDuration.QuadPart = -1 *
|
||
(LONGLONG)pScpInfo->LockoutDuration * 60 * 10000000L;
|
||
bFlagSet = TRUE;
|
||
|
||
}
|
||
}
|
||
} else {
|
||
//
|
||
// make sure to delete these two tattoo values if they exist
|
||
//
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"ResetLockoutCount", ConfigOptions,
|
||
SCE_NO_VALUE);
|
||
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"LockoutDuration", ConfigOptions,
|
||
SCE_NO_VALUE);
|
||
}
|
||
|
||
if ( bFlagSet ) {
|
||
NtStatus = SamSetInformationDomain(
|
||
DomainHandle,
|
||
DomainLockoutInformation,
|
||
Buffer
|
||
);
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
}
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
pTattooKeys && cTattooKeys ) {
|
||
|
||
//
|
||
// even if there is no change
|
||
// we still need to check if some of the tattoo values should be deleted
|
||
//
|
||
ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_ARRAY, cTattooKeys);
|
||
//
|
||
// some policy is different than the system setting
|
||
// check if we should save the existing setting as the tattoo value
|
||
// also remove reset'ed tattoo policy
|
||
//
|
||
ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
|
||
}
|
||
|
||
if ( pTattooKeys ) {
|
||
ScepFree(pTattooKeys);
|
||
pTattooKeys = NULL;
|
||
}
|
||
cTattooKeys = 0;
|
||
|
||
SamFreeMemory(Buffer);
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
//
|
||
// if error, just log it and continue
|
||
//
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_PASSWORD
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LOCKOUT);
|
||
}
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
} else if ( bFlagSet ) {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_LOCKOUT);
|
||
}
|
||
} else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_ERROR_QUERY_LOCKOUT
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_LOCKOUT);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_LOCKOUT_INFO, rc, NULL, 0, 0);
|
||
|
||
//
|
||
// Force Logoff when hour expire
|
||
//
|
||
|
||
if ( pScpInfo->ForceLogoffWhenHourExpire != SCE_NO_VALUE ) {
|
||
|
||
Buffer = NULL;
|
||
NtStatus = SamQueryInformationDomain(
|
||
DomainHandle,
|
||
DomainLogoffInformation,
|
||
&Buffer
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
rc = ERROR_SUCCESS;
|
||
|
||
bFlagSet = FALSE;
|
||
RegData = pScpInfo->ForceLogoffWhenHourExpire;
|
||
|
||
if ( pScpInfo->ForceLogoffWhenHourExpire == 1 ) { // yes
|
||
if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart != 0 ||
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart != 0 ) {
|
||
|
||
RegData = 0;
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart = 0;
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart = 0;
|
||
bFlagSet = TRUE;
|
||
}
|
||
} else {
|
||
if ( ((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart != MINLONG ||
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart != 0 ) {
|
||
|
||
RegData = 1;
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.HighPart = MINLONG;
|
||
((DOMAIN_LOGOFF_INFORMATION *)Buffer)->ForceLogoff.LowPart = 0;
|
||
bFlagSet = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( bFlagSet ) {
|
||
|
||
NtStatus = SamSetInformationDomain(
|
||
DomainHandle,
|
||
DomainLogoffInformation,
|
||
Buffer
|
||
);
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
//
|
||
// some policy is different than the system setting or this is a domain controller
|
||
// check if we should save the existing setting as the tattoo value
|
||
// also remove reset'ed tattoo policy
|
||
//
|
||
ScepTattooManageOneIntValue(hSectionDomain, hSectionTattoo,
|
||
(PWSTR)L"ForceLogoffWhenHourExpire",
|
||
0,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_FORCE_LOGOFF : RegData, rc);
|
||
|
||
}
|
||
SamFreeMemory(Buffer);
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LOGOFF
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LOGOFF);
|
||
}
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_LOGOFF);
|
||
}
|
||
|
||
} else if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_ERROR_QUERY_LOGOFF
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_LOGOFF);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_LOGOFF_INFO, rc, NULL, 0, 0);
|
||
|
||
}
|
||
|
||
OtherSettings:
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
SaveStat = rc;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Rename Administrator/Guest account
|
||
//
|
||
|
||
if ( NULL != pScpInfo->NewAdministratorName ) {
|
||
|
||
NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
|
||
pScpInfo->NewAdministratorName,
|
||
0,
|
||
SCE_RENAME_ADMIN,
|
||
ConfigOptions,
|
||
hSectionDomain,
|
||
hSectionTattoo
|
||
);
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) )
|
||
ScepLogOutput3(0, 0, SCEDLL_SCP_RENAME_ADMIN,
|
||
pScpInfo->NewAdministratorName );
|
||
else {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_ADMINISTRATOR
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_ADMINISTRATOR);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_ADMIN_INFO, rc, NULL, 0, 0);
|
||
}
|
||
|
||
if ( NULL != pScpInfo->NewGuestName ) {
|
||
|
||
NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
|
||
pScpInfo->NewGuestName,
|
||
0,
|
||
SCE_RENAME_GUEST,
|
||
ConfigOptions,
|
||
hSectionDomain,
|
||
hSectionTattoo
|
||
);
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) ) {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_RENAME_GUEST,
|
||
pScpInfo->NewGuestName );
|
||
} else {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_GUEST
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1,rc, SCEDLL_SCP_ERROR_GUEST);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_GUEST_INFO, rc, NULL, 0, 0);
|
||
}
|
||
|
||
//
|
||
// LSAAnonymousNameLookup
|
||
//
|
||
|
||
if ( pScpInfo->LSAAnonymousNameLookup != SCE_NO_VALUE ) {
|
||
|
||
BOOL bImpliedOldLSAPolicyDifferent = FALSE;
|
||
DWORD dwImpliedOldLSAAnonymousNameLookup = pScpInfo->LSAAnonymousNameLookup;
|
||
|
||
rc = ScepConfigureLSAPolicyObject(
|
||
pScpInfo->LSAAnonymousNameLookup,
|
||
ConfigOptions,
|
||
pErrLog,
|
||
&bImpliedOldLSAPolicyDifferent
|
||
);
|
||
|
||
if (bImpliedOldLSAPolicyDifferent) {
|
||
dwImpliedOldLSAAnonymousNameLookup = (pScpInfo->LSAAnonymousNameLookup ? 0 : 1);
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooManageOneIntValue(hSectionDomain,
|
||
hSectionTattoo,
|
||
(PWSTR)L"LSAAnonymousNameLookup",
|
||
0,
|
||
(ProductType == NtProductLanManNt) ? SCEDCPOL_LSA_ANON_LOOKUP : dwImpliedOldLSAAnonymousNameLookup, rc);
|
||
|
||
}
|
||
|
||
if ( rc != ERROR_SUCCESS ) {
|
||
|
||
SaveStat = rc;
|
||
|
||
}
|
||
else {
|
||
|
||
ScepLogOutput3(1, 0, SCEDLL_SCP_LSAPOLICY);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_LSA_POLICY_INFO, rc, NULL, 0, 0);
|
||
}
|
||
|
||
|
||
//
|
||
// disable admin account
|
||
//
|
||
|
||
if ( pScpInfo->EnableAdminAccount != SCE_NO_VALUE ) {
|
||
|
||
NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
|
||
NULL,
|
||
(pScpInfo->EnableAdminAccount > 0) ? 0 : 1,
|
||
SCE_DISABLE_ADMIN,
|
||
ConfigOptions,
|
||
hSectionDomain,
|
||
hSectionTattoo
|
||
);
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) ) {
|
||
|
||
ScepLogOutput3(0, 0, pScpInfo->EnableAdminAccount ?
|
||
SCEDLL_SCP_ENABLE_ADMIN : SCEDLL_SCP_DISABLE_ADMIN);
|
||
|
||
} else {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_DISABLE_ADMIN
|
||
);
|
||
} else if ( STATUS_SPECIAL_ACCOUNT == NtStatus ) {
|
||
|
||
ScepLogOutput3(0, 0, SCEDLL_SCP_ADMIN_NOT_ALLOWED);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_DISABLE_ADMIN);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_DISABLE_ADMIN_INFO, rc, NULL, 0, 0);
|
||
}
|
||
|
||
//
|
||
// disable guest account
|
||
//
|
||
|
||
if ( pScpInfo->EnableGuestAccount != SCE_NO_VALUE ) {
|
||
|
||
NtStatus = ScepManageAdminGuestAccounts(DomainHandle,
|
||
NULL,
|
||
(pScpInfo->EnableGuestAccount > 0) ? 0 : 1,
|
||
SCE_DISABLE_GUEST,
|
||
ConfigOptions,
|
||
hSectionDomain,
|
||
hSectionTattoo
|
||
);
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) ) {
|
||
|
||
ScepLogOutput3(0, 0, pScpInfo->EnableGuestAccount ?
|
||
SCEDLL_SCP_ENABLE_GUEST : SCEDLL_SCP_DISABLE_GUEST);
|
||
|
||
} else {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) &&
|
||
pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_DISABLE_GUEST
|
||
);
|
||
} else if ( STATUS_SPECIAL_ACCOUNT == NtStatus ) {
|
||
ScepLogOutput3(0, 0, SCEDLL_SCP_GUEST_NOT_ALLOWED);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_DISABLE_GUEST);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
// goto GETOUT;
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_DISABLE_GUEST_INFO, rc, NULL, 0, 0);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Other Registry Key Values
|
||
//
|
||
bFlagSet = FALSE;
|
||
|
||
if ( bFlagSet && rc == NO_ERROR )
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_OTHER_POLICY);
|
||
|
||
|
||
if ( hSectionDomain ) SceJetCloseSection( &hSectionDomain, TRUE );
|
||
if ( hSectionTattoo ) SceJetCloseSection( &hSectionTattoo, TRUE );
|
||
|
||
//
|
||
// Clear out memory and return
|
||
//
|
||
|
||
SamCloseHandle( DomainHandle );
|
||
SamCloseHandle( ServerHandle );
|
||
if ( DomainSid != NULL )
|
||
SamFreeMemory(DomainSid);
|
||
|
||
if ( SaveStat == ERROR_SUCCESS )
|
||
SaveStat = PendingRc;
|
||
|
||
return(ScepDosErrorToSceStatus(SaveStat));
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
ScepManageAdminGuestAccounts(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PWSTR NewName,
|
||
IN DWORD DisableFlag,
|
||
IN DWORD AccountType,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCESECTION hSectionDomain OPTIONAL,
|
||
IN PSCESECTION hSectionTattoo OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine renames the specified account's name to the new account name
|
||
in the account domain.
|
||
|
||
Arguments:
|
||
|
||
DomainHandle - The account domain handle
|
||
|
||
NewName - New account name to rename to
|
||
|
||
AccountType - indicate it is Administrator account or Guest account
|
||
SCE_RENAME_ADMIN
|
||
SCE_RENAME_GUEST
|
||
SCE_DISABLE_ADMIN
|
||
SCE_DISABLE_GUEST
|
||
|
||
Return value:
|
||
|
||
NTSTATUS error codes
|
||
|
||
-- */
|
||
{
|
||
SAM_HANDLE UserHandle1=NULL;
|
||
USER_NAME_INFORMATION Buffer1, *Buffer=NULL;
|
||
PVOID pInfoBuffer=NULL;
|
||
USER_CONTROL_INFORMATION *pControlBuffer=NULL;
|
||
NTSTATUS NtStatus;
|
||
ULONG UserId;
|
||
PWSTR TempStr=NULL;
|
||
DWORD cb;
|
||
PWSTR KeyName;
|
||
BOOL bDisable = FALSE;
|
||
|
||
|
||
//
|
||
// find the right userid for the account
|
||
//
|
||
|
||
switch ( AccountType ) {
|
||
case SCE_RENAME_ADMIN:
|
||
UserId = DOMAIN_USER_RID_ADMIN;
|
||
KeyName = (PWSTR)L"NewAdministratorName";
|
||
break;
|
||
case SCE_RENAME_GUEST:
|
||
UserId = DOMAIN_USER_RID_GUEST;
|
||
KeyName = (PWSTR)L"NewGuestName";
|
||
break;
|
||
case SCE_DISABLE_ADMIN:
|
||
UserId = DOMAIN_USER_RID_ADMIN;
|
||
KeyName = (PWSTR)L"EnableAdminAccount";
|
||
bDisable = TRUE;
|
||
break;
|
||
case SCE_DISABLE_GUEST:
|
||
UserId = DOMAIN_USER_RID_GUEST;
|
||
KeyName = (PWSTR)L"EnableGuestAccount";
|
||
bDisable = TRUE;
|
||
break;
|
||
default:
|
||
return(STATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
NtStatus = SamOpenUser(
|
||
DomainHandle,
|
||
MAXIMUM_ALLOWED, //USER_ALL_ACCESS,
|
||
UserId,
|
||
&UserHandle1
|
||
);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) ) {
|
||
|
||
NtStatus = SamQueryInformationUser(
|
||
UserHandle1,
|
||
bDisable? UserControlInformation : UserNameInformation,
|
||
&pInfoBuffer
|
||
);
|
||
|
||
if ( NT_SUCCESS( NtStatus ) ) {
|
||
|
||
if ( bDisable ) {
|
||
//
|
||
// disable the accounts
|
||
//
|
||
pControlBuffer = (USER_CONTROL_INFORMATION *)pInfoBuffer;
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
hSectionDomain && hSectionTattoo &&
|
||
(ProductType != NtProductLanManNt) ) {
|
||
//
|
||
// do not save tattoo value of account controls for domain controllers
|
||
//
|
||
ScepTattooManageOneIntValue(hSectionDomain, hSectionTattoo,
|
||
KeyName, 0,
|
||
(pControlBuffer->UserAccountControl & USER_ACCOUNT_DISABLED) ? 0 : 1,
|
||
RtlNtStatusToDosError(NtStatus)
|
||
);
|
||
}
|
||
//
|
||
// compare the control flag with existing flag
|
||
// if it's different, set the new flag to the system
|
||
//
|
||
if ( DisableFlag != (pControlBuffer->UserAccountControl & USER_ACCOUNT_DISABLED) ) {
|
||
|
||
pControlBuffer->UserAccountControl &= ~USER_ACCOUNT_DISABLED;
|
||
pControlBuffer->UserAccountControl |= DisableFlag;
|
||
|
||
NtStatus = SamSetInformationUser(
|
||
UserHandle1,
|
||
UserControlInformation,
|
||
(PVOID)pControlBuffer
|
||
);
|
||
|
||
}
|
||
|
||
} else {
|
||
//
|
||
// rename the accounts
|
||
//
|
||
Buffer = (USER_NAME_INFORMATION *)pInfoBuffer;
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
hSectionDomain && hSectionTattoo &&
|
||
(ProductType != NtProductLanManNt) ) {
|
||
//
|
||
// do not save off account names for domain controllers
|
||
//
|
||
ScepTattooManageOneStringValue(hSectionDomain, hSectionTattoo,
|
||
KeyName, 0,
|
||
Buffer->UserName.Buffer,
|
||
Buffer->UserName.Length/sizeof(WCHAR),
|
||
RtlNtStatusToDosError(NtStatus)
|
||
);
|
||
}
|
||
//
|
||
// compare the new name with existing name
|
||
// if it's different, set the new name to the system
|
||
//
|
||
if ( (Buffer->UserName.Length/sizeof(WCHAR) != wcslen(NewName)) ||
|
||
(_wcsnicmp(NewName, Buffer->UserName.Buffer, Buffer->UserName.Length/sizeof(WCHAR)) != 0) ) {
|
||
|
||
//
|
||
// keep the full name and copy the new account name to username field
|
||
//
|
||
cb = Buffer->FullName.Length+2;
|
||
TempStr = (PWSTR)ScepAlloc( (UINT)0, cb);
|
||
if ( TempStr == NULL ) {
|
||
NtStatus = STATUS_NO_MEMORY;
|
||
} else {
|
||
RtlMoveMemory( TempStr, Buffer->FullName.Buffer, cb );
|
||
RtlCreateUnicodeString(&(Buffer1.FullName), TempStr);
|
||
RtlCreateUnicodeString(&(Buffer1.UserName), NewName );
|
||
|
||
NtStatus = SamSetInformationUser(
|
||
UserHandle1,
|
||
UserNameInformation,
|
||
(PVOID)&Buffer1
|
||
);
|
||
|
||
RtlFreeUnicodeString( &(Buffer1.FullName) );
|
||
RtlFreeUnicodeString( &(Buffer1.UserName) );
|
||
ScepFree(TempStr);
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
SamFreeMemory(pInfoBuffer);
|
||
SamCloseHandle( UserHandle1 );
|
||
}
|
||
|
||
return( NtStatus );
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivileges(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN BOOL bCreateBuiltinAccount,
|
||
IN DWORD Options,
|
||
IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
This routine configure the system security in the area of user privilege/rights.
|
||
|
||
Arguments:
|
||
|
||
ppPrivilegeAssigned - The address of the pointer to a list of user privilege/rights as
|
||
specified in the SCP inf file.
|
||
Note, account in the list is a pointer to SID.
|
||
|
||
bCreateBuiltinAccount - if TRUE, builtin accounts (server ops, account ops, print ops,
|
||
power users) will be created if they don't exist
|
||
|
||
Options - configuration options
|
||
|
||
pIgnoreAccounts - the accounts to ignore in configuration (because of pending notifications)
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
|
||
DWORD rc;
|
||
DWORD PrivLowMask=0;
|
||
DWORD PrivHighMask=0;
|
||
|
||
if ( !ppPrivilegeAssigned ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// get privilege mask from the template
|
||
//
|
||
rc = ScepGetPrivilegeMask(hProfile,
|
||
(Options & SCE_POLICY_TEMPLATE) ? SCE_ENGINE_SCP :SCE_ENGINE_SMP,
|
||
&PrivLowMask,
|
||
&PrivHighMask
|
||
);
|
||
|
||
if ( (rc != ERROR_SUCCESS) && (PrivLowMask == 0) && (PrivHighMask == 0) ) {
|
||
//
|
||
// it's likely not possible to fail here because
|
||
// the previous GetPrivileges succeeded.
|
||
// but if it failed, just return.
|
||
//
|
||
return(rc);
|
||
}
|
||
|
||
rc = ScepConfigurePrivilegesWithMask(ppPrivilegeAssigned,
|
||
bCreateBuiltinAccount,
|
||
Options,
|
||
PrivLowMask,
|
||
PrivHighMask,
|
||
NULL,
|
||
pIgnoreAccounts
|
||
);
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivilegesWithMask(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN BOOL bCreateBuiltinAccount,
|
||
IN DWORD Options,
|
||
IN DWORD LowMask,
|
||
IN DWORD HighMask,
|
||
IN OUT PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
|
||
IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
This routine configure the system security in the area of user privilege/rights.
|
||
|
||
Arguments:
|
||
|
||
ppPrivilegeAssigned - The address of the pointer to a list of user privilege/rights as
|
||
specified in the SCP inf file.
|
||
Note, account in the list is a pointer to SID.
|
||
|
||
bCreateBuiltinAccount - if TRUE, builtin accounts (server ops, account ops, print ops,
|
||
power users) will be created if they don't exist
|
||
|
||
Options - configuration options
|
||
|
||
PrivLowMask - the privileges (mask) to configure
|
||
|
||
PrivHighMask - more privileges (mask) to configure
|
||
|
||
pErrLog - output error info
|
||
|
||
pIgnoreAccounts - the accounts to ignore in configuration (because of pending notifications)
|
||
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
|
||
TCHAR MsgBuf[256];
|
||
DWORD rc=ERROR_SUCCESS;
|
||
DWORD SaveStat=NO_ERROR;
|
||
DWORD PendingRc=NO_ERROR;
|
||
NTSTATUS NtStatus;
|
||
|
||
LSA_HANDLE PolicyHandle=NULL;
|
||
BYTE SidBuffer[256];
|
||
PSID AccountSid=NULL;
|
||
DWORD SidLength;
|
||
SID_NAME_USE UserType;
|
||
DWORD DomainLength;
|
||
|
||
PSCE_PRIVILEGE_VALUE_LIST pPrivilege;
|
||
DWORD nPrivCount=0;
|
||
PSCE_PRIVILEGE_VALUE_LIST pRemAccounts=NULL;
|
||
PWSTR StringSid=NULL;
|
||
|
||
DWORD ConfigStatus[64];
|
||
DWORD DonePrivLowMask=0;
|
||
DWORD DonePrivHighMask=0;
|
||
DWORD PrivLowMask=0;
|
||
DWORD PrivHighMask=0;
|
||
|
||
if ( !ppPrivilegeAssigned ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// user privilege/rights -- LSA Server
|
||
// open the lsa policy first
|
||
//
|
||
|
||
//
|
||
// since client RSOP logging side uses test-and-set for success/failure, the first error (if any)for
|
||
// a particular privilege will always be seen
|
||
//
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
return(SCESTATUS_SERVICE_NOT_SUPPORT);
|
||
}
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) && LsaPrivatePolicy ) {
|
||
|
||
PolicyHandle = LsaPrivatePolicy;
|
||
|
||
if ( !ScepSplayTreeEmpty(pIgnoreAccounts) )
|
||
ScepNotifyLogPolicy(0, FALSE, L"Configuration will ignore pending notified accounts", 0, 0, NULL );
|
||
else
|
||
ScepNotifyLogPolicy(0, FALSE, L"No pending notified accounts", 0, 0, NULL );
|
||
|
||
} else {
|
||
|
||
NtStatus = ScepOpenLsaPolicy(
|
||
MAXIMUM_ALLOWED, //GENERIC_ALL,
|
||
&PolicyHandle,
|
||
(Options & ( SCE_POLICY_TEMPLATE | SCE_SYSTEM_DB) ) ? TRUE : FALSE // do not notify policy filter if within policy prop
|
||
);
|
||
if (NtStatus != ERROR_SUCCESS) {
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_LSA_POLICY
|
||
);
|
||
} else {
|
||
|
||
ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
goto Done;
|
||
}
|
||
}
|
||
|
||
AccountSid = (PSID)SidBuffer;
|
||
|
||
ScepIsDomainLocal(NULL);
|
||
|
||
PrivLowMask = LowMask;
|
||
PrivHighMask = HighMask;
|
||
|
||
//
|
||
// make sure Authenticated Users, Everyone and Enterprise Controllers have appropriate rights
|
||
// ignore any error occurred
|
||
//
|
||
|
||
(void)ScepCheckNetworkLogonRights(PolicyHandle,
|
||
&PrivLowMask,
|
||
&PrivHighMask,
|
||
ppPrivilegeAssigned);
|
||
|
||
//
|
||
// save the old privilege settings
|
||
//
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooSavePrivilegeValues(hProfile, PolicyHandle,
|
||
PrivLowMask, PrivHighMask,
|
||
Options
|
||
);
|
||
// initialize
|
||
for ( int i=0;i<64;i++) ConfigStatus[i] = (DWORD)-1;
|
||
|
||
}
|
||
|
||
//
|
||
// other area accounts to remove for the privilege mask
|
||
//
|
||
|
||
NtStatus = ScepBuildAccountsToRemove(
|
||
PolicyHandle,
|
||
PrivLowMask, // the privileges to look up
|
||
PrivHighMask,
|
||
SCE_BUILD_IGNORE_UNKNOWN | SCE_BUILD_ACCOUNT_SID,
|
||
*ppPrivilegeAssigned, // accounts in the template already
|
||
Options,
|
||
pIgnoreAccounts,
|
||
&pRemAccounts // accounts to remove
|
||
);
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
(NtStatus == STATUS_PENDING) ) {
|
||
|
||
// this error is to make sure that policy propagation will be invoked again
|
||
ScepLogOutput3(0,0, SCESRV_POLICY_PENDING_REMOVE_RIGHTS);
|
||
|
||
PendingRc = ERROR_IO_PENDING;
|
||
NtStatus = STATUS_SUCCESS;
|
||
}
|
||
|
||
if ( NT_SUCCESS(NtStatus) && pRemAccounts ) {
|
||
//
|
||
// remove user rights for the accounts first
|
||
//
|
||
|
||
for (pPrivilege = pRemAccounts;
|
||
pPrivilege != NULL;
|
||
pPrivilege = pPrivilege->Next ) {
|
||
|
||
if ( pPrivilege->PrivLowPart == 0 &&
|
||
pPrivilege->PrivHighPart == 0 ) {
|
||
continue;
|
||
}
|
||
//
|
||
// Note: even though it's an invalid account SID,
|
||
// we still should remove it from the system
|
||
// because this account is enumerated from current system.
|
||
//
|
||
/*
|
||
if ( !ScepValidSid( (PSID)(pPrivilege->Name) ) ) {
|
||
continue;
|
||
}
|
||
*/
|
||
//
|
||
// get the user/group sid string (to display)
|
||
//
|
||
ConvertSidToStringSid( (PSID)(pPrivilege->Name), &StringSid );
|
||
|
||
if ( !(Options & SCE_SYSTEM_SETTINGS) ) {
|
||
|
||
//
|
||
// lookup for the user/group name. If it does not exist
|
||
// log an error and continue ? (or stop ?)
|
||
//
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, StringSid ? StringSid : L"SID");
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
SaveStat = ERROR_NOT_SUPPORTED;
|
||
break;
|
||
}
|
||
}
|
||
|
||
DonePrivHighMask |= (pPrivilege->PrivHighPart & PrivHighMask);
|
||
DonePrivLowMask |= (pPrivilege->PrivLowPart & PrivLowMask);
|
||
|
||
//
|
||
// remove the rights
|
||
//
|
||
NtStatus = ScepAddOrRemoveAccountRights(
|
||
PolicyHandle,
|
||
(PSID)(pPrivilege->Name),
|
||
FALSE,
|
||
pPrivilege->PrivLowPart & PrivLowMask,
|
||
pPrivilege->PrivHighPart & PrivHighMask
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
|
||
if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_CONFIGURE,
|
||
StringSid ? StringSid : L"SID"
|
||
);
|
||
} else {
|
||
|
||
ScepLogOutput3(1,rc,SCEDLL_SCP_ERROR_CONFIGURE,
|
||
StringSid ? StringSid : L"SID");
|
||
}
|
||
|
||
// update the tattoo status array
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
rc,
|
||
pPrivilege->PrivLowPart & PrivLowMask,
|
||
pPrivilege->PrivHighPart & PrivHighMask
|
||
);
|
||
}
|
||
|
||
SaveStat = rc;
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
rc,
|
||
NULL,
|
||
pPrivilege->PrivLowPart & PrivLowMask,
|
||
pPrivilege->PrivHighPart & PrivHighMask);
|
||
}
|
||
}
|
||
else if (Options & SCE_RSOP_CALLBACK) {
|
||
|
||
// success - has to be logged because some privilege may want to remove all accounts and
|
||
// processing is over at this point for such privileges
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
rc,
|
||
NULL,
|
||
pPrivilege->PrivLowPart & PrivLowMask,
|
||
pPrivilege->PrivHighPart & PrivHighMask);
|
||
|
||
}
|
||
|
||
|
||
if ( StringSid ) {
|
||
LocalFree(StringSid);
|
||
StringSid = NULL;
|
||
}
|
||
}
|
||
} else if ( !NT_SUCCESS(NtStatus) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
//
|
||
// fail to get the accounts to remove
|
||
// in this case, do not remove any tattoo value
|
||
//
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
PrivLowMask,
|
||
PrivHighMask
|
||
);
|
||
}
|
||
|
||
//
|
||
// free the remove account list
|
||
//
|
||
ScepFreePrivilegeValueList(pRemAccounts);
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
SaveStat = ERROR_NOT_SUPPORTED;
|
||
|
||
} else {
|
||
|
||
for (pPrivilege = *ppPrivilegeAssigned;
|
||
pPrivilege != NULL;
|
||
pPrivilege = pPrivilege->Next ) {
|
||
|
||
if ( !(Options & SCE_SYSTEM_SETTINGS) ) {
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
SaveStat = ERROR_NOT_SUPPORTED;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// remember the privileges we touched here
|
||
//
|
||
DonePrivHighMask |= pPrivilege->PrivHighPart;
|
||
DonePrivLowMask |= pPrivilege->PrivLowPart;
|
||
|
||
//
|
||
// note, this list may contain SID or name (when name can't
|
||
// be mapped to SID, such as in dcpromo case)
|
||
// so both name and SID must be handled here.
|
||
// lookup for the user/group name. If it does not exist
|
||
// log an error and continue ? (or stop ?)
|
||
//
|
||
|
||
if ( ScepValidSid( (PSID)(pPrivilege->Name) ) ) {
|
||
//
|
||
// get the user/group sid string (to display)
|
||
//
|
||
ConvertSidToStringSid( (PSID)(pPrivilege->Name), &StringSid );
|
||
|
||
if ( !(Options & SCE_SYSTEM_SETTINGS) &&
|
||
(nPrivCount < TICKS_PRIVILEGE) ) {
|
||
|
||
//
|
||
// only post maximum TICKS_PRIVILEGE ticks because that's the number
|
||
// remembers in the total ticks
|
||
//
|
||
|
||
ScepPostProgress(1, AREA_PRIVILEGES, StringSid);
|
||
nPrivCount++;
|
||
}
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, StringSid ? StringSid : L"SID");
|
||
|
||
//
|
||
// check if this account should be ignored
|
||
//
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) ) {
|
||
|
||
if ( ScepSplayValueExist( (PVOID)(pPrivilege->Name), pIgnoreAccounts) ) {
|
||
//
|
||
// this one should be ingored in this policy prop
|
||
//
|
||
NtStatus = STATUS_PENDING;
|
||
rc = ERROR_IO_PENDING;
|
||
|
||
ScepLogOutput3(1, 0, SCESRV_POLICY_PENDING_RIGHTS, StringSid ? StringSid : L"SID");
|
||
/*
|
||
} else {
|
||
|
||
ScepLogOutput2(1, 0, L"%s will be configured.", StringSid ? StringSid : L"SID");
|
||
*/ }
|
||
}
|
||
|
||
if ( NT_SUCCESS(NtStatus) && (STATUS_PENDING != NtStatus) ) {
|
||
|
||
NtStatus = ScepAdjustAccountPrivilegesRights(
|
||
PolicyHandle,
|
||
(PSID)(pPrivilege->Name),
|
||
pPrivilege->PrivLowPart,
|
||
PrivLowMask,
|
||
pPrivilege->PrivHighPart,
|
||
PrivHighMask,
|
||
Options
|
||
);
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
}
|
||
|
||
if ( !NT_SUCCESS(NtStatus) || (STATUS_PENDING == NtStatus) ) {
|
||
|
||
if ( (Options & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_CONFIGURE,
|
||
StringSid ? StringSid : L"SID"
|
||
);
|
||
|
||
} else if ( STATUS_PENDING != NtStatus) {
|
||
|
||
ScepLogOutput3(1, rc,
|
||
SCEDLL_SCP_ERROR_CONFIGURE,
|
||
StringSid ? StringSid : L"SID");
|
||
}
|
||
|
||
if ( ERROR_IO_PENDING == rc )
|
||
PendingRc = rc;
|
||
else
|
||
SaveStat = rc;
|
||
|
||
// update tattoo status array
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
rc,
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart
|
||
);
|
||
}
|
||
}
|
||
|
||
if ( StringSid ) {
|
||
LocalFree(StringSid);
|
||
StringSid = NULL;
|
||
}
|
||
|
||
} else if (Options & SCE_SYSTEM_SETTINGS ) {
|
||
//
|
||
// if work on system settings directly, the buffer must contain
|
||
// a SID. If not, it's an error
|
||
//
|
||
if ( pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
ERROR_NONE_MAPPED,
|
||
pErrLog,
|
||
SCEDLL_INVALID_GROUP,
|
||
pPrivilege->Name
|
||
);
|
||
}
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK ){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
ERROR_NONE_MAPPED,
|
||
NULL,
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart);
|
||
}
|
||
|
||
} else {
|
||
|
||
if ( !(Options & SCE_SYSTEM_SETTINGS) &&
|
||
(nPrivCount < TICKS_PRIVILEGE) ) {
|
||
|
||
//
|
||
// only post maximum TICKS_PRIVILEGE ticks because that's the number
|
||
// remembers in the total ticks
|
||
//
|
||
|
||
ScepPostProgress(1, AREA_PRIVILEGES, pPrivilege->Name);
|
||
nPrivCount++;
|
||
}
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, pPrivilege->Name);
|
||
|
||
SidLength=256;
|
||
DomainLength=256;
|
||
MsgBuf[0] = L'\0';
|
||
|
||
rc = ERROR_SUCCESS;
|
||
|
||
if ( wcschr(pPrivilege->Name, L'\\') == NULL ) {
|
||
//
|
||
// isolated accounts can't be resolved when reading the configuration
|
||
// no need to try now.
|
||
//
|
||
rc = ERROR_NONE_MAPPED;
|
||
|
||
} else if ( !LookupAccountName(
|
||
NULL,
|
||
pPrivilege->Name,
|
||
AccountSid,
|
||
&SidLength,
|
||
MsgBuf,
|
||
&DomainLength,
|
||
&UserType
|
||
)) {
|
||
|
||
rc = GetLastError();
|
||
}
|
||
|
||
if ( ERROR_SUCCESS != rc && bCreateBuiltinAccount ) {
|
||
|
||
//
|
||
// builtin accounts should be created here
|
||
//
|
||
rc = ScepCreateBuiltinAccountInLsa(
|
||
PolicyHandle,
|
||
pPrivilege->Name,
|
||
AccountSid
|
||
);
|
||
|
||
|
||
}
|
||
|
||
if ( ERROR_SUCCESS != rc ) {
|
||
|
||
ScepLogOutput3(1, rc, SCEDLL_CANNOT_FIND, pPrivilege->Name);
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
rc,
|
||
NULL,
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart);
|
||
}
|
||
|
||
//
|
||
// for accounts not mapped in the tattoo value
|
||
// ignore them so that the tattoo value can be removed
|
||
// update tattoo status array
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
0, // rc, see comment above
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart
|
||
);
|
||
}
|
||
|
||
if ( ERROR_TRUSTED_RELATIONSHIP_FAILURE == rc ) {
|
||
//
|
||
// this error is only returned when the name
|
||
// can't be found locally and trust relationship
|
||
// is broken on the domain
|
||
//
|
||
// for policy propagation, this failure is the same
|
||
// as account not found (locally).
|
||
//
|
||
rc = ERROR_NONE_MAPPED;
|
||
}
|
||
|
||
SaveStat = rc;
|
||
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// check if the account should be ignored
|
||
//
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) ) {
|
||
|
||
if ( ScepSplayValueExist( (PVOID)AccountSid, pIgnoreAccounts) ) {
|
||
//
|
||
// this one should be ingored in this policy prop
|
||
//
|
||
NtStatus = STATUS_PENDING;
|
||
rc = ERROR_IO_PENDING;
|
||
|
||
ScepLogOutput3(1, 0, SCESRV_POLICY_PENDING_RIGHTS, pPrivilege->Name);
|
||
/*
|
||
} else {
|
||
|
||
ScepLogOutput2(1, 0, L"%s will be configured.", pPrivilege->Name);
|
||
*/ }
|
||
}
|
||
|
||
if ( NT_SUCCESS(NtStatus) && (NtStatus != STATUS_PENDING) ) {
|
||
|
||
NtStatus = ScepAdjustAccountPrivilegesRights(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
pPrivilege->PrivLowPart,
|
||
PrivLowMask,
|
||
pPrivilege->PrivHighPart,
|
||
PrivHighMask,
|
||
Options
|
||
);
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
}
|
||
|
||
if ( !NT_SUCCESS(NtStatus) || (NtStatus == STATUS_PENDING) ) {
|
||
|
||
if ( STATUS_PENDING != NtStatus ) {
|
||
ScepLogOutput3(1, rc,
|
||
SCEDLL_SCP_ERROR_CONFIGURE,
|
||
pPrivilege->Name);
|
||
SaveStat = rc;
|
||
|
||
} else
|
||
PendingRc = rc;
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
rc,
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart
|
||
);
|
||
}
|
||
|
||
// goto Done;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
//
|
||
// at this point, if rc == ERROR_SUCCESS we should log all privs concerned with this acct
|
||
//
|
||
if ( rc == ERROR_SUCCESS &&
|
||
(Options & SCE_RSOP_CALLBACK) ){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
rc,
|
||
NULL,
|
||
pPrivilege->PrivLowPart,
|
||
pPrivilege->PrivHighPart);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( StringSid ) {
|
||
LocalFree(StringSid);
|
||
}
|
||
|
||
if ( !(Options & SCE_SYSTEM_SETTINGS) &&
|
||
(nPrivCount < TICKS_PRIVILEGE) ) {
|
||
|
||
ScepPostProgress(TICKS_PRIVILEGE-nPrivCount,
|
||
AREA_PRIVILEGES, NULL);
|
||
}
|
||
|
||
if ( SaveStat == ERROR_SUCCESS ) SaveStat = PendingRc;
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
0,
|
||
DonePrivLowMask,
|
||
DonePrivHighMask
|
||
);
|
||
if ( SaveStat == ERROR_SUCCESS ) {
|
||
//
|
||
// make sure all privileges are covered
|
||
//
|
||
ScepTattooUpdatePrivilegeArrayStatus(ConfigStatus,
|
||
0,
|
||
PrivLowMask,
|
||
PrivHighMask
|
||
);
|
||
}
|
||
|
||
ScepTattooRemovePrivilegeValues(hProfile,
|
||
ConfigStatus
|
||
);
|
||
|
||
}
|
||
|
||
if ( PolicyHandle != LsaPrivatePolicy )
|
||
LsaClose(PolicyHandle);
|
||
|
||
return( ScepDosErrorToSceStatus(SaveStat) );
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepGetPrivilegeMask(
|
||
IN PSCECONTEXT hProfile,
|
||
IN SCETYPE ProfileType,
|
||
OUT PDWORD pdLowMask,
|
||
OUT PDWORD pdHighMask
|
||
)
|
||
{
|
||
SCESTATUS rc;
|
||
PSCESECTION hSection=NULL;
|
||
DWORD nLowMask, nHighMask;
|
||
DWORD i;
|
||
|
||
|
||
if ( !hProfile || !pdHighMask || !pdLowMask ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// open the section
|
||
//
|
||
rc = ScepOpenSectionForName(
|
||
hProfile,
|
||
ProfileType,
|
||
szPrivilegeRights,
|
||
&hSection
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
ScepLogOutput3( 1,
|
||
ScepSceStatusToDosError(rc),
|
||
SCEERR_OPEN,
|
||
(LPTSTR)szPrivilegeRights
|
||
);
|
||
return(rc);
|
||
}
|
||
|
||
nLowMask = 0;
|
||
nHighMask = 0;
|
||
for ( i=0; i<cPrivCnt; i++) {
|
||
|
||
rc = SceJetSeek(
|
||
hSection,
|
||
SCE_Privileges[i].Name,
|
||
wcslen(SCE_Privileges[i].Name)*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
if ( i < 32 ) {
|
||
|
||
nLowMask |= (1 << i );
|
||
} else {
|
||
nHighMask |= (1 << ( i-32 ) );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// close the section
|
||
//
|
||
SceJetCloseSection( &hSection, TRUE );
|
||
|
||
*pdLowMask = nLowMask;
|
||
*pdHighMask = nHighMask;
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
DWORD
|
||
ScepCreateBuiltinAccountInLsa(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN LPTSTR AccountName,
|
||
OUT PSID AccountSid
|
||
)
|
||
{
|
||
DWORD rc;
|
||
WCHAR szTempString[256];
|
||
ULONG Rid;
|
||
|
||
if ( !PolicyHandle || !AccountName || !AccountSid ) {
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// figure out which constant SID to build
|
||
//
|
||
|
||
Rid = 0;
|
||
szTempString[0] = L'\0';
|
||
|
||
LoadString( MyModuleHandle,
|
||
SCESRV_ALIAS_NAME_SERVER_OPS,
|
||
szTempString,
|
||
256
|
||
);
|
||
if ( _wcsicmp(AccountName, szTempString) == 0 ) {
|
||
//
|
||
// it's server operators
|
||
//
|
||
Rid = DOMAIN_ALIAS_RID_SYSTEM_OPS;
|
||
|
||
} else {
|
||
|
||
szTempString[0] = L'\0';
|
||
|
||
LoadString( MyModuleHandle,
|
||
SCESRV_ALIAS_NAME_ACCOUNT_OPS,
|
||
szTempString,
|
||
256
|
||
);
|
||
if ( _wcsicmp(AccountName, szTempString) == 0 ) {
|
||
//
|
||
// it's account operators
|
||
//
|
||
Rid = DOMAIN_ALIAS_RID_ACCOUNT_OPS;
|
||
|
||
} else {
|
||
|
||
szTempString[0] = L'\0';
|
||
|
||
LoadString( MyModuleHandle,
|
||
SCESRV_ALIAS_NAME_PRINT_OPS,
|
||
szTempString,
|
||
256
|
||
);
|
||
|
||
if ( _wcsicmp(AccountName, szTempString) == 0 ) {
|
||
//
|
||
// it's print operators
|
||
//
|
||
Rid = DOMAIN_ALIAS_RID_PRINT_OPS;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( Rid ) {
|
||
//
|
||
// if found the account, build the SID
|
||
// create the account in lsa database and return the SID
|
||
//
|
||
SID_IDENTIFIER_AUTHORITY sidBuiltinAuthority = SECURITY_NT_AUTHORITY;
|
||
NTSTATUS NtStatus;
|
||
|
||
NtStatus = RtlInitializeSid( AccountSid, &sidBuiltinAuthority, 2 );
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
*(RtlSubAuthoritySid(AccountSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
|
||
*(RtlSubAuthoritySid(AccountSid, 1)) = Rid;
|
||
|
||
//
|
||
// create the account in Lsa
|
||
//
|
||
LSA_HANDLE AccountHandle=NULL;
|
||
|
||
NtStatus = LsaCreateAccount(PolicyHandle,
|
||
AccountSid,
|
||
ACCOUNT_ALL_ACCESS,
|
||
&AccountHandle
|
||
);
|
||
if ( STATUS_OBJECT_NAME_EXISTS == NtStatus ||
|
||
STATUS_OBJECT_NAME_COLLISION == NtStatus ) {
|
||
NtStatus = STATUS_SUCCESS;
|
||
}
|
||
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
if ( AccountHandle ) {
|
||
LsaClose(AccountHandle);
|
||
}
|
||
|
||
} else {
|
||
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
}
|
||
|
||
ScepLogOutput3(3,rc, SCESRV_ALIAS_CREATE, Rid);
|
||
|
||
} else {
|
||
|
||
rc = ERROR_NONE_MAPPED;
|
||
ScepLogOutput3(3,0, SCESRV_ALIAS_UNSUPPORTED, AccountName);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepBuildAccountsToRemove(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN DWORD PrivLowMask,
|
||
IN DWORD PrivHighMask,
|
||
IN DWORD dwBuildRule,
|
||
IN PSCE_PRIVILEGE_VALUE_LIST pTemplateList OPTIONAL,
|
||
IN DWORD Options OPTIONAL,
|
||
IN OUT PSCEP_SPLAY_TREE pIgnoreAccounts OPTIONAL,
|
||
OUT PSCE_PRIVILEGE_VALUE_LIST *pRemoveList
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Build a list of accounts which are not in pTemplateList for the privilege(s)
|
||
.
|
||
|
||
Note, the account(s) returned are in SID format when dwBuildRule requests
|
||
SCE_BUILD_ACCOUNT_SID, or in name format if the flag is not set.
|
||
|
||
The reason to return all name format (instead of name/SID string format) is due
|
||
to the default templates (defltdc.inf, dcup.inf) use names instead of SID string
|
||
for account domain accounts (such as the guest account). Even if a sid string
|
||
is used, the sid string and the account name will be treated as two different
|
||
accounts, which will be eventually duplicated out in configuration (where
|
||
account SID is used).
|
||
|
||
*/
|
||
{
|
||
//
|
||
// LSA buffers and variables
|
||
//
|
||
|
||
ULONG uAccountIndex = 0;
|
||
ULONG uCountOfRights = 0;
|
||
DWORD dwPrivLowThisAccount = 0;
|
||
DWORD dwPrivHighThisAccount = 0;
|
||
ULONG uEnumerationContext;
|
||
ULONG uPreferedMaximumLength;
|
||
ULONG uNumAccounts;
|
||
|
||
PLSA_ENUMERATION_INFORMATION aSids = NULL;
|
||
PLSA_TRANSLATED_NAME aNames=NULL;
|
||
PLSA_REFERENCED_DOMAIN_LIST pReferencedDomains=NULL;
|
||
PUNICODE_STRING aUserRights = NULL;
|
||
|
||
//
|
||
// other variables
|
||
//
|
||
|
||
NTSTATUS NtStatus;
|
||
NTSTATUS NtStatusSave=STATUS_SUCCESS;
|
||
NTSTATUS NtStatusRsop = STATUS_SUCCESS;
|
||
|
||
PSCE_NAME_LIST pAccountSidOrName=NULL;
|
||
PSCE_PRIVILEGE_VALUE_LIST pAccountNode=NULL;
|
||
PWSTR pwszStringSid = NULL;
|
||
|
||
SCE_NAME_LIST sNameList;
|
||
PSCE_NAME_LIST psList = &sNameList;
|
||
PWSTR StringSid=NULL;
|
||
BOOL bIgnored = FALSE;
|
||
|
||
if ( !PolicyHandle || !pRemoveList ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( PrivLowMask == 0 && PrivHighMask == 0 ) {
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// get all the accounts (potentially with multiple calls to LSA - the while loop)
|
||
//
|
||
|
||
//
|
||
// say each SID has 20 bytes and we'd like to get about SCEP_NUM_LSA_QUERY_SIDS
|
||
// (currently SCEP_NUM_LSA_QUERY_SIDS = 2000 SIDs at a time (approx 40 kB))
|
||
// we might need to tune SCEP_NUM_LSA_QUERY_SIDS depending on LSA memory performance
|
||
//
|
||
|
||
uPreferedMaximumLength = 20 * SCEP_NUM_LSA_QUERY_SIDS;
|
||
uEnumerationContext = 0;
|
||
uNumAccounts = 0;
|
||
|
||
NtStatus = LsaEnumerateAccounts(
|
||
PolicyHandle,
|
||
&uEnumerationContext,
|
||
(PVOID *)&aSids,
|
||
uPreferedMaximumLength,
|
||
&uNumAccounts
|
||
);
|
||
//
|
||
// in case there are more accounts returned, continue processing
|
||
// until all SIDs
|
||
// from LSA are exhausted
|
||
//
|
||
|
||
while ( NtStatus == STATUS_SUCCESS
|
||
&& uNumAccounts > 0
|
||
&& aSids != NULL) {
|
||
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
//
|
||
// convert SIDs to names if required
|
||
//
|
||
|
||
if ( !(dwBuildRule & SCE_BUILD_ACCOUNT_SID) &&
|
||
!(dwBuildRule & SCE_BUILD_ACCOUNT_SID_STRING) ) {
|
||
|
||
NtStatus = LsaLookupSids(
|
||
PolicyHandle,
|
||
uNumAccounts,
|
||
(PSID *)aSids,
|
||
&pReferencedDomains,
|
||
&aNames
|
||
);
|
||
}
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
BOOL bUsed;
|
||
|
||
for ( uAccountIndex = 0; uAccountIndex < uNumAccounts ; uAccountIndex++ ) {
|
||
|
||
ScepFree ( pwszStringSid );
|
||
pwszStringSid = NULL;
|
||
|
||
ScepConvertSidToPrefixStringSid(aSids[uAccountIndex].Sid, &pwszStringSid);
|
||
|
||
//
|
||
// check if this account is in the ignore list
|
||
//
|
||
if ( (Options & SCE_POLICY_TEMPLATE) ) {
|
||
|
||
if ( ScepSplayValueExist( (PVOID)(aSids[uAccountIndex].Sid), pIgnoreAccounts) ) {
|
||
//
|
||
// this one should be ingored in this policy prop
|
||
//
|
||
//
|
||
NtStatusRsop = STATUS_PENDING;
|
||
bIgnored = TRUE;
|
||
|
||
ScepLogOutput2(1, 0, L"\t\tIgnore %s.", pwszStringSid ? pwszStringSid : L"");
|
||
|
||
continue;
|
||
/*
|
||
} else {
|
||
|
||
ScepLogOutput2(1, 0, L"\tSome rights assigned to %s may be removed", pwszStringSid ? pwszStringSid : L"");
|
||
*/
|
||
}
|
||
}
|
||
|
||
uCountOfRights = 0;
|
||
aUserRights = NULL;
|
||
|
||
NtStatus = LsaEnumerateAccountRights(
|
||
PolicyHandle,
|
||
aSids[uAccountIndex].Sid,
|
||
&aUserRights,
|
||
&uCountOfRights
|
||
);
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
|
||
//
|
||
// log error for this account and continue with the next account
|
||
//
|
||
|
||
ScepLogOutput3(1,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
SCESRV_ERROR_QUERY_ACCOUNT_RIGHTS,
|
||
pwszStringSid);
|
||
|
||
if ( aUserRights ) {
|
||
|
||
LsaFreeMemory( aUserRights );
|
||
|
||
aUserRights = NULL;
|
||
|
||
}
|
||
|
||
NtStatusSave = NtStatus;
|
||
|
||
continue;
|
||
}
|
||
|
||
dwPrivLowThisAccount = 0;
|
||
dwPrivHighThisAccount = 0;
|
||
|
||
ScepBuildDwMaskFromStrArray(
|
||
aUserRights,
|
||
uCountOfRights,
|
||
&dwPrivLowThisAccount,
|
||
&dwPrivHighThisAccount
|
||
);
|
||
|
||
//
|
||
// if account has at least one user right after masking,
|
||
// we have to process it further
|
||
//
|
||
|
||
if ( (dwPrivLowThisAccount & PrivLowMask) ||
|
||
(dwPrivHighThisAccount & PrivHighMask) ) {
|
||
|
||
if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID ) {
|
||
//
|
||
// add the SID to the name list
|
||
//
|
||
(VOID) ScepAddSidToNameList(
|
||
&pAccountSidOrName,
|
||
aSids[uAccountIndex].Sid,
|
||
FALSE,
|
||
&bUsed);
|
||
|
||
} else if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID_STRING ) {
|
||
//
|
||
// add the SID in string format
|
||
//
|
||
if ( ERROR_SUCCESS == ScepConvertSidToPrefixStringSid(
|
||
aSids[uAccountIndex].Sid, &StringSid) ) {
|
||
|
||
sNameList.Name = StringSid;
|
||
sNameList.Next = NULL;
|
||
|
||
pAccountSidOrName = psList;
|
||
} // else out of memory, catch it later
|
||
|
||
} else {
|
||
|
||
//
|
||
// detect if the sid can't be mapped, there are two cases:
|
||
// 1) the domain can't be found, a string format of SID is returned
|
||
// 2) the domain is found. If the domain is builtin and the account
|
||
// name has all digits (the RID), then the builtin account can't be found
|
||
// the second case is solely for the server and DC accounts (PU, SO, AO, PO)
|
||
//
|
||
|
||
if ( (dwBuildRule & SCE_BUILD_IGNORE_UNKNOWN) &&
|
||
( aNames[uAccountIndex].Use == SidTypeInvalid ||
|
||
aNames[uAccountIndex].Use == SidTypeUnknown ) ) {
|
||
|
||
//
|
||
// this name is not mapped, ignore it and
|
||
// continue with the next account
|
||
//
|
||
|
||
if ( aUserRights ) {
|
||
|
||
LsaFreeMemory( aUserRights );
|
||
|
||
aUserRights = NULL;
|
||
|
||
}
|
||
|
||
NtStatusSave = NtStatus;
|
||
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// build the full name of each account
|
||
//
|
||
if ( pReferencedDomains->Entries > 0 && aNames[uAccountIndex].Use != SidTypeWellKnownGroup &&
|
||
pReferencedDomains->Domains != NULL &&
|
||
aNames[uAccountIndex].DomainIndex != -1 &&
|
||
(ULONG)(aNames[uAccountIndex].DomainIndex) < pReferencedDomains->Entries &&
|
||
ScepIsDomainLocalBySid(pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Sid) == FALSE &&
|
||
ScepIsDomainLocal(&pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name) == FALSE ) {
|
||
|
||
//
|
||
// add both domain name and account name
|
||
//
|
||
(VOID) ScepAddTwoNamesToNameList(
|
||
&pAccountSidOrName,
|
||
TRUE,
|
||
pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name.Buffer,
|
||
pReferencedDomains->Domains[aNames[uAccountIndex].DomainIndex].Name.Length/2,
|
||
aNames[uAccountIndex].Name.Buffer,
|
||
aNames[uAccountIndex].Name.Length/2);
|
||
} else {
|
||
//
|
||
// add only the account name
|
||
//
|
||
(VOID) ScepAddToNameList(
|
||
&pAccountSidOrName,
|
||
aNames[uAccountIndex].Name.Buffer,
|
||
aNames[uAccountIndex].Name.Length/2);
|
||
}
|
||
}
|
||
|
||
if ( pAccountSidOrName ) {
|
||
|
||
//
|
||
// if sid/name exists in the template list
|
||
// continue (the explicit mask takes care of remove)
|
||
// else
|
||
// add it to the remove list
|
||
//
|
||
|
||
for ( pAccountNode=pTemplateList;
|
||
pAccountNode != NULL;
|
||
pAccountNode = pAccountNode->Next ) {
|
||
|
||
if ( pAccountNode->Name == NULL ) {
|
||
continue;
|
||
}
|
||
|
||
if ( dwBuildRule & SCE_BUILD_ACCOUNT_SID ) {
|
||
|
||
if ( ScepValidSid( (PSID)(pAccountNode->Name) ) &&
|
||
RtlEqualSid( (PSID)(pAccountSidOrName->Name), (PSID)(pAccountNode->Name) ) ) {
|
||
break;
|
||
}
|
||
} else if ( _wcsicmp(pAccountNode->Name, pAccountSidOrName->Name) == 0 ) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// always need to add to the remove list since each sid/name
|
||
// is seen only once in the new algorithm
|
||
//
|
||
|
||
if ( pAccountNode == NULL ) {
|
||
|
||
pAccountNode = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc(
|
||
LPTR,
|
||
sizeof(SCE_PRIVILEGE_VALUE_LIST));
|
||
if ( pAccountNode != NULL ) {
|
||
|
||
pAccountNode->Name = pAccountSidOrName->Name;
|
||
pAccountSidOrName->Name = NULL;
|
||
|
||
pAccountNode->PrivLowPart = dwPrivLowThisAccount & PrivLowMask;
|
||
pAccountNode->PrivHighPart = dwPrivHighThisAccount & PrivHighMask;
|
||
|
||
pAccountNode->Next = *pRemoveList;
|
||
*pRemoveList = pAccountNode;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// free the buffer
|
||
//
|
||
if ( pAccountSidOrName->Name ) {
|
||
ScepFree(pAccountSidOrName->Name);
|
||
}
|
||
if ( pAccountSidOrName != psList)
|
||
ScepFree(pAccountSidOrName);
|
||
pAccountSidOrName = NULL;
|
||
|
||
}
|
||
}
|
||
|
||
if ( aUserRights ) {
|
||
|
||
LsaFreeMemory( aUserRights );
|
||
|
||
aUserRights = NULL;
|
||
}
|
||
}
|
||
|
||
} else if ( NtStatus == STATUS_NONE_MAPPED ) {
|
||
//
|
||
// lookup for all sids failed
|
||
//
|
||
NtStatusRsop = NtStatus;
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
NtStatusRsop = NtStatus;
|
||
ScepLogOutput3(3,0, IDS_ERROR_LOOKUP, NtStatus, uNumAccounts);
|
||
NtStatus = STATUS_SUCCESS; // ignore the error for now
|
||
}
|
||
|
||
//
|
||
// free and reset all parameters except the enumeration context
|
||
// for which state has to be remembered between calls to LSA
|
||
//
|
||
|
||
if (pReferencedDomains) {
|
||
LsaFreeMemory(pReferencedDomains);
|
||
pReferencedDomains = NULL;
|
||
}
|
||
|
||
if (aNames) {
|
||
LsaFreeMemory(aNames);
|
||
aNames = NULL;
|
||
}
|
||
|
||
if (aSids) {
|
||
LsaFreeMemory( aSids );
|
||
aSids = NULL;
|
||
}
|
||
|
||
//
|
||
// attempt to enumerate the next batch of SIDs
|
||
//
|
||
|
||
uNumAccounts = 0;
|
||
|
||
NtStatus = LsaEnumerateAccounts(
|
||
PolicyHandle,
|
||
&uEnumerationContext,
|
||
(PVOID *)&aSids,
|
||
uPreferedMaximumLength,
|
||
&uNumAccounts
|
||
);
|
||
|
||
}
|
||
|
||
if ( aSids ) {
|
||
|
||
LsaFreeMemory( aSids );
|
||
|
||
}
|
||
|
||
ScepFree(pwszStringSid);
|
||
pwszStringSid = NULL;
|
||
|
||
if ( NtStatus == STATUS_NO_MORE_ENTRIES ||
|
||
NtStatus == STATUS_NOT_FOUND ) {
|
||
|
||
//
|
||
// not a real error - just an enumeration warning/status
|
||
//
|
||
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
//
|
||
// in this scheme in which it is "foreach SID" and not "foreach privilege",
|
||
// either log all in case of failure
|
||
//
|
||
|
||
if ( ! NT_SUCCESS( NtStatus ) ) {
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
NULL,
|
||
PrivLowMask,
|
||
PrivHighMask);
|
||
|
||
ScepLogOutput3(1,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SAP_ERROR_ENUMERATE,
|
||
L"Accounts from LSA");
|
||
|
||
}
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
if ( bIgnored ) {
|
||
//
|
||
// if some accounts are ignored, return the pending error
|
||
//
|
||
return(STATUS_PENDING);
|
||
} else
|
||
return NtStatusSave;
|
||
|
||
} else
|
||
return(NtStatus);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
ScepBuildDwMaskFromStrArray(
|
||
IN PUNICODE_STRING aUserRights,
|
||
IN ULONG uCountOfRights,
|
||
OUT DWORD *pdwPrivLowThisAccount,
|
||
OUT DWORD *pdwPrivHighThisAccount
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine converts a privilege array of unicode strings two DWORD masks.
|
||
|
||
Arguments:
|
||
|
||
aUserRights - an array of unicode strings, each string is a user right
|
||
uCountOfRights - array count
|
||
pdwPrivLowThisAccount - converted privileges' low 32 mask
|
||
pdwPrivHighThisAccount - converted privileges' high 32 mask
|
||
|
||
Return value:
|
||
|
||
None except the low 32 and high 32 masks
|
||
|
||
-- */
|
||
{
|
||
ULONG uAccountIndex;
|
||
DWORD dwRefPrivIndex;
|
||
DWORD dwLowMask = 0;
|
||
DWORD dwHighMask = 0;
|
||
|
||
if (pdwPrivLowThisAccount == NULL ||
|
||
pdwPrivHighThisAccount == NULL ||
|
||
aUserRights == NULL ||
|
||
uCountOfRights == 0 ) {
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
for (uAccountIndex = 0; uAccountIndex < uCountOfRights; uAccountIndex++ ) {
|
||
for (dwRefPrivIndex = 0; dwRefPrivIndex < cPrivCnt; dwRefPrivIndex++ ) {
|
||
if ( 0 == _wcsnicmp(SCE_Privileges[ dwRefPrivIndex ].Name, aUserRights[ uAccountIndex ].Buffer, aUserRights[ uAccountIndex ].Length/sizeof(WCHAR))) {
|
||
if ( dwRefPrivIndex < 32 ) {
|
||
dwLowMask |= 1 << dwRefPrivIndex;
|
||
}
|
||
else {
|
||
dwHighMask |= 1 << (dwRefPrivIndex - 32) ;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
*pdwPrivLowThisAccount = dwLowMask;
|
||
*pdwPrivHighThisAccount = dwHighMask;
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepAdjustAccountPrivilegesRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN PSID AccountSid,
|
||
IN DWORD PrivilegeLowRights,
|
||
IN DWORD PrivilegeLowMask,
|
||
IN DWORD PrivilegeHighRights,
|
||
IN DWORD PrivilegeHighMask,
|
||
IN DWORD Options
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine set the privilege/rights as specified in PrivilegeRights
|
||
(DWORD type, each bit represents a privilege/right) to the account
|
||
referenced by AccountSid. This routine compares the current privilege/
|
||
right setting with the "should be" setting and add/remove privileges/
|
||
rights from the account.
|
||
|
||
Arguments:
|
||
|
||
PolicyHandle - Lsa Policy Domain handle
|
||
|
||
AccountSid - The SID for the account
|
||
|
||
PrivilegeRights - Privilege/Rights to set for this account
|
||
|
||
Return value:
|
||
|
||
NTSTATUS
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus;
|
||
DWORD ExplicitPrivLowRights=0, ExplicitPrivHighRights=0;
|
||
DWORD PrivLowRightAdd,
|
||
PrivLowRightRemove;
|
||
|
||
DWORD PrivHighRightAdd,
|
||
PrivHighRightRemove;
|
||
//
|
||
// Enumerate current explicitly assigned privilege/rights
|
||
//
|
||
|
||
NtStatus = ScepGetAccountExplicitRight(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
&ExplicitPrivLowRights,
|
||
&ExplicitPrivHighRights
|
||
);
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ){
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
NULL,
|
||
PrivilegeLowRights,
|
||
PrivilegeHighRights);
|
||
}
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
//
|
||
// Compare CurrentPrivRights with pRights->PrivilegeRights for add
|
||
// Example: CurrentPrivRights 10101
|
||
// pRights->PrivilegeRights( change to) 11010
|
||
// where 1 means the privilege/right is on
|
||
// So the privileges/rights to add 01010
|
||
// Compare ExplicitPrivRights with pRights->PrivilegeRights for remove
|
||
//
|
||
|
||
PrivLowRightAdd = ~ExplicitPrivLowRights & PrivilegeLowRights;
|
||
PrivLowRightRemove = (~(PrivilegeLowRights) & ExplicitPrivLowRights) & PrivilegeLowMask;
|
||
|
||
PrivHighRightAdd = ~ExplicitPrivHighRights & PrivilegeHighRights;
|
||
PrivHighRightRemove = (~(PrivilegeHighRights) & ExplicitPrivHighRights) & PrivilegeHighMask;
|
||
|
||
//
|
||
// Add
|
||
//
|
||
|
||
if ( PrivLowRightAdd != 0 || PrivHighRightAdd != 0 ) {
|
||
|
||
NtStatus = ScepAddOrRemoveAccountRights(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
TRUE,
|
||
PrivLowRightAdd,
|
||
PrivHighRightAdd
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
NULL,
|
||
PrivLowRightAdd,
|
||
PrivHighRightAdd);
|
||
}
|
||
|
||
if ( RtlNtStatusToDosError(NtStatus) != ERROR_ALREADY_EXISTS ){
|
||
|
||
return(NtStatus);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Remove
|
||
//
|
||
|
||
if ( PrivLowRightRemove != 0 || PrivHighRightRemove != 0 ) {
|
||
|
||
NtStatus = ScepAddOrRemoveAccountRights(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
FALSE,
|
||
PrivLowRightRemove,
|
||
PrivHighRightRemove
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ){
|
||
|
||
if ( Options & SCE_RSOP_CALLBACK){
|
||
|
||
ScepRsopLog(SCE_RSOP_PRIVILEGE_INFO,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
NULL,
|
||
PrivLowRightRemove,
|
||
PrivHighRightRemove);
|
||
}
|
||
return(NtStatus);
|
||
}
|
||
}
|
||
|
||
return (NtStatus);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepAddOrRemoveAccountRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN PSID AccountSid,
|
||
IN BOOL AddOrRemove,
|
||
IN DWORD PrivLowAdjust,
|
||
IN DWORD PrivHighAdjust
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine add or remove the privilege/rights as specified in PrivAdjust
|
||
to the account referenced by AccountSid.
|
||
|
||
Arguments:
|
||
|
||
PolicyHandle - Lsa Policy Domain handle
|
||
|
||
AccountSid - The SID for the account
|
||
|
||
AddOrRemove - TRUE = Add, FALSE = remove
|
||
|
||
PrivAdjust - Privilege/Rights to add or remove
|
||
|
||
Return value:
|
||
|
||
NTSTATUS
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus=STATUS_SUCCESS;
|
||
DWORD cTotal;
|
||
DWORD i, cnt;
|
||
PLSA_UNICODE_STRING UserRightAdjust=NULL;
|
||
|
||
//
|
||
// count how many privileges/rights to adjust
|
||
//
|
||
|
||
i = PrivLowAdjust;
|
||
cTotal = 0;
|
||
|
||
while ( i != 0 ) {
|
||
if ( i & 0x1 )
|
||
cTotal++;
|
||
i /= 2;
|
||
}
|
||
|
||
i = PrivHighAdjust;
|
||
|
||
while ( i != 0 ) {
|
||
if ( i & 0x1 )
|
||
cTotal++;
|
||
i /= 2;
|
||
}
|
||
|
||
if ( cTotal > 0 ) {
|
||
//
|
||
// add names in privileges table
|
||
//
|
||
UserRightAdjust = (PLSA_UNICODE_STRING)ScepAlloc( (UINT)0,
|
||
cTotal*sizeof(LSA_UNICODE_STRING));
|
||
|
||
if ( UserRightAdjust == NULL ) {
|
||
NtStatus = STATUS_NO_MEMORY;
|
||
goto Done;
|
||
}
|
||
|
||
for (i = 0, cnt=0; i < cPrivCnt; i++)
|
||
|
||
if ( ( ( i < 32 ) && ( PrivLowAdjust & (1 << i) ) ) ||
|
||
( ( i >= 32 ) && ( PrivHighAdjust & (1 << ( i-32 )) ) ) ) {
|
||
|
||
RtlInitUnicodeString(&(UserRightAdjust[cnt]), SCE_Privileges[i].Name);
|
||
if (AddOrRemove)
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_ADD, SCE_Privileges[i].Name);
|
||
else
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, SCE_Privileges[i].Name);
|
||
|
||
cnt++;
|
||
}
|
||
|
||
|
||
if (AddOrRemove) {
|
||
// add
|
||
NtStatus = LsaAddAccountRights(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
UserRightAdjust,
|
||
cTotal
|
||
);
|
||
} else {
|
||
// remove
|
||
NtStatus = LsaRemoveAccountRights(
|
||
PolicyHandle,
|
||
AccountSid,
|
||
FALSE,
|
||
UserRightAdjust,
|
||
cTotal
|
||
);
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
if (UserRightAdjust != NULL)
|
||
ScepFree(UserRightAdjust);
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
ScepValidateUserInGroups(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN PSID DomainSid,
|
||
IN UNICODE_STRING UserName,
|
||
IN ULONG UserId,
|
||
IN PSCE_NAME_LIST pGroupsToCheck
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine validates the user's group membership to the list of groups.
|
||
If the user is not in one of the groups, add it to the group. If a group
|
||
has more members, just ignore.
|
||
|
||
Arguments:
|
||
|
||
DomainHandle - The SAM handle of the SAM account domain
|
||
|
||
BuiltinDomainHandle - The SAM handle of the SAM builtin domain
|
||
|
||
DomainSid - The SID of the account domain
|
||
|
||
UserName - The user's name in UNICODE_STRING
|
||
|
||
UserId - The user's relative ID
|
||
|
||
pGroupsToCheck - The group list to check for this user
|
||
|
||
Return value:
|
||
|
||
NTSTATUS
|
||
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus;
|
||
SAM_HANDLE UserHandle=NULL;
|
||
PSID AccountSid=NULL;
|
||
PSCE_NAME_LIST GroupList=NULL,
|
||
pGroup, pGroup2;
|
||
BOOL FirstTime=TRUE;
|
||
|
||
|
||
if ( pGroupsToCheck == NULL )
|
||
return(ERROR_SUCCESS);
|
||
|
||
NtStatus = SamOpenUser(
|
||
DomainHandle,
|
||
USER_READ | USER_EXECUTE,
|
||
UserId,
|
||
&UserHandle
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1,RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_USER_OBJECT);
|
||
return(NtStatus);
|
||
}
|
||
|
||
//
|
||
// Get user's SID
|
||
//
|
||
|
||
NtStatus = ScepDomainIdToSid(
|
||
DomainSid,
|
||
UserId,
|
||
&AccountSid
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) )
|
||
goto Done;
|
||
|
||
//
|
||
// get all current assigned groups of this user.
|
||
//
|
||
|
||
NtStatus = ScepGetGroupsForAccount(
|
||
DomainHandle,
|
||
BuiltinDomainHandle,
|
||
UserHandle,
|
||
AccountSid,
|
||
&GroupList
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) )
|
||
goto Done;
|
||
|
||
UNICODE_STRING uName;
|
||
PWSTR pTemp;
|
||
|
||
for ( pGroup=pGroupsToCheck; pGroup != NULL; pGroup = pGroup->Next ) {
|
||
|
||
//
|
||
// should expect pGroup->Name has domain prefix
|
||
//
|
||
pTemp = wcschr(pGroup->Name, L'\\');
|
||
|
||
if ( pTemp ) {
|
||
|
||
//
|
||
// check if this group is from a different domain
|
||
//
|
||
|
||
uName.Buffer = pGroup->Name;
|
||
uName.Length = ((USHORT)(pTemp-pGroup->Name))*sizeof(TCHAR);
|
||
|
||
if ( !ScepIsDomainLocal(&uName) ) {
|
||
ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->Name);
|
||
continue;
|
||
}
|
||
|
||
pTemp++;
|
||
|
||
} else {
|
||
pTemp = pGroup->Name;
|
||
}
|
||
|
||
for ( pGroup2=GroupList; pGroup2 != NULL; pGroup2 = pGroup2->Next ) {
|
||
|
||
if ( _wcsnicmp(pGroup2->Name, pTemp, wcslen(pTemp)) == 0)
|
||
break;
|
||
}
|
||
|
||
if ( pGroup2 == NULL ) {
|
||
//
|
||
// Did not find the group. Add the user to it (pGroup->Name)
|
||
//
|
||
if (FirstTime)
|
||
ScepLogOutput3(2, 0, SCEDLL_SCP_ADDTO, pGroup->Name );
|
||
FirstTime = FALSE;
|
||
|
||
NtStatus = ScepAddUserToGroup(
|
||
DomainHandle,
|
||
BuiltinDomainHandle,
|
||
UserId,
|
||
AccountSid,
|
||
pTemp // pGroup->Name
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) && NtStatus != STATUS_NONE_MAPPED ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_ADDTO, pGroup->Name);
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
SamCloseHandle(UserHandle);
|
||
|
||
if (AccountSid != NULL)
|
||
ScepFree(AccountSid);
|
||
|
||
ScepFreeNameList(GroupList);
|
||
|
||
return(NtStatus);
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepAddUserToGroup(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN ULONG UserId,
|
||
IN PSID AccountSid,
|
||
IN PWSTR GroupName
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
|
||
Return value:
|
||
|
||
NTSTATUS
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus=ERROR_SUCCESS;
|
||
SAM_HANDLE ThisDomain=DomainHandle;
|
||
UNICODE_STRING Name;
|
||
PULONG GrpId=NULL;
|
||
PSID_NAME_USE GrpUse=NULL;
|
||
SAM_HANDLE GroupHandle=NULL;
|
||
|
||
|
||
// initialize a UNICODE_STRING for the group name
|
||
RtlInitUnicodeString(&Name, GroupName);
|
||
|
||
//
|
||
// lookup the group name in account domain first
|
||
//
|
||
NtStatus = SamLookupNamesInDomain(
|
||
DomainHandle,
|
||
1,
|
||
&Name,
|
||
&GrpId,
|
||
&GrpUse
|
||
);
|
||
|
||
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) )
|
||
return(NtStatus);
|
||
|
||
//
|
||
// add the user to the group/alias
|
||
//
|
||
|
||
if (GrpUse != NULL){
|
||
|
||
switch ( GrpUse[0] ) {
|
||
case SidTypeGroup:
|
||
NtStatus = SamOpenGroup(
|
||
ThisDomain,
|
||
GROUP_ADD_MEMBER,
|
||
GrpId[0],
|
||
&GroupHandle
|
||
);
|
||
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
NtStatus = SamAddMemberToGroup(
|
||
GroupHandle,
|
||
UserId,
|
||
SE_GROUP_MANDATORY |
|
||
SE_GROUP_ENABLED_BY_DEFAULT |
|
||
SE_GROUP_ENABLED
|
||
);
|
||
}
|
||
break;
|
||
case SidTypeAlias:
|
||
NtStatus = SamOpenAlias(
|
||
ThisDomain,
|
||
ALIAS_ADD_MEMBER,
|
||
GrpId[0],
|
||
&GroupHandle
|
||
);
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
NtStatus = SamAddMemberToAlias(
|
||
GroupHandle,
|
||
AccountSid
|
||
);
|
||
}
|
||
break;
|
||
default:
|
||
NtStatus = STATUS_DATA_ERROR;
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_NOT_GROUP, GroupName);
|
||
goto Done;
|
||
}
|
||
|
||
}
|
||
|
||
Done:
|
||
|
||
SamFreeMemory(GrpId);
|
||
SamFreeMemory(GrpUse);
|
||
|
||
SamCloseHandle(GroupHandle);
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureGroupMembership(
|
||
IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine configure restricted group's membership which includes members
|
||
in the group and groups this group belongs to ( Currently a global group can
|
||
only belong to a local group and a local group can't be a member of other
|
||
groups. But this will change in the future). Members in the group are
|
||
configured exactly as the pMembers list in the restricted group. The group
|
||
is only validated (added) as a member of the MemberOf group list. Other
|
||
existing members in those groups won't be removed.
|
||
|
||
The restricted groups are specified in the SCP profile by group name. It
|
||
could be a global group, or a alias, but must be defined on the local system.
|
||
|
||
Arguments:
|
||
|
||
pGroupMembership - the restricted group list to configure
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
:
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus;
|
||
NTSTATUS SaveStat=STATUS_SUCCESS;
|
||
PSCE_GROUP_MEMBERSHIP pGroup;
|
||
SAM_HANDLE ServerHandle=NULL,
|
||
DomainHandle=NULL,
|
||
BuiltinDomainHandle=NULL;
|
||
PSID DomainSid=NULL,
|
||
BuiltinDomainSid=NULL;
|
||
|
||
LSA_HANDLE PolicyHandle=NULL;
|
||
|
||
SAM_HANDLE ThisDomain=NULL;
|
||
PSID ThisDomainSid=NULL;
|
||
UNICODE_STRING Name;
|
||
PULONG GrpId=NULL;
|
||
PSID_NAME_USE GrpUse=NULL;
|
||
PSID GrpSid=NULL;
|
||
DWORD GroupLen;
|
||
DWORD rc;
|
||
|
||
DWORD nGroupCount=0;
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
PWSTR GroupSidString=NULL;
|
||
|
||
|
||
if (pGroupMembership == NULL) {
|
||
|
||
ScepPostProgress(TICKS_GROUPS,
|
||
AREA_GROUP_MEMBERSHIP,
|
||
NULL);
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// open LSA policy
|
||
//
|
||
NtStatus = ScepOpenLsaPolicy(
|
||
POLICY_VIEW_LOCAL_INFORMATION |
|
||
POLICY_VIEW_AUDIT_INFORMATION |
|
||
POLICY_GET_PRIVATE_INFORMATION |
|
||
POLICY_LOOKUP_NAMES,
|
||
// GENERIC_ALL,
|
||
&PolicyHandle,
|
||
TRUE
|
||
);
|
||
if (NtStatus != STATUS_SUCCESS) {
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
|
||
|
||
ScepPostProgress(TICKS_GROUPS,
|
||
AREA_GROUP_MEMBERSHIP,
|
||
NULL);
|
||
|
||
return(ScepDosErrorToSceStatus(rc));
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
SaveStat = STATUS_NOT_SUPPORTED;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// Open SAM domain
|
||
//
|
||
NtStatus = ScepOpenSamDomain(
|
||
SAM_SERVER_ALL_ACCESS,
|
||
MAXIMUM_ALLOWED,
|
||
&ServerHandle,
|
||
&DomainHandle,
|
||
&DomainSid,
|
||
&BuiltinDomainHandle,
|
||
&BuiltinDomainSid
|
||
);
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ACCOUNT_DOMAIN);
|
||
SaveStat = NtStatus;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// open policy/tattoo tables
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szGroupMembership,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
}
|
||
|
||
//
|
||
// configure each group
|
||
//
|
||
|
||
for ( pGroup=pGroupMembership; pGroup != NULL; pGroup = pGroup->Next ) {
|
||
//
|
||
// Get this group's ID and SID
|
||
// initialize a UNICODE_STRING for the group name
|
||
//
|
||
if ( (pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS ) &&
|
||
(pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF ) ) {
|
||
|
||
// it's not possible to get invalid tattoo group values into the
|
||
// tattoo table so we don't handle tattoo value here
|
||
|
||
continue;
|
||
}
|
||
|
||
if ( (ProductType == NtProductLanManNt) &&
|
||
(pGroup->Status & SCE_GROUP_STATUS_DONE_IN_DS) ) {
|
||
//
|
||
// this one is already done by DS
|
||
//
|
||
nGroupCount++;
|
||
continue;
|
||
}
|
||
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_CONFIGURE, pGroup->GroupName);
|
||
|
||
if ( nGroupCount < TICKS_GROUPS ) {
|
||
ScepPostProgress(1, AREA_GROUP_MEMBERSHIP, pGroup->GroupName);
|
||
nGroupCount++;
|
||
}
|
||
|
||
LPTSTR pTemp = wcschr(pGroup->GroupName, L'\\');
|
||
if ( pTemp ) {
|
||
//
|
||
// there is a domain name, check it with computer name
|
||
//
|
||
UNICODE_STRING uName;
|
||
|
||
uName.Buffer = pGroup->GroupName;
|
||
uName.Length = ((USHORT)(pTemp-pGroup->GroupName))*sizeof(TCHAR);
|
||
|
||
if ( !ScepIsDomainLocal(&uName) ) {
|
||
//
|
||
// it's not possible to get a foreign domain group into the tattoo
|
||
// table so we don't handle the tattoo values here
|
||
//
|
||
ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pGroup->GroupName);
|
||
rc = SCESTATUS_INVALID_DATA;
|
||
continue;
|
||
}
|
||
pTemp++;
|
||
} else {
|
||
pTemp = pGroup->GroupName;
|
||
}
|
||
|
||
RtlInitUnicodeString(&Name, pTemp);
|
||
|
||
GroupLen = wcslen(pTemp);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
SaveStat = STATUS_NOT_SUPPORTED;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// lookup the group name in account domain first
|
||
//
|
||
NtStatus = SamLookupNamesInDomain(
|
||
DomainHandle,
|
||
1,
|
||
&Name,
|
||
&GrpId,
|
||
&GrpUse
|
||
);
|
||
ThisDomain = DomainHandle;
|
||
ThisDomainSid = DomainSid;
|
||
|
||
if ( NtStatus == STATUS_NONE_MAPPED ) {
|
||
//
|
||
// not found in account domain. Lookup in the builtin domain (maybe a alias)
|
||
//
|
||
NtStatus = SamLookupNamesInDomain(
|
||
BuiltinDomainHandle,
|
||
1,
|
||
&Name,
|
||
&GrpId,
|
||
&GrpUse
|
||
);
|
||
ThisDomain=BuiltinDomainHandle;
|
||
ThisDomainSid = BuiltinDomainSid;
|
||
}
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_NO_MAPPINGS, pGroup->GroupName);
|
||
SaveStat = NtStatus;
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
ScepRsopLog(SCE_RSOP_GROUP_INFO, RtlNtStatusToDosError(NtStatus), pGroup->GroupName, 0, 0);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
pTemp,
|
||
GroupLen,
|
||
NULL,
|
||
TRUE,
|
||
ERROR_NONE_MAPPED
|
||
);
|
||
}
|
||
|
||
// goto Done;
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Get the group's account SID
|
||
//
|
||
NtStatus = ScepDomainIdToSid(
|
||
ThisDomainSid,
|
||
GrpId[0],
|
||
&GrpSid
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_NO_MAPPINGS, pGroup->GroupName);
|
||
SaveStat = NtStatus;
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
ScepRsopLog(SCE_RSOP_GROUP_INFO, RtlNtStatusToDosError(NtStatus), pGroup->GroupName, 0, 0);
|
||
|
||
goto NextGroup;
|
||
}
|
||
|
||
if ( GrpId[0] == DOMAIN_GROUP_RID_USERS ) {
|
||
|
||
//
|
||
// do not configure this one
|
||
// there should never be tattoo values for this setting
|
||
// so we don't check tattoo values here
|
||
//
|
||
goto NextGroup;
|
||
}
|
||
|
||
if ( GrpId[0] == DOMAIN_ALIAS_RID_ADMINS ) {
|
||
|
||
//
|
||
// local builtin administrators alias, make sure local Administrator
|
||
// account is in the members list, if it's not, add it there
|
||
//
|
||
|
||
(VOID) ScepAddAdministratorToThisList(
|
||
DomainHandle,
|
||
&(pGroup->pMembers)
|
||
);
|
||
}
|
||
|
||
//
|
||
// members
|
||
//
|
||
if ( !(pGroup->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) {
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) ) {
|
||
|
||
DWORD rc2 = ScepConvertSidToPrefixStringSid(GrpSid, &GroupSidString);
|
||
|
||
if ( ERROR_SUCCESS != rc2 ) {
|
||
ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_SETTING,rc2,pGroup->GroupName);
|
||
GroupSidString = NULL;
|
||
}
|
||
}
|
||
|
||
switch ( GrpUse[0] ) {
|
||
case SidTypeGroup:
|
||
NtStatus = ScepConfigureMembersOfGroup(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
ThisDomain,
|
||
ThisDomainSid,
|
||
GrpId[0],
|
||
GrpSid,
|
||
pGroup->GroupName,
|
||
GroupSidString,
|
||
pGroup->pMembers,
|
||
ConfigOptions
|
||
);
|
||
|
||
|
||
break;
|
||
case SidTypeAlias:
|
||
NtStatus = ScepConfigureMembersOfAlias(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
ThisDomain,
|
||
ThisDomainSid,
|
||
PolicyHandle,
|
||
GrpId[0],
|
||
GrpSid,
|
||
pGroup->GroupName,
|
||
GroupSidString,
|
||
pGroup->pMembers,
|
||
ConfigOptions
|
||
);
|
||
|
||
break;
|
||
case SidTypeUser:
|
||
if ( pGroup->pMembers != NULL ) {
|
||
ScepLogOutput3(1, 0, SCEDLL_ERROR_USER_MEMBER);
|
||
|
||
NtStatus = STATUS_DATA_ERROR;
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
GroupSidString ) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
NULL,
|
||
TRUE,
|
||
ERROR_NONE_MAPPED
|
||
);
|
||
}
|
||
|
||
break;
|
||
default:
|
||
NtStatus = STATUS_DATA_ERROR;
|
||
ScepLogOutput3(1, 0, SCEDLL_NOT_GROUP, pGroup->GroupName);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
GroupSidString ) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
NULL,
|
||
TRUE,
|
||
ERROR_NONE_MAPPED
|
||
);
|
||
}
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_GROUP_INFO,
|
||
RtlNtStatusToDosError(NtStatus),
|
||
pGroup->GroupName,0,0);
|
||
|
||
if ( !NT_SUCCESS(NtStatus) )
|
||
SaveStat = NtStatus;
|
||
|
||
if ( GroupSidString ) {
|
||
ScepFree(GroupSidString);
|
||
GroupSidString = NULL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// member of
|
||
//
|
||
if ( (pGroup->pMemberOf != NULL) &&
|
||
!(pGroup->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
|
||
|
||
switch ( GrpUse[0] ) {
|
||
case SidTypeGroup:
|
||
//
|
||
// group can be members of alias only
|
||
//
|
||
NtStatus = ScepValidateGroupInAliases(
|
||
DomainHandle,
|
||
BuiltinDomainHandle,
|
||
GrpSid,
|
||
pGroup->pMemberOf
|
||
);
|
||
break;
|
||
|
||
case SidTypeUser:
|
||
NtStatus = ScepValidateUserInGroups(
|
||
DomainHandle,
|
||
BuiltinDomainHandle,
|
||
ThisDomainSid,
|
||
Name,
|
||
GrpId[0],
|
||
pGroup->pMemberOf
|
||
);
|
||
|
||
break;
|
||
|
||
case SidTypeAlias:
|
||
NtStatus = STATUS_DATA_ERROR;
|
||
ScepLogOutput3(1, 0, SCEDLL_ERROR_ALIAS_MEMBER);
|
||
|
||
}
|
||
if ( !NT_SUCCESS(NtStatus) )
|
||
SaveStat = NtStatus;
|
||
|
||
}
|
||
NextGroup:
|
||
|
||
//
|
||
// free memory for this group
|
||
//
|
||
SamFreeMemory(GrpId);
|
||
GrpId = NULL;
|
||
|
||
SamFreeMemory(GrpUse);
|
||
GrpUse = NULL;
|
||
|
||
ScepFree(GrpSid);
|
||
GrpSid = NULL;
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( GrpId != NULL )
|
||
SamFreeMemory(GrpId);
|
||
|
||
if ( GrpUse != NULL )
|
||
SamFreeMemory(GrpUse);
|
||
|
||
if ( GrpSid != NULL )
|
||
ScepFree(GrpSid);
|
||
|
||
// close sam handles
|
||
SamCloseHandle(DomainHandle);
|
||
SamCloseHandle(BuiltinDomainHandle);
|
||
SamCloseHandle(ServerHandle);
|
||
|
||
if ( DomainSid != NULL )
|
||
SamFreeMemory(DomainSid);
|
||
if ( BuiltinDomainSid != NULL )
|
||
SamFreeMemory(BuiltinDomainSid);
|
||
|
||
LsaClose(PolicyHandle);
|
||
|
||
if ( nGroupCount < TICKS_GROUPS ) {
|
||
ScepPostProgress(TICKS_GROUPS-nGroupCount,
|
||
AREA_GROUP_MEMBERSHIP,
|
||
NULL);
|
||
}
|
||
|
||
SceJetCloseSection(&hSectionDomain, TRUE);
|
||
SceJetCloseSection(&hSectionTattoo, TRUE);
|
||
|
||
rc = RtlNtStatusToDosError(SaveStat);
|
||
return( ScepDosErrorToSceStatus(rc) );
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepConfigureMembersOfGroup(
|
||
IN PSCESECTION hSectionDomain,
|
||
IN PSCESECTION hSectionTattoo,
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PSID ThisDomainSid,
|
||
IN ULONG GrpId,
|
||
IN PSID GrpSid,
|
||
IN PWSTR GrpName,
|
||
IN PWSTR GroupSidString,
|
||
IN PSCE_NAME_LIST pMembers,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine configure a group's members as specified in the SCP profile (
|
||
pMembers ). Less members are added and extra members are removed.
|
||
|
||
Arguments:
|
||
|
||
DomainHandle - the SAM domain's handle
|
||
|
||
GrpId - the group's RID
|
||
|
||
pMembers - the members list as specified in the SCP profile
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS return SAM APIs
|
||
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus;
|
||
|
||
PUNICODE_STRING MemberNames=NULL;
|
||
PULONG MemberRids=NULL;
|
||
PSID_NAME_USE MemberUse=NULL;
|
||
ULONG MemberCount=0;
|
||
SAM_HANDLE GroupHandle=NULL;
|
||
|
||
PULONG CurrentRids=NULL;
|
||
PULONG Attributes=NULL;
|
||
ULONG CurrentCount=0;
|
||
|
||
DWORD i, j;
|
||
WCHAR MsgBuf[256];
|
||
|
||
PUNICODE_STRING pName=NULL;
|
||
PSID_NAME_USE pUse=NULL;
|
||
PSCE_NAME_LIST pMemberList=NULL;
|
||
BOOL bMemberQueried=FALSE;
|
||
|
||
/*
|
||
if ( pMembers == NULL )
|
||
return(STATUS_SUCCESS);
|
||
*/
|
||
//
|
||
// Accept empty member list
|
||
// look up the members list first (all members should be within this domain
|
||
//
|
||
NtStatus = ScepLookupNamesInDomain(
|
||
DomainHandle,
|
||
pMembers,
|
||
&MemberNames,
|
||
&MemberRids,
|
||
&MemberUse,
|
||
&MemberCount
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_LOOKUP, pMembers ? pMembers->Name : L"");
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo && GrpSid && GroupSidString &&
|
||
(NtStatus == STATUS_NONE_MAPPED)) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
NULL,
|
||
TRUE,
|
||
0
|
||
);
|
||
}
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
//
|
||
// open the group to get a handle
|
||
//
|
||
NtStatus = SamOpenGroup(
|
||
DomainHandle,
|
||
MAXIMUM_ALLOWED, // ? GROUP_ALL_ACCESS,
|
||
GrpId,
|
||
&GroupHandle
|
||
);
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_OPEN, L"");
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// get current members of the group
|
||
//
|
||
NtStatus = SamGetMembersInGroup(
|
||
GroupHandle,
|
||
&CurrentRids,
|
||
&Attributes,
|
||
&CurrentCount
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_QUERY_INFO, L"");
|
||
goto Done;
|
||
}
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo && GrpSid && GroupSidString ) {
|
||
|
||
DWORD rc = ScepTattooCurrentGroupMembers(ThisDomainSid,
|
||
SidTypeGroup,
|
||
CurrentRids,
|
||
NULL,
|
||
CurrentCount,
|
||
&pMemberList
|
||
);
|
||
if ( ERROR_SUCCESS != rc ) {
|
||
//
|
||
// something is wrong when building the list
|
||
// this shoudln't happen unless out of memory etc.
|
||
//
|
||
ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,GrpName);
|
||
} else
|
||
bMemberQueried=TRUE;
|
||
}
|
||
|
||
//
|
||
// Compare the member ids with the current ids for adding
|
||
//
|
||
for ( i=0; i<MemberCount; i++ ) {
|
||
#ifdef SCE_DBG
|
||
printf("process member %x for adding\n", MemberRids[i]);
|
||
#endif
|
||
|
||
if (MemberUse[i] == SidTypeInvalid ||
|
||
MemberUse[i] == SidTypeUnknown ||
|
||
MemberUse[i] == SidTypeDeletedAccount)
|
||
continue;
|
||
|
||
for ( j=0; j<CurrentCount; j++)
|
||
if ( MemberRids[i] == CurrentRids[j] )
|
||
break;
|
||
|
||
if ( j >= CurrentCount) {
|
||
//
|
||
// Add this member
|
||
//
|
||
memset(MsgBuf, '\0', 512);
|
||
wcsncat(MsgBuf, MemberNames[i].Buffer, MemberNames[i].Length/2);
|
||
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_ADD, MsgBuf);
|
||
|
||
NtStatus = SamAddMemberToGroup(
|
||
GroupHandle,
|
||
MemberRids[i],
|
||
0
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_ADD, MsgBuf);
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Compare the member ids with the current ids for removing
|
||
//
|
||
for ( i=0; i<CurrentCount; i++ ) {
|
||
#ifdef SCE_DBG
|
||
printf("process member %x for removing\n", CurrentRids[i]);
|
||
#endif
|
||
for ( j=0; j<MemberCount; j++)
|
||
if ( CurrentRids[i] == MemberRids[j] )
|
||
break;
|
||
|
||
if ( j >= MemberCount) {
|
||
//
|
||
// Find the member name
|
||
//
|
||
memset(MsgBuf, '\0', 512);
|
||
pName=NULL;
|
||
pUse=NULL;
|
||
|
||
if ( NT_SUCCESS( SamLookupIdsInDomain(
|
||
DomainHandle,
|
||
1,
|
||
&(CurrentRids[i]),
|
||
&pName,
|
||
&pUse
|
||
) ) ) {
|
||
if ( pName != NULL ) {
|
||
wcsncat(MsgBuf, pName[0].Buffer, pName[0].Length/2);
|
||
} else
|
||
swprintf(MsgBuf, L"(Rid=%d)", CurrentRids[i]);
|
||
|
||
if ( pName != NULL )
|
||
SamFreeMemory( pName );
|
||
|
||
if ( pUse != NULL )
|
||
SamFreeMemory( pUse );
|
||
|
||
} else
|
||
swprintf(MsgBuf, L"(Rid=%d) ", CurrentRids[i]);
|
||
|
||
//
|
||
// remove this member
|
||
//
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, MsgBuf);
|
||
|
||
NtStatus = SamRemoveMemberFromGroup(
|
||
GroupHandle,
|
||
CurrentRids[i]
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
if ( NtStatus == STATUS_SPECIAL_ACCOUNT )
|
||
ScepLogOutput3(2, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_CANNOT_REMOVE,
|
||
MsgBuf);
|
||
else {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_REMOVE, MsgBuf);
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( MemberNames != NULL )
|
||
RtlFreeHeap(RtlProcessHeap(), 0, MemberNames);
|
||
|
||
if ( MemberRids != NULL )
|
||
SamFreeMemory( MemberRids );
|
||
|
||
if ( MemberUse != NULL )
|
||
SamFreeMemory( MemberUse );
|
||
|
||
if ( CurrentRids != NULL )
|
||
SamFreeMemory( CurrentRids );
|
||
|
||
if ( GroupHandle != NULL )
|
||
SamCloseHandle( GroupHandle );
|
||
|
||
//
|
||
// log the tattoo value
|
||
// if fail to get current value for the group, do not save the tattoo value
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo &&
|
||
GrpSid && GroupSidString && bMemberQueried) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
pMemberList,
|
||
FALSE,
|
||
RtlNtStatusToDosError(NtStatus)
|
||
);
|
||
}
|
||
|
||
// free name list
|
||
if ( pMemberList )
|
||
ScepFreeNameList(pMemberList);
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ScepConfigureMembersOfAlias(
|
||
IN PSCESECTION hSectionDomain,
|
||
IN PSCESECTION hSectionTattoo,
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN PSID DomainSid,
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN ULONG GrpId,
|
||
IN PSID GrpSid,
|
||
IN PWSTR GrpName,
|
||
IN PWSTR GroupSidString,
|
||
IN PSCE_NAME_LIST pMembers,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine configure a local group (alias) members as specified in the
|
||
SCP profile ( pMembers ). Less members are added and extra members are removed.
|
||
|
||
Arguments:
|
||
|
||
DomainHandle - The domains' handle
|
||
|
||
DomainSid - The sid for the domain
|
||
|
||
PolicyHandle - the LSA policy handle
|
||
|
||
GrpId - the alias's RID
|
||
|
||
pMembers - the members list as specified in the SCP profile
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS return SAM APIs
|
||
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus=STATUS_SUCCESS;
|
||
|
||
ULONG MemberCount=0;
|
||
PUNICODE_STRING MemberNames=NULL;
|
||
PSID *Sids=NULL;
|
||
SAM_HANDLE GroupHandle=NULL;
|
||
PSID *CurrentSids=NULL;
|
||
ULONG CurrentCount=0;
|
||
|
||
DWORD i, j;
|
||
WCHAR MsgBuf[256];
|
||
|
||
PLSA_REFERENCED_DOMAIN_LIST pRefDomain;
|
||
PLSA_TRANSLATED_NAME pLsaName;
|
||
LPTSTR StringSid=NULL;
|
||
PSCE_NAME_LIST pMemberList=NULL;
|
||
BOOL bMemberQueried=FALSE;
|
||
|
||
/*
|
||
if ( pMembers == NULL )
|
||
return(STATUS_SUCCESS);
|
||
*/
|
||
//
|
||
// Accept empty member list
|
||
// find Sids for the pMember list
|
||
//
|
||
NtStatus = ScepGetMemberListSids(
|
||
DomainSid,
|
||
PolicyHandle,
|
||
pMembers,
|
||
&MemberNames,
|
||
&Sids,
|
||
&MemberCount
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_LOOKUP, pMembers ? pMembers->Name : L"");
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo && GrpSid && GroupSidString &&
|
||
(NtStatus == STATUS_NONE_MAPPED)) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
NULL,
|
||
TRUE,
|
||
0
|
||
);
|
||
}
|
||
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// open the alias to get a handle
|
||
//
|
||
NtStatus = SamOpenAlias(
|
||
DomainHandle,
|
||
MAXIMUM_ALLOWED, // ? ALIAS_ALL_ACCESS,
|
||
GrpId,
|
||
&GroupHandle
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_OPEN, L"");
|
||
goto Done;
|
||
}
|
||
//
|
||
// get current members of the alias
|
||
// members of alias may exist in everywhere
|
||
//
|
||
NtStatus = SamGetMembersInAlias(
|
||
GroupHandle,
|
||
&CurrentSids,
|
||
&CurrentCount
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_QUERY_INFO, L"");
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// build current group membership into the list
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo && GrpSid ) {
|
||
|
||
DWORD rc = ScepTattooCurrentGroupMembers(DomainSid,
|
||
SidTypeAlias,
|
||
NULL,
|
||
CurrentSids,
|
||
CurrentCount,
|
||
&pMemberList
|
||
);
|
||
if ( ERROR_SUCCESS != rc ) {
|
||
//
|
||
// something is wrong when building the list
|
||
// this shoudln't happen unless out of memory etc.
|
||
//
|
||
ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,GrpName);
|
||
} else
|
||
bMemberQueried = TRUE;
|
||
}
|
||
|
||
//
|
||
// Compare the member sids with the current sids for adding
|
||
//
|
||
|
||
for ( i=0; i<MemberCount; i++ ) {
|
||
#ifdef SCE_DBG
|
||
printf("process member %d for adding\n", i);
|
||
#endif
|
||
|
||
memset(MsgBuf, '\0', 512);
|
||
wcsncpy(MsgBuf, MemberNames[i].Buffer, MemberNames[i].Length/2);
|
||
|
||
if ( Sids[i] == NULL ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_CANNOT_FIND, MsgBuf);
|
||
} else {
|
||
|
||
for ( j=0; j<CurrentCount; j++) {
|
||
if ( EqualSid(Sids[i], CurrentSids[j]) ) {
|
||
|
||
ScepLogOutput3(3,0, SCEDLL_STATUS_MATCH, MsgBuf);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( j >= CurrentCount) {
|
||
//
|
||
// Add this member
|
||
//
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_ADD, MsgBuf);
|
||
|
||
NtStatus = SamAddMemberToAlias(
|
||
GroupHandle,
|
||
Sids[i]
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_ADD, MsgBuf);
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Compare the member ids with the current ids for adding
|
||
//
|
||
|
||
for ( i=0; i<CurrentCount; i++ ) {
|
||
#ifdef SCE_DBG
|
||
printf("process member %d for removing\n", i);
|
||
#endif
|
||
memset(MsgBuf, '\0', 512);
|
||
|
||
if ( ConvertSidToStringSid(
|
||
CurrentSids[i],
|
||
&StringSid
|
||
) && StringSid ) {
|
||
|
||
swprintf(MsgBuf, L"SID: %s",StringSid);
|
||
LocalFree(StringSid);
|
||
StringSid = NULL;
|
||
|
||
} else {
|
||
ScepLogOutput3(3,GetLastError(), IDS_ERROR_CONVERT_SID);
|
||
swprintf(MsgBuf, L"Member %d",i);
|
||
}
|
||
|
||
for ( j=0; j<MemberCount; j++) {
|
||
if ( Sids[j] != NULL && EqualSid( CurrentSids[i], Sids[j]) ) {
|
||
|
||
ScepLogOutput3(3,0, SCEDLL_STATUS_MATCH, MsgBuf);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( j >= MemberCount) {
|
||
//
|
||
// Find the member name
|
||
//
|
||
pRefDomain=NULL;
|
||
pLsaName=NULL;
|
||
|
||
if ( NT_SUCCESS( LsaLookupSids(
|
||
PolicyHandle,
|
||
1,
|
||
&(CurrentSids[i]),
|
||
&pRefDomain,
|
||
&pLsaName
|
||
) ) ) {
|
||
|
||
if ( pLsaName != NULL ) {
|
||
|
||
if ( pRefDomain != NULL && pRefDomain->Entries > 0 && pLsaName[0].Use != SidTypeWellKnownGroup &&
|
||
pRefDomain->Domains != NULL &&
|
||
pLsaName[0].DomainIndex != -1 &&
|
||
pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Buffer != NULL &&
|
||
ScepIsSidFromAccountDomain( pRefDomain->Domains[pLsaName[0].DomainIndex].Sid ) ) {
|
||
|
||
wcsncpy(MsgBuf, pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Buffer,
|
||
pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Length/2);
|
||
MsgBuf[pRefDomain->Domains[pLsaName[0].DomainIndex].Name.Length/2] = L'\0';
|
||
wcscat(MsgBuf, L"\\");
|
||
}
|
||
|
||
wcsncat(MsgBuf, pLsaName[0].Name.Buffer, pLsaName[0].Name.Length/2);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
if ( pRefDomain != NULL ) {
|
||
LsaFreeMemory(pRefDomain);
|
||
pRefDomain = NULL;
|
||
}
|
||
|
||
if ( pLsaName != NULL ){
|
||
LsaFreeMemory(pLsaName);
|
||
pLsaName = NULL;
|
||
}
|
||
//
|
||
// remove this member
|
||
//
|
||
ScepLogOutput3(2,0, SCEDLL_SCP_REMOVE, MsgBuf);
|
||
|
||
NtStatus = SamRemoveMemberFromAlias(
|
||
GroupHandle,
|
||
CurrentSids[i]
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_REMOVE, MsgBuf);
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( Sids != NULL ) {
|
||
for ( i=0; i<MemberCount; i++ ) {
|
||
if ( Sids[i] != NULL )
|
||
ScepFree( Sids[i] );
|
||
}
|
||
ScepFree( Sids );
|
||
}
|
||
|
||
if ( CurrentSids != NULL )
|
||
LsaFreeMemory(CurrentSids);
|
||
|
||
if ( MemberNames != NULL )
|
||
RtlFreeHeap(RtlProcessHeap(), 0, MemberNames);
|
||
|
||
if ( GroupHandle != NULL )
|
||
SamCloseHandle( GroupHandle );
|
||
|
||
//
|
||
// log the tattoo value
|
||
// if fail to get current value for the group, do not save the tattoo value
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
hSectionDomain && hSectionTattoo &&
|
||
GrpSid && GroupSidString && bMemberQueried) {
|
||
|
||
ScepTattooManageOneMemberListValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
GroupSidString,
|
||
wcslen(GroupSidString),
|
||
pMemberList,
|
||
FALSE,
|
||
RtlNtStatusToDosError(NtStatus)
|
||
);
|
||
}
|
||
|
||
// free name list
|
||
if ( pMemberList )
|
||
ScepFreeNameList(pMemberList);
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepValidateGroupInAliases(
|
||
IN SAM_HANDLE DomainHandle,
|
||
IN SAM_HANDLE BuiltinDomainHandle,
|
||
IN PSID GrpSid,
|
||
IN PSCE_NAME_LIST pAliasList
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine add the group to a list of alieses to ensure the group's
|
||
membership.
|
||
|
||
Arguments:
|
||
|
||
DomainHandle - The account domain handle
|
||
|
||
BuiltinDomainHandle - The builtin domain handle
|
||
|
||
GrpSid - The group's SID
|
||
|
||
pAliasList - the list of aliases to check
|
||
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus;
|
||
|
||
PSCE_NAME_LIST pAlias;
|
||
UNICODE_STRING Name;
|
||
PULONG AliasId=NULL;
|
||
PSID_NAME_USE AliasUse=NULL;
|
||
SAM_HANDLE ThisDomain;
|
||
SAM_HANDLE AliasHandle=NULL;
|
||
|
||
|
||
PWSTR pTemp;
|
||
UNICODE_STRING uName;
|
||
|
||
//
|
||
// Process each alias in the list
|
||
//
|
||
for ( pAlias=pAliasList; pAlias != NULL; pAlias = pAlias->Next ) {
|
||
|
||
//
|
||
// should expect pGroup->Name has domain prefix
|
||
//
|
||
pTemp = wcschr(pAlias->Name, L'\\');
|
||
|
||
if ( pTemp ) {
|
||
|
||
//
|
||
// check if this group is from a different domain
|
||
//
|
||
|
||
uName.Buffer = pAlias->Name;
|
||
uName.Length = ((USHORT)(pTemp-pAlias->Name))*sizeof(TCHAR);
|
||
|
||
if ( !ScepIsDomainLocal(&uName) ) {
|
||
ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pAlias->Name);
|
||
continue;
|
||
}
|
||
|
||
pTemp++;
|
||
|
||
} else {
|
||
pTemp = pAlias->Name;
|
||
}
|
||
|
||
RtlInitUnicodeString( &Name, pTemp);
|
||
|
||
NtStatus = SamLookupNamesInDomain(
|
||
DomainHandle,
|
||
1,
|
||
&Name,
|
||
&AliasId,
|
||
&AliasUse
|
||
);
|
||
ThisDomain = DomainHandle;
|
||
if ( NtStatus == STATUS_NONE_MAPPED ) {
|
||
//
|
||
// not found in account domain. Lookup in the builtin domain
|
||
//
|
||
NtStatus = SamLookupNamesInDomain(
|
||
BuiltinDomainHandle,
|
||
1,
|
||
&Name,
|
||
&AliasId,
|
||
&AliasUse
|
||
);
|
||
ThisDomain=BuiltinDomainHandle;
|
||
}
|
||
if ( !NT_SUCCESS(NtStatus) || !AliasUse || !AliasId ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_NO_MAPPINGS, pTemp);
|
||
return(NtStatus);
|
||
}
|
||
//
|
||
// add the group to the alias
|
||
//
|
||
|
||
if ( AliasUse[0] != SidTypeAlias ) {
|
||
ScepLogOutput3(1,0, SCEDLL_ERROR_ALIAS_MEMBEROF);
|
||
|
||
SamFreeMemory(AliasId);
|
||
AliasId = NULL;
|
||
|
||
SamFreeMemory(AliasUse);
|
||
AliasUse = NULL;
|
||
continue; // ignore this error goto Done;
|
||
}
|
||
|
||
NtStatus = SamOpenAlias(
|
||
ThisDomain,
|
||
MAXIMUM_ALLOWED, // ? ALIAS_ALL_ACCESS,
|
||
AliasId[0],
|
||
&AliasHandle
|
||
);
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_ERROR_OPEN, pAlias->Name);
|
||
goto Done;
|
||
}
|
||
|
||
NtStatus = SamAddMemberToAlias(
|
||
AliasHandle,
|
||
GrpSid
|
||
);
|
||
//
|
||
// if group is already in alias, ignore the error
|
||
//
|
||
if ( NtStatus == STATUS_MEMBER_IN_ALIAS )
|
||
NtStatus = STATUS_SUCCESS;
|
||
|
||
if ( !NT_SUCCESS(NtStatus) ) {
|
||
ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
|
||
SCEDLL_SCP_ERROR_ADDTO, pAlias->Name);
|
||
goto Done;
|
||
}
|
||
//
|
||
// free memory for this group
|
||
//
|
||
SamCloseHandle(AliasHandle);
|
||
AliasHandle = NULL;
|
||
|
||
SamFreeMemory(AliasId);
|
||
AliasId = NULL;
|
||
|
||
SamFreeMemory(AliasUse);
|
||
AliasUse = NULL;
|
||
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( AliasHandle != NULL )
|
||
SamCloseHandle(AliasHandle);
|
||
|
||
if ( AliasId != NULL )
|
||
SamFreeMemory(AliasId);
|
||
|
||
if ( AliasUse != NULL )
|
||
SamFreeMemory(AliasUse);
|
||
|
||
return(NtStatus);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureObjectSecurity(
|
||
IN PSCE_OBJECT_LIST pRoots,
|
||
IN AREA_INFORMATION Area,
|
||
IN BOOL bPolicyProp,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
Configure the security setting on Registry keys as specified in pObject tree
|
||
|
||
Arguments:
|
||
|
||
pRoots - a list of object roots to configure
|
||
|
||
Area - The security area to configure (registry or file)
|
||
|
||
ObjectType - Type of the object tree
|
||
SCEJET_AUDITING
|
||
SCEJET_PERMISSION
|
||
|
||
Return value:
|
||
|
||
SCESTATUS error codes
|
||
|
||
++ */
|
||
{
|
||
|
||
|
||
if (Area == AREA_REGISTRY_SECURITY) {
|
||
#ifdef _WIN64
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY_64KEY);
|
||
#else
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY);
|
||
#endif
|
||
}
|
||
|
||
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
return( SCESTATUS_SERVICE_NOT_SUPPORT );
|
||
}
|
||
|
||
HANDLE Token;
|
||
SCESTATUS rc;
|
||
SCESTATUS SaveStat=SCESTATUS_SUCCESS;
|
||
DWORD Win32rc;
|
||
PSCE_OBJECT_LIST pOneRoot;
|
||
PSCE_OBJECT_CHILD_LIST pSecurityObject=NULL;
|
||
DWORD FileSystemFlags;
|
||
SID_IDENTIFIER_AUTHORITY IdentifierAuthority=SECURITY_NT_AUTHORITY;
|
||
WCHAR theDrive[4];
|
||
UINT DriveType;
|
||
|
||
//
|
||
// get current thread/process's token
|
||
//
|
||
if (!OpenThreadToken( GetCurrentThread(),
|
||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
FALSE,
|
||
&Token)) {
|
||
|
||
if (!OpenProcessToken( GetCurrentProcess(),
|
||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
&Token)) {
|
||
|
||
ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
|
||
return(ScepDosErrorToSceStatus(GetLastError()));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Adjust privilege for setting SACL
|
||
//
|
||
Win32rc = SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
|
||
|
||
//
|
||
// if can't adjust privilege, still continue
|
||
//
|
||
|
||
if ( Win32rc != NO_ERROR )
|
||
ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ADJUST, L"SE_SECURITY_PRIVILEGE");
|
||
|
||
// adjust take ownership privilege
|
||
// if fails, continue
|
||
Win32rc = SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, Token );
|
||
|
||
if ( Win32rc != NO_ERROR )
|
||
ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_ADJUST, L"SE_TAKE_OWNERSHIP_PRIVILEGE");
|
||
|
||
|
||
// create a sid for administrators
|
||
// if fails, continue
|
||
|
||
|
||
if ( ! NT_SUCCESS ( RtlAllocateAndInitializeSid( &IdentifierAuthority,
|
||
2,
|
||
SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS,
|
||
0,0,0,0,0,0,
|
||
&AdminsSid
|
||
) ) ) {
|
||
ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY,
|
||
SCEDLL_ADMINISTRATORS_SID);
|
||
}
|
||
|
||
|
||
#ifdef _WIN64
|
||
|
||
//
|
||
// declaration for object tree root pointer to remember from the 64-bit phase and use
|
||
// for 32-bit phase for regkeys (only from the HKLM root, since wow6432node resides
|
||
// under this root only). In future, if there are more wow6432node's that need security
|
||
// synchronization, we will have to extend the logic on similar lines to handle them.
|
||
//
|
||
|
||
PSCE_OBJECT_CHILD_LIST pHKLMSubtreeRoot = NULL;
|
||
BOOL bIsHKLMSubtree = FALSE;
|
||
|
||
#endif
|
||
|
||
|
||
// process each tree
|
||
for ( pOneRoot=pRoots; pOneRoot != NULL; pOneRoot=pOneRoot->Next ) {
|
||
|
||
if ( Area == AREA_FILE_SECURITY &&
|
||
(pOneRoot->Status == SCE_STATUS_CHECK ||
|
||
pOneRoot->Status == SCE_STATUS_NO_AUTO_INHERIT ||
|
||
pOneRoot->Status == SCE_STATUS_OVERWRITE) ) {
|
||
|
||
//
|
||
// make sure the input data follows file format
|
||
//
|
||
if ( pOneRoot->Name[1] != L'\0' && pOneRoot->Name[1] != L':') {
|
||
ScepLogOutput3(1, ERROR_INVALID_DATA, SCEDLL_CANNOT_FIND, pOneRoot->Name);
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// check if support acl
|
||
//
|
||
theDrive[0] = pOneRoot->Name[0];
|
||
theDrive[1] = L':';
|
||
theDrive[2] = L'\\';
|
||
theDrive[3] = L'\0';
|
||
|
||
DriveType = GetDriveType(theDrive);
|
||
|
||
if ( DriveType == DRIVE_FIXED ||
|
||
DriveType == DRIVE_RAMDISK ) {
|
||
|
||
if ( GetVolumeInformation( theDrive,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
NULL,
|
||
&FileSystemFlags,
|
||
NULL,
|
||
0
|
||
) == TRUE ) {
|
||
|
||
if ( !( FileSystemFlags & FS_PERSISTENT_ACLS) ) {
|
||
|
||
pOneRoot->Status = SCE_STATUS_NO_ACL_SUPPORT;
|
||
ScepLogOutput3(1, 0, SCEDLL_NO_ACL_SUPPORT, theDrive);
|
||
}
|
||
} else {
|
||
ScepLogOutput3(1, GetLastError(),
|
||
SCEDLL_ERROR_QUERY_VOLUME, theDrive);
|
||
}
|
||
} else {
|
||
|
||
pOneRoot->Status = SCE_STATUS_NO_ACL_SUPPORT;
|
||
ScepLogOutput3(1, 0, SCEDLL_NO_ACL_SUPPORT, theDrive);
|
||
}
|
||
|
||
}
|
||
|
||
if ( pOneRoot->Status != SCE_STATUS_CHECK &&
|
||
pOneRoot->Status != SCE_STATUS_NO_AUTO_INHERIT &&
|
||
pOneRoot->Status != SCE_STATUS_OVERWRITE)
|
||
continue;
|
||
|
||
//
|
||
// if system is shutting down within policy propagation,
|
||
// quit as soon as possible
|
||
//
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
break;
|
||
}
|
||
|
||
rc = ScepGetOneSection(
|
||
hProfile,
|
||
Area,
|
||
pOneRoot->Name,
|
||
bPolicyProp ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
|
||
(PVOID *)&pSecurityObject
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
SaveStat = rc;
|
||
continue; //goto Done;
|
||
}
|
||
|
||
#ifdef _WIN64
|
||
|
||
//
|
||
// on a 64-bit platform, if the closest ancestor of "Machine\Software\Wow6432Node"
|
||
// specified in the template, has mode 2, we have to insert "Machine\Software\Wow6432Node"
|
||
// in the tree in the SCE_STATUS_IGNORE mode since this 32-bit hive should not be
|
||
// configured by SCE in the 64-bit phase (same situation for '0' mode is handled by MARTA apis)
|
||
//
|
||
|
||
if ( Area == AREA_REGISTRY_SECURITY ) {
|
||
|
||
if ( _wcsnicmp(pSecurityObject->Node->ObjectFullName,
|
||
L"MACHINE",
|
||
sizeof(L"MACHINE")/sizeof(WCHAR) - 1
|
||
) == 0 ){
|
||
|
||
//
|
||
// idea is to find mode of closest ancestor of "Machine\Software\Wow6432Node"
|
||
//
|
||
|
||
PSCE_OBJECT_CHILD_LIST pSearchSwHiveNode = pSecurityObject->Node->ChildList;
|
||
BYTE byClosestAncestorStatus;
|
||
|
||
//
|
||
// we need to do the 32-bit phase only if we get in here
|
||
// so remember HKLM ptr in the tree for 32-bit phase
|
||
//
|
||
|
||
pHKLMSubtreeRoot = pSecurityObject;
|
||
bIsHKLMSubtree = TRUE;
|
||
|
||
//
|
||
// try to find "Machine\Software"
|
||
//
|
||
|
||
while ( pSearchSwHiveNode ) {
|
||
|
||
if ( pSearchSwHiveNode->Node &&
|
||
_wcsnicmp(pSearchSwHiveNode->Node->ObjectFullName + (sizeof(L"MACHINE")/sizeof(WCHAR)),
|
||
L"SOFTWARE",
|
||
sizeof(L"SOFTWARE")/sizeof(WCHAR) - 1
|
||
) == 0 ) {
|
||
|
||
//
|
||
// found "Machine\Software"
|
||
//
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
pSearchSwHiveNode = pSearchSwHiveNode->Next;
|
||
}
|
||
|
||
byClosestAncestorStatus = (pSearchSwHiveNode && pSearchSwHiveNode->Node) ? pSearchSwHiveNode->Node->Status : pHKLMSubtreeRoot->Node->Status;
|
||
|
||
//
|
||
// if mode of closest ancestor of "Machine\Software\Wow6432Node" is
|
||
// SCE_STATUS_OVERWRITE or "Machine\Software" has some children
|
||
// need to add "Machine\Software\Wow6432Node" with SCE_STATUS_IGNORE
|
||
// to the tree
|
||
//
|
||
|
||
if ( ( pSearchSwHiveNode && pSearchSwHiveNode->Node &&
|
||
pSearchSwHiveNode->Node->ChildList != NULL) ||
|
||
byClosestAncestorStatus == SCE_STATUS_OVERWRITE ) {
|
||
|
||
rc = ScepBuildObjectTree(
|
||
NULL,
|
||
&pSecurityObject,
|
||
1,
|
||
L'\\',
|
||
L"MACHINE\\SOFTWARE\\WOW6432Node",
|
||
1,
|
||
SCE_STATUS_IGNORE,
|
||
NULL,
|
||
0
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
SaveStat = rc;
|
||
|
||
ScepFreeObject2Security( pSecurityObject, FALSE);
|
||
pSecurityObject = NULL;
|
||
|
||
continue; //goto Done;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
//
|
||
// then process each node in the list
|
||
//
|
||
for (PSCE_OBJECT_CHILD_LIST pTemp = pSecurityObject; pTemp != NULL; pTemp=pTemp->Next) {
|
||
|
||
if ( pTemp->Node == NULL ) continue;
|
||
|
||
if ( Area == AREA_FILE_SECURITY ) {
|
||
if ( pTemp->Node->ObjectFullName[1] == L':' &&
|
||
pTemp->Node->ObjectFullName[2] == L'\0' ) {
|
||
|
||
pTemp->Node->ObjectFullName[2] = L'\\';
|
||
pTemp->Node->ObjectFullName[3] = L'\0';
|
||
}
|
||
}
|
||
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
//
|
||
// calculate the "real" security descriptor for each node
|
||
//
|
||
if ( Area == AREA_FILE_SECURITY ) {
|
||
rc = ScepCalculateSecurityToApply(
|
||
pTemp->Node,
|
||
SE_FILE_OBJECT,
|
||
Token,
|
||
&FileGenericMapping
|
||
);
|
||
} else if ( Area == AREA_REGISTRY_SECURITY ) {
|
||
rc = ScepCalculateSecurityToApply(
|
||
pTemp->Node,
|
||
SE_REGISTRY_KEY,
|
||
Token,
|
||
&KeyGenericMapping
|
||
);
|
||
}
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
if ( Area == AREA_FILE_SECURITY ) {
|
||
rc = ScepConfigureObjectTree(
|
||
pTemp->Node,
|
||
SE_FILE_OBJECT,
|
||
Token,
|
||
&FileGenericMapping,
|
||
ConfigOptions
|
||
);
|
||
|
||
} else if ( Area == AREA_REGISTRY_SECURITY ) {
|
||
rc = ScepConfigureObjectTree(
|
||
pTemp->Node,
|
||
SE_REGISTRY_KEY,
|
||
Token,
|
||
&KeyGenericMapping,
|
||
ConfigOptions
|
||
);
|
||
|
||
} else {
|
||
// ds objects
|
||
rc = ScepConfigureDsSecurity( pTemp->Node);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
SaveStat = rc;
|
||
}
|
||
|
||
#ifdef _WIN64
|
||
//
|
||
// If 64-bit platform and AREA_REGISTRY_SECURITY and HKLM, do
|
||
// not free the whole subtree , only free the computed SDs
|
||
//
|
||
|
||
if (Area == AREA_FILE_SECURITY)
|
||
ScepFreeObject2Security( pSecurityObject, FALSE);
|
||
else if (Area == AREA_REGISTRY_SECURITY)
|
||
ScepFreeObject2Security( pSecurityObject, bIsHKLMSubtree);
|
||
|
||
bIsHKLMSubtree = FALSE;
|
||
#else
|
||
ScepFreeObject2Security( pSecurityObject, FALSE);
|
||
#endif
|
||
pSecurityObject = NULL;
|
||
|
||
//
|
||
// stop right away if bPolicyProp and system is being shutdown
|
||
//
|
||
|
||
if (rc == SCESTATUS_SERVICE_NOT_SUPPORT)
|
||
break;
|
||
|
||
}
|
||
|
||
if ( Area == AREA_REGISTRY_SECURITY ) {
|
||
|
||
if ( SaveStat != SCESTATUS_SUCCESS ) {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_SUCCESS);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
#ifdef _WIN64
|
||
|
||
//
|
||
// on a 64-bit platform, if AREA_REGISTRY_SECURITY, will have to recompute
|
||
// security and apply for the same keys as before except that it is for the
|
||
// 32-bit hives this time around (idea is to synchronize 64-bit and 32 bit
|
||
// registry security). There is no need to rebuild the tree from the template.
|
||
//
|
||
|
||
if (rc != SCESTATUS_SERVICE_NOT_SUPPORT && Area == AREA_REGISTRY_SECURITY) {
|
||
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_BEGIN_REGISTRY_32KEY);
|
||
|
||
if (pSecurityObject = pHKLMSubtreeRoot) {
|
||
|
||
//
|
||
// nothing needs to be done to the Wow6432Node that was added in SCE_STATUS_IGNORE
|
||
// mode in the 64-bit phase since it is illegal to specify Wow6432Node in the template
|
||
// (the plan is that registry APIs will treat "Wow6432Node" as a reserved keyname)
|
||
//
|
||
|
||
//
|
||
// we will set SCE_STATUS_IGNORE mode to all immediate nodes under HKLM except
|
||
// HKLM\Software. This will take care of HKLM or HKLM\Software being specified
|
||
// in any mode etc. as though it was 32-bit registry configuration, since all
|
||
// we care about now is 32-bit configuration for HKLM\Software and under
|
||
//
|
||
|
||
PSCE_OBJECT_CHILD_LIST pHKLMChild = pSecurityObject->Node->ChildList;
|
||
|
||
while ( pHKLMChild ) {
|
||
|
||
if ( pHKLMChild->Node &&
|
||
_wcsnicmp(pHKLMChild->Node->ObjectFullName + (sizeof(L"MACHINE")/sizeof(WCHAR)),
|
||
L"SOFTWARE",
|
||
sizeof(L"SOFTWARE")/sizeof(WCHAR) - 1
|
||
) != 0 ) {
|
||
|
||
//
|
||
// not "Machine\Software"
|
||
//
|
||
|
||
pHKLMChild->Node->Status = SCE_STATUS_IGNORE;
|
||
|
||
}
|
||
|
||
pHKLMChild = pHKLMChild->Next;
|
||
}
|
||
|
||
|
||
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
//
|
||
// calculate the "real" security descriptor for each node
|
||
//
|
||
rc = ScepCalculateSecurityToApply(
|
||
pSecurityObject->Node,
|
||
SE_REGISTRY_WOW64_32KEY,
|
||
Token,
|
||
&KeyGenericMapping
|
||
);
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
if ( bPolicyProp &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
|
||
} else {
|
||
|
||
rc = ScepConfigureObjectTree(
|
||
pSecurityObject->Node,
|
||
SE_REGISTRY_WOW64_32KEY,
|
||
Token,
|
||
&KeyGenericMapping,
|
||
ConfigOptions
|
||
);
|
||
|
||
}
|
||
}
|
||
|
||
//
|
||
// Free the whole tree now (done with 32-bit phase)
|
||
//
|
||
|
||
ScepFreeObject2Security( pSecurityObject, FALSE);
|
||
pSecurityObject = NULL;
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
SaveStat = rc;
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_ERROR);
|
||
} else {
|
||
ScepLogOutput3(0,0, SCEDLL_SCP_REGISTRY_SUCCESS);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
if( AdminsSid != NULL ) {
|
||
RtlFreeSid( AdminsSid );
|
||
AdminsSid = NULL;
|
||
}
|
||
|
||
SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
|
||
//
|
||
// disable take ownership privilege, even for administrators
|
||
// because by default it's disabled
|
||
//
|
||
SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, FALSE, Token );
|
||
|
||
CloseHandle(Token);
|
||
|
||
if ( pSecurityObject != NULL ) {
|
||
ScepFreeObject2Security( pSecurityObject, FALSE);
|
||
}
|
||
|
||
return(SaveStat);
|
||
}
|
||
|
||
|
||
DWORD
|
||
ScepConfigureSystemAuditing(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
/* ++
|
||
|
||
Routine Description:
|
||
|
||
This routine configure the system security in the area of auditing which
|
||
includes event log setting, audit event setting, SACL for registry, and
|
||
SACL for files.
|
||
|
||
Arguments:
|
||
|
||
scpInfo - The buffer which contains SCP info loaded from the INF file
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
DWORD rc = NO_ERROR;
|
||
DWORD Saverc = NO_ERROR;
|
||
DWORD MaxSize=0;
|
||
DWORD Retention=0;
|
||
DWORD RestrictGuest=0;
|
||
DWORD OldMaxSize,OldRetention,OldGuest;
|
||
DWORD AuditLogRetentionPeriod, RetentionDays;
|
||
TCHAR MsgBuf[256];
|
||
DWORD i;
|
||
BOOL bFlagSet=FALSE;
|
||
|
||
PCWSTR szAuditSection=NULL;
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
|
||
//
|
||
// Set audit log information. Audit Log settings are saved in the Registry
|
||
// under System\CurrentControlSet\Services\EventLog\<LogName>\MaxSize and Retention
|
||
//
|
||
|
||
for ( i=0; i<3; i++) {
|
||
|
||
if ( pScpInfo->MaximumLogSize[i] == SCE_NO_VALUE )
|
||
MaxSize = SCE_NO_VALUE;
|
||
else
|
||
MaxSize = (pScpInfo->MaximumLogSize[i] - (pScpInfo->MaximumLogSize[i] % 64 )) * 1024;
|
||
|
||
switch ( pScpInfo->AuditLogRetentionPeriod[i] ) {
|
||
case SCE_NO_VALUE:
|
||
Retention = SCE_NO_VALUE;
|
||
break;
|
||
case 2: // manually
|
||
Retention = MAXULONG;
|
||
break;
|
||
case 1: // number of days * seconds/day
|
||
if ( pScpInfo->RetentionDays[i] == SCE_NO_VALUE ) {
|
||
Retention = SCE_NO_VALUE;
|
||
} else {
|
||
Retention = pScpInfo->RetentionDays[i] * 24 * 3600;
|
||
}
|
||
break;
|
||
case 0: // as needed
|
||
Retention = 0;
|
||
break;
|
||
}
|
||
|
||
if ( pScpInfo->RestrictGuestAccess[i] == SCE_NO_VALUE )
|
||
RestrictGuest = SCE_NO_VALUE;
|
||
else
|
||
RestrictGuest = (pScpInfo->RestrictGuestAccess[i])? 1 : 0;
|
||
//
|
||
// Different logs have different keys in Registry
|
||
//
|
||
if ( MaxSize != SCE_NO_VALUE || Retention != SCE_NO_VALUE ||
|
||
RestrictGuest != SCE_NO_VALUE ) {
|
||
|
||
bFlagSet = TRUE;
|
||
|
||
switch (i) {
|
||
case 0:
|
||
wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\System");
|
||
szAuditSection = szAuditSystemLog;
|
||
break;
|
||
case 1:
|
||
|
||
wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Security");
|
||
szAuditSection = szAuditSecurityLog;
|
||
break;
|
||
default:
|
||
|
||
wcscpy(MsgBuf,L"System\\CurrentControlSet\\Services\\EventLog\\Application");
|
||
szAuditSection = szAuditApplicationLog;
|
||
break;
|
||
}
|
||
|
||
WCHAR StrBuf[2];
|
||
_itow(i, StrBuf, 10);
|
||
|
||
//
|
||
// open policy sections
|
||
//
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szAuditSection,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
OldMaxSize=0;
|
||
OldRetention=0;
|
||
OldGuest=0;
|
||
}
|
||
|
||
if ( MaxSize != SCE_NO_VALUE ) {
|
||
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
|
||
//
|
||
// query existing value
|
||
//
|
||
if ( ERROR_SUCCESS != ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"MaxSize",
|
||
&OldMaxSize
|
||
) )
|
||
OldMaxSize = SCE_NO_VALUE;
|
||
else
|
||
OldMaxSize /= 1024;
|
||
}
|
||
|
||
rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"MaxSize",
|
||
MaxSize
|
||
);
|
||
|
||
//
|
||
// compare and set if different
|
||
//
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(OldMaxSize != SCE_NO_VALUE) ) {
|
||
|
||
// even if OldMaxSize = MaxSize, we still need to check if the tattoo value should be deleted
|
||
ScepTattooManageOneIntValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
L"MaximumLogSize",
|
||
0,
|
||
OldMaxSize,
|
||
rc
|
||
);
|
||
}
|
||
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_AUDIT_LOG_MAXSIZE_INFO, rc, StrBuf,0,0);
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS && Retention != SCE_NO_VALUE ) {
|
||
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
|
||
//
|
||
// query existing value
|
||
//
|
||
if ( ERROR_SUCCESS == ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"Retention",
|
||
&OldRetention
|
||
) ) {
|
||
switch ( OldRetention ) {
|
||
case MAXULONG: // manually
|
||
AuditLogRetentionPeriod = 2;
|
||
RetentionDays = SCE_NO_VALUE;
|
||
break;
|
||
case 0:
|
||
AuditLogRetentionPeriod = 0;
|
||
RetentionDays = SCE_NO_VALUE;
|
||
break;
|
||
default:
|
||
AuditLogRetentionPeriod = 1;
|
||
|
||
// number of days * seconds/day
|
||
RetentionDays = OldRetention / (24 * 3600);
|
||
break;
|
||
}
|
||
} else {
|
||
AuditLogRetentionPeriod = SCE_NO_VALUE;
|
||
RetentionDays = SCE_NO_VALUE;
|
||
}
|
||
}
|
||
|
||
rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"Retention",
|
||
Retention
|
||
);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(OldRetention != SCE_NO_VALUE) ) {
|
||
|
||
//
|
||
// handle the RetentionDays first since
|
||
// it depends on auditlogretentionperiod
|
||
//
|
||
if ( RetentionDays != SCE_NO_VALUE ||
|
||
pScpInfo->RetentionDays[i] != SCE_NO_VALUE ) {
|
||
|
||
ScepTattooManageOneIntValueWithDependency(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
L"AuditLogRetentionPeriod",
|
||
0,
|
||
L"RetentionDays",
|
||
RetentionDays,
|
||
rc
|
||
);
|
||
}
|
||
|
||
ScepTattooManageOneIntValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
L"AuditLogRetentionPeriod",
|
||
0,
|
||
AuditLogRetentionPeriod,
|
||
rc
|
||
);
|
||
}
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_AUDIT_LOG_RETENTION_INFO, rc, StrBuf,0,0);
|
||
}
|
||
if ( rc == SCESTATUS_SUCCESS && RestrictGuest != SCE_NO_VALUE ) {
|
||
|
||
if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
|
||
|
||
//
|
||
// query existing value
|
||
//
|
||
if ( ERROR_SUCCESS != ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"RestrictGuestAccess",
|
||
&OldGuest
|
||
) )
|
||
OldGuest = SCE_NO_VALUE;
|
||
}
|
||
|
||
rc = ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
|
||
MsgBuf,
|
||
L"RestrictGuestAccess",
|
||
RestrictGuest
|
||
);
|
||
|
||
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
||
(OldGuest != SCE_NO_VALUE) ) {
|
||
|
||
ScepTattooManageOneIntValue(
|
||
hSectionDomain,
|
||
hSectionTattoo,
|
||
L"RestrictGuestAccess",
|
||
0,
|
||
OldGuest,
|
||
rc
|
||
);
|
||
}
|
||
if (ConfigOptions & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_AUDIT_LOG_GUEST_INFO, rc, StrBuf,0,0);
|
||
}
|
||
|
||
if ( hSectionDomain ) {
|
||
SceJetCloseSection(&hSectionDomain, TRUE);
|
||
hSectionDomain = NULL;
|
||
}
|
||
|
||
if ( hSectionTattoo ) {
|
||
SceJetCloseSection(&hSectionTattoo, TRUE);
|
||
hSectionTattoo = NULL;
|
||
}
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_LOGSETTINGS);
|
||
}
|
||
}
|
||
|
||
if ( Saverc == SCESTATUS_SUCCESS && bFlagSet )
|
||
ScepLogOutput3(1,0, SCEDLL_SCP_LOGSETTINGS);
|
||
|
||
return(Saverc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureAuditEvent(
|
||
IN PSCE_PROFILE_INFO pScpInfo,
|
||
IN PPOLICY_AUDIT_EVENTS_INFO auditEvent,
|
||
IN DWORD Options,
|
||
IN LSA_HANDLE PolicyHandle OPTIONAL
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
LSA_HANDLE lsaHandle=NULL;
|
||
DWORD rc = NO_ERROR;
|
||
DWORD Saverc = NO_ERROR;
|
||
// POLICY_AUDIT_FULL_SET_INFO AuditFullSet;
|
||
PPOLICY_AUDIT_FULL_QUERY_INFO AuditFullQry=NULL;
|
||
ULONG i;
|
||
ULONG dwAudit;
|
||
|
||
SCE_TATTOO_KEYS *pTattooKeys=NULL;
|
||
DWORD cTattooKeys=0;
|
||
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
|
||
#define MAX_AUDIT_KEYS 9
|
||
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
ScepIsSystemShutDown() ) {
|
||
|
||
return(SCESTATUS_SERVICE_NOT_SUPPORT);
|
||
}
|
||
|
||
if ( PolicyHandle == NULL ) {
|
||
|
||
//
|
||
// Set audit event information using LSA APIs
|
||
//
|
||
status = ScepOpenLsaPolicy(
|
||
POLICY_VIEW_AUDIT_INFORMATION |
|
||
POLICY_SET_AUDIT_REQUIREMENTS |
|
||
POLICY_AUDIT_LOG_ADMIN,
|
||
&lsaHandle,
|
||
( Options & (SCE_POLICY_TEMPLATE | SCE_SYSTEM_DB) ) ? TRUE : FALSE // do not notify policy filter if within policy prop
|
||
);
|
||
|
||
if (status != ERROR_SUCCESS) {
|
||
|
||
lsaHandle = NULL;
|
||
rc = RtlNtStatusToDosError( status );
|
||
|
||
ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
|
||
|
||
if (Options & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
|
||
|
||
return(ScepDosErrorToSceStatus(rc));
|
||
}
|
||
|
||
} else {
|
||
lsaHandle = PolicyHandle;
|
||
}
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) ) {
|
||
//
|
||
// save off the current auditing settings
|
||
//
|
||
pTattooKeys = (SCE_TATTOO_KEYS *)ScepAlloc(LPTR,MAX_AUDIT_KEYS*sizeof(SCE_TATTOO_KEYS));
|
||
|
||
if ( !pTattooKeys ) {
|
||
ScepLogOutput3(1, ERROR_NOT_ENOUGH_MEMORY, SCESRV_POLICY_TATTOO_ERROR_CREATE);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Set audit event information
|
||
//
|
||
|
||
if ( !auditEvent->AuditingMode ) {
|
||
// reset the event array
|
||
for ( i=0; i<auditEvent->MaximumAuditEventCount; i++ )
|
||
auditEvent->EventAuditingOptions[i] = POLICY_AUDIT_EVENT_NONE;
|
||
}
|
||
//
|
||
// process each event
|
||
//
|
||
i=0;
|
||
if ( (pScpInfo->AuditSystemEvents != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategorySystem] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditSystemEvents", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditSystemEvents != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategorySystem] =
|
||
(pScpInfo->AuditSystemEvents & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditSystemEvents & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditLogonEvents != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryLogon] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditLogonEvents", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditLogonEvents != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryLogon] =
|
||
(pScpInfo->AuditLogonEvents & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditLogonEvents & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditObjectAccess != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryObjectAccess] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditObjectAccess", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditObjectAccess != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryObjectAccess] =
|
||
(pScpInfo->AuditObjectAccess & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditObjectAccess & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditPrivilegeUse != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditPrivilegeUse", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditPrivilegeUse != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryPrivilegeUse] =
|
||
(pScpInfo->AuditPrivilegeUse & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditPrivilegeUse & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditProcessTracking != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryDetailedTracking] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditProcessTracking", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditProcessTracking != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryDetailedTracking] =
|
||
(pScpInfo->AuditProcessTracking & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditProcessTracking & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditPolicyChange != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryPolicyChange] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditPolicyChange", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditPolicyChange != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryPolicyChange] =
|
||
(pScpInfo->AuditPolicyChange & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditPolicyChange & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditAccountManage != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryAccountManagement] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditAccountManage", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditAccountManage != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryAccountManagement] =
|
||
(pScpInfo->AuditAccountManage & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditAccountManage & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditDSAccess != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditDSAccess", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditDSAccess != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryDirectoryServiceAccess] =
|
||
(pScpInfo->AuditDSAccess & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditDSAccess & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( (pScpInfo->AuditAccountLogon != SCE_NO_VALUE) ) {
|
||
|
||
dwAudit = (auditEvent->EventAuditingOptions[AuditCategoryAccountLogon] & ~POLICY_AUDIT_EVENT_NONE );
|
||
ScepTattooCheckAndUpdateArray(pTattooKeys, &cTattooKeys,
|
||
(PWSTR)L"AuditAccountLogon", Options,
|
||
dwAudit );
|
||
|
||
if ( (pScpInfo->AuditAccountLogon != dwAudit) ) {
|
||
|
||
auditEvent->EventAuditingOptions[AuditCategoryAccountLogon] =
|
||
(pScpInfo->AuditAccountLogon & POLICY_AUDIT_EVENT_SUCCESS) |
|
||
(pScpInfo->AuditAccountLogon & POLICY_AUDIT_EVENT_FAILURE) |
|
||
POLICY_AUDIT_EVENT_NONE;
|
||
i=1;
|
||
}
|
||
}
|
||
|
||
if ( i ) {
|
||
//
|
||
// there are some settings to configure
|
||
//
|
||
auditEvent->AuditingMode = FALSE;
|
||
for ( i=0; i<auditEvent->MaximumAuditEventCount; i++ ) {
|
||
if ( auditEvent->EventAuditingOptions[i] & ~POLICY_AUDIT_EVENT_NONE ) {
|
||
auditEvent->AuditingMode = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
status = LsaSetInformationPolicy( lsaHandle,
|
||
PolicyAuditEventsInformation,
|
||
(PVOID)auditEvent
|
||
);
|
||
rc = RtlNtStatusToDosError( status );
|
||
|
||
if ( rc != NO_ERROR ) {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
|
||
|
||
Saverc = rc;
|
||
} else {
|
||
ScepLogOutput3(1, 0, SCEDLL_SCP_EVENT_AUDITING);
|
||
}
|
||
//
|
||
// turn the mode off so auditing won't be "restored" at the end of configuration
|
||
//
|
||
|
||
auditEvent->AuditingMode = FALSE;
|
||
}
|
||
|
||
if ( (Options & SCE_POLICY_TEMPLATE) &&
|
||
( ProductType != NtProductLanManNt ) &&
|
||
pTattooKeys && cTattooKeys ) {
|
||
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szAuditEvent,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
//
|
||
// some policy is different than the system setting
|
||
// check if we should save the existing setting as the tattoo value
|
||
// also remove reset'ed tattoo policy
|
||
//
|
||
ScepLogOutput3(3,0,SCESRV_POLICY_TATTOO_ARRAY,cTattooKeys);
|
||
|
||
ScepTattooManageValues(hSectionDomain, hSectionTattoo, pTattooKeys, cTattooKeys, rc);
|
||
|
||
if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain,TRUE);
|
||
if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo,TRUE);
|
||
|
||
}
|
||
|
||
if ( pTattooKeys )
|
||
ScepFree(pTattooKeys);
|
||
|
||
if (Options & SCE_RSOP_CALLBACK)
|
||
|
||
ScepRsopLog(SCE_RSOP_AUDIT_EVENT_INFO, rc, NULL,0,0);
|
||
|
||
if ( lsaHandle && (PolicyHandle != lsaHandle) )
|
||
LsaClose( lsaHandle );
|
||
|
||
return(ScepDosErrorToSceStatus(Saverc));
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigureDeInitialize(
|
||
IN SCESTATUS rc,
|
||
IN AREA_INFORMATION Area
|
||
)
|
||
|
||
/*++
|
||
Routine Description:
|
||
|
||
This routine de-initialize the SCP engine. The operations include
|
||
|
||
clear SCE_PROFILE_INFO buffer and close the SCP profile
|
||
close the error log file
|
||
reset the status
|
||
|
||
Arguments:
|
||
|
||
rc - SCESTATUS error code (from other routines)
|
||
|
||
Area - one or more area configured
|
||
|
||
Return value:
|
||
|
||
SCESTATUS error code
|
||
|
||
++*/
|
||
{
|
||
if ( rc == SCESTATUS_ALREADY_RUNNING ) {
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// free LSA handle
|
||
//
|
||
if ( LsaPrivatePolicy ) {
|
||
|
||
ScepNotifyLogPolicy(0, TRUE, L"Policy Prop: Private LSA handle is to be released", 0, 0, NULL );
|
||
|
||
LsaClose(LsaPrivatePolicy);
|
||
LsaPrivatePolicy = NULL;
|
||
|
||
}
|
||
|
||
//
|
||
// Free memory and close the SCP profile
|
||
//
|
||
|
||
SceFreeMemory( (PVOID)pScpInfo, Area );
|
||
|
||
cbClientFlag = 0;
|
||
gTotalTicks = 0;
|
||
gCurrentTicks = 0;
|
||
gWarningCode = 0;
|
||
|
||
if ( hProfile != NULL ) {
|
||
|
||
SceJetCloseFile( hProfile, TRUE, FALSE );
|
||
}
|
||
|
||
hProfile = NULL;
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepDeleteInfoForAreas(
|
||
IN PSCECONTEXT hProfile,
|
||
IN SCETYPE tblType,
|
||
IN AREA_INFORMATION Area
|
||
)
|
||
{
|
||
SCESTATUS saveRc=SCESTATUS_SUCCESS, rc;
|
||
PSCE_SERVICES pServices=NULL, pNode;
|
||
PSCE_NAME_LIST pList=NULL, pnl;
|
||
|
||
if ( Area & AREA_SECURITY_POLICY ) {
|
||
//
|
||
// delete szSystemAccess section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szSystemAccess
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szAuditSystemLog section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szAuditSystemLog
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szAuditSecurityLog section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szAuditSecurityLog
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szAuditApplicationLog section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szAuditApplicationLog
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szAuditEvent section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szAuditEvent
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szKerberosPolicy section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szKerberosPolicy
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete szRegistryValues section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szRegistryValues
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
//
|
||
// delete each attachment's sections
|
||
//
|
||
rc = ScepEnumServiceEngines( &pServices, SCE_ATTACHMENT_POLICY );
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
for ( pNode = pServices; pNode != NULL; pNode=pNode->Next ) {
|
||
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
(PCWSTR)(pNode->ServiceName)
|
||
);
|
||
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
SceFreePSCE_SERVICES( pServices );
|
||
|
||
} else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
|
||
rc != SCESTATUS_RECORD_NOT_FOUND &&
|
||
saveRc == SCESTATUS_SUCCESS ) {
|
||
saveRc = rc;
|
||
}
|
||
|
||
}
|
||
|
||
if ( Area & AREA_PRIVILEGES ) {
|
||
//
|
||
// delete szPrivilegeRights section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szPrivilegeRights
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
|
||
}
|
||
if ( Area & AREA_GROUP_MEMBERSHIP ) {
|
||
|
||
//
|
||
// delete szGroupMembership section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szGroupMembership
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
if ( Area & AREA_USER_SETTINGS ) {
|
||
//
|
||
// later - delete the list of profiles/users first
|
||
//
|
||
|
||
//
|
||
// delete szAccountProfiles/szUserList section info
|
||
//
|
||
if ( tblType == SCEJET_TABLE_SAP) {
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szUserList
|
||
);
|
||
} else {
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szAccountProfiles
|
||
);
|
||
}
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
if ( Area & AREA_FILE_SECURITY ) {
|
||
|
||
//
|
||
// delete szFileSecurity section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szFileSecurity
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
if ( Area & AREA_REGISTRY_SECURITY ) {
|
||
|
||
//
|
||
// delete szRegistryKeys section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szRegistryKeys
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
if ( Area & AREA_DS_OBJECTS ) {
|
||
|
||
//
|
||
// delete szDSSecurity section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szDSSecurity
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
if ( Area & AREA_SYSTEM_SERVICE ) {
|
||
|
||
//
|
||
// delete szServiceGeneral section info
|
||
//
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
szServiceGeneral
|
||
);
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
//
|
||
// delete each attachment's sections
|
||
//
|
||
rc = ScepEnumServiceEngines( &pServices, SCE_ATTACHMENT_SERVICE );
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
for ( pNode = pServices; pNode != NULL; pNode=pNode->Next ) {
|
||
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
(PCWSTR)(pNode->ServiceName)
|
||
);
|
||
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
SceFreePSCE_SERVICES( pServices );
|
||
|
||
} else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
|
||
rc != SCESTATUS_RECORD_NOT_FOUND &&
|
||
saveRc == SCESTATUS_SUCCESS ) {
|
||
saveRc = rc;
|
||
}
|
||
}
|
||
|
||
if ( Area & AREA_ATTACHMENTS ) {
|
||
//
|
||
// delete attachment sections
|
||
//
|
||
rc = ScepEnumAttachmentSections( hProfile, &pList);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
for ( pnl = pList; pnl != NULL; pnl=pnl->Next ) {
|
||
|
||
rc = ScepDeleteOneSection(
|
||
hProfile,
|
||
tblType,
|
||
(PCWSTR)(pnl->Name)
|
||
);
|
||
|
||
if ( saveRc == SCESTATUS_SUCCESS )
|
||
saveRc = rc;
|
||
}
|
||
|
||
ScepFreeNameList( pList );
|
||
|
||
} else if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
|
||
rc != SCESTATUS_RECORD_NOT_FOUND &&
|
||
saveRc == SCESTATUS_SUCCESS ) {
|
||
saveRc = rc;
|
||
}
|
||
}
|
||
|
||
return(saveRc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepMakePolicyIntoFile(
|
||
IN DWORD Options,
|
||
IN AREA_INFORMATION Area
|
||
)
|
||
{
|
||
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
|
||
if ( Options & SCE_COPY_LOCAL_POLICY ) {
|
||
|
||
PSCE_PROFILE_INFO pTmpBuffer=NULL;
|
||
|
||
HINSTANCE hSceCliDll = LoadLibrary(TEXT("scecli.dll"));
|
||
|
||
if ( hSceCliDll) {
|
||
PFSCEINFWRITEINFO pfSceInfWriteInfo = (PFSCEINFWRITEINFO)GetProcAddress(
|
||
hSceCliDll,
|
||
"SceWriteSecurityProfileInfo");
|
||
if ( pfSceInfWriteInfo ) {
|
||
|
||
//
|
||
// have to query the current system setting for privileges
|
||
// because IIS/MTS accounts do not exist in our database
|
||
// we only support AREA_SECURITY_POLICY and AREA_PRIVILEGES
|
||
//
|
||
|
||
TCHAR Buffer[MAX_PATH+1];
|
||
TCHAR FileName[MAX_PATH+50];
|
||
|
||
Buffer[0] = L'\0';
|
||
GetSystemWindowsDirectory(Buffer, MAX_PATH);
|
||
Buffer[MAX_PATH] = L'\0';
|
||
|
||
if ( Area & AREA_SECURITY_POLICY ) {
|
||
|
||
//
|
||
// get other area's information (AREA_SECURITY_POLICY)
|
||
//
|
||
rc = ScepGetDatabaseInfo(
|
||
hProfile,
|
||
SCE_ENGINE_SMP,
|
||
AREA_SECURITY_POLICY,
|
||
0,
|
||
&pTmpBuffer,
|
||
NULL
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
wcscpy(FileName, Buffer);
|
||
wcscat(FileName, L"\\security\\FirstDGPO.inf\0");
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MinimumPasswordAge"),
|
||
pTmpBuffer->MinimumPasswordAge
|
||
);
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MaximumPasswordAge"),
|
||
pTmpBuffer->MaximumPasswordAge
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MinimumPasswordLength"),
|
||
pTmpBuffer->MinimumPasswordLength
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("PasswordComplexity"),
|
||
pTmpBuffer->PasswordComplexity
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("PasswordHistorySize"),
|
||
pTmpBuffer->PasswordHistorySize
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("LockoutBadCount"),
|
||
pTmpBuffer->LockoutBadCount
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("ResetLockoutCount"),
|
||
pTmpBuffer->ResetLockoutCount
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("LockoutDuration"),
|
||
pTmpBuffer->LockoutDuration
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("RequireLogonToChangePassword"),
|
||
pTmpBuffer->RequireLogonToChangePassword
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("ForceLogoffWhenHourExpire"),
|
||
pTmpBuffer->ForceLogoffWhenHourExpire
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szSystemAccess,
|
||
(LPCTSTR)FileName,
|
||
TEXT("ClearTextPassword"),
|
||
pTmpBuffer->ClearTextPassword
|
||
);
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc && pTmpBuffer->pKerberosInfo ) {
|
||
|
||
rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MaxTicketAge"),
|
||
pTmpBuffer->pKerberosInfo->MaxTicketAge
|
||
);
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MaxRenewAge"),
|
||
pTmpBuffer->pKerberosInfo->MaxRenewAge
|
||
);
|
||
}
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MaxServiceAge"),
|
||
pTmpBuffer->pKerberosInfo->MaxServiceAge
|
||
);
|
||
}
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
|
||
(LPCTSTR)FileName,
|
||
TEXT("MaxClockSkew"),
|
||
pTmpBuffer->pKerberosInfo->MaxClockSkew
|
||
);
|
||
}
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
rc = ScepWriteOneAttributeToFile(szKerberosPolicy,
|
||
(LPCTSTR)FileName,
|
||
TEXT("TicketValidateClient"),
|
||
pTmpBuffer->pKerberosInfo->TicketValidateClient
|
||
);
|
||
}
|
||
}
|
||
|
||
if ( ERROR_SUCCESS == rc ) {
|
||
//
|
||
// make sure to delete the local policy sections
|
||
//
|
||
WritePrivateProfileSection(
|
||
szAuditSystemLog,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
WritePrivateProfileSection(
|
||
szAuditSecurityLog,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
WritePrivateProfileSection(
|
||
szAuditApplicationLog,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
WritePrivateProfileSection(
|
||
szAuditEvent,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
WritePrivateProfileSection(
|
||
szRegistryValues,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
|
||
}
|
||
|
||
ScepLogOutput3(1, rc, IDS_COPY_DOMAIN_GPO);
|
||
|
||
rc = ScepDosErrorToSceStatus(rc);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
wcscpy(FileName, Buffer);
|
||
wcscat(FileName, L"\\security\\FirstOGPO.inf\0");
|
||
//
|
||
// do not write registry value section
|
||
//
|
||
DWORD RegValueCount;
|
||
PSCE_REGISTRY_VALUE_INFO pSaveRegValues;
|
||
|
||
RegValueCount = pTmpBuffer->RegValueCount;
|
||
pSaveRegValues = pTmpBuffer->aRegValues;
|
||
|
||
pTmpBuffer->RegValueCount = 0;
|
||
pTmpBuffer->aRegValues = NULL;
|
||
|
||
rc = (*pfSceInfWriteInfo)(
|
||
FileName,
|
||
AREA_SECURITY_POLICY,
|
||
pTmpBuffer,
|
||
NULL
|
||
);
|
||
//
|
||
// restore the buffer
|
||
//
|
||
|
||
pTmpBuffer->RegValueCount = RegValueCount;
|
||
pTmpBuffer->aRegValues = pSaveRegValues;
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
//
|
||
// delete the domain policy sections from this file
|
||
//
|
||
WritePrivateProfileSection(
|
||
szSystemAccess,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
|
||
WritePrivateProfileSection(
|
||
szKerberosPolicy,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
/*
|
||
WritePrivateProfileSection(
|
||
szRegistryValues,
|
||
NULL,
|
||
(LPCTSTR)FileName);
|
||
*/
|
||
}
|
||
|
||
ScepLogOutput3(1, rc, IDS_COPY_OU_GPO);
|
||
}
|
||
|
||
//
|
||
// free the temp buffer
|
||
//
|
||
SceFreeMemory((PVOID)pTmpBuffer, Area);
|
||
|
||
} else {
|
||
|
||
ScepLogOutput2(1, ScepSceStatusToDosError(rc), L"Unable to read security policy from database");
|
||
}
|
||
}
|
||
|
||
if ( (SCESTATUS_SUCCESS == rc) &&
|
||
(Area & AREA_PRIVILEGES) ) {
|
||
|
||
//
|
||
// privileges must be processed separately
|
||
// because they are saved in the GPO template
|
||
// as "Add/Remove" format
|
||
//
|
||
|
||
wcscpy(FileName, Buffer);
|
||
wcscat(FileName, L"\\security\\FirstOGPO.inf\0");
|
||
|
||
//
|
||
// if security policy is also requested, this must be an upgrade
|
||
//
|
||
|
||
rc = ScepCopyPrivilegesIntoFile(FileName,
|
||
(Area & AREA_SECURITY_POLICY) //TRUE upgrade
|
||
);
|
||
|
||
if ( Area & AREA_SECURITY_POLICY ) {
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_PRIVILEGE_UPGRADE);
|
||
} else {
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_PRIVILEGE_FRESH);
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepLogOutput3(1, GetLastError(), IDS_ERROR_GET_PROCADDR, L"SceWriteSecurityProfileInfo");
|
||
rc = SCESTATUS_MOD_NOT_FOUND;
|
||
}
|
||
|
||
FreeLibrary(hSceCliDll);
|
||
|
||
} else {
|
||
|
||
ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_LOAD, L"scecli.dll");
|
||
rc = SCESTATUS_MOD_NOT_FOUND;
|
||
}
|
||
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
DWORD
|
||
ScepWriteOneAttributeToFile(
|
||
IN LPCTSTR SectionName,
|
||
IN LPCTSTR FileName,
|
||
IN LPCTSTR KeyName,
|
||
IN DWORD dwValue
|
||
)
|
||
{
|
||
|
||
TCHAR valBuf[20];
|
||
DWORD rc=NO_ERROR;
|
||
|
||
if ( dwValue != SCE_NO_VALUE ) {
|
||
|
||
swprintf(valBuf, L"%d", dwValue);
|
||
|
||
if ( !WritePrivateProfileString(SectionName,
|
||
KeyName,
|
||
(LPCTSTR)valBuf,
|
||
FileName
|
||
) ) {
|
||
rc = GetLastError();
|
||
}
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepCopyPrivilegesIntoFile(
|
||
IN LPTSTR FileName,
|
||
IN BOOL bInUpgrade
|
||
)
|
||
{
|
||
if ( FileName == NULL ) {
|
||
return SCESTATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
SCESTATUS rc;
|
||
HINF hInf;
|
||
|
||
rc = SceInfpOpenProfile(
|
||
FileName,
|
||
&hInf
|
||
);
|
||
if ( SCESTATUS_SUCCESS != rc ) {
|
||
return rc;
|
||
}
|
||
|
||
INFCONTEXT InfLine;
|
||
WCHAR Keyname[SCE_KEY_MAX_LENGTH];
|
||
PWSTR StrValue=NULL;
|
||
DWORD ValueLen=0;
|
||
TCHAR TmpNull[2];
|
||
|
||
LSA_HANDLE LsaPolicy=NULL;
|
||
|
||
TmpNull[0] = L'\0';
|
||
TmpNull[1] = L'\0';
|
||
|
||
PSCESECTION hSection=NULL;
|
||
|
||
if ( SetupFindFirstLine(hInf,szPrivilegeRights,NULL,&InfLine) ) {
|
||
|
||
//
|
||
// do not need database access to get privilege
|
||
// must query from system at real time
|
||
//
|
||
|
||
//
|
||
// process each line in the section and save to the scp table.
|
||
// Each INF line has a key and a value.
|
||
//
|
||
|
||
do {
|
||
|
||
memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(TCHAR));
|
||
rc = SCESTATUS_BAD_FORMAT;
|
||
|
||
if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
|
||
|
||
//
|
||
// do not save new privileges into the policy file because
|
||
// W2K clients (DCs) do not support them.
|
||
//
|
||
for (DWORD i=cPrivW2k; i<cPrivCnt; i++) {
|
||
if ( _wcsicmp(Keyname, SCE_Privileges[i].Name) == 0 )
|
||
break;
|
||
}
|
||
if ( i < cPrivCnt ) {
|
||
// this is a new user right
|
||
// do not save it in policy
|
||
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( !WritePrivateProfileString(szPrivilegeRights,
|
||
Keyname,
|
||
NULL,
|
||
FileName
|
||
) ) {
|
||
rc = ScepDosErrorToSceStatus(GetLastError());
|
||
}
|
||
|
||
ScepLogOutput3( 1, ScepDosErrorToSceStatus(rc), SCEDLL_ERROR_IGNORE_POLICY, Keyname);
|
||
|
||
continue;
|
||
}
|
||
|
||
if ( SetupGetMultiSzField(&InfLine, 1, NULL, 0, &ValueLen) ) {
|
||
|
||
if ( ValueLen > 1 ) {
|
||
//
|
||
// allocate buffer for the multi string
|
||
//
|
||
StrValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
|
||
(ValueLen+1)*sizeof(TCHAR));
|
||
|
||
if( StrValue == NULL ) {
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
|
||
} else if( SetupGetMultiSzField(&InfLine, 1, StrValue, ValueLen, NULL) ) {
|
||
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
} else {
|
||
ScepFree(StrValue);
|
||
StrValue = NULL;
|
||
}
|
||
|
||
} else
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
//
|
||
// another format for user rights (ADD: REMOVE:...)
|
||
// Note, if this is within dcpromo upgrade, the current boot
|
||
// is in the temperatory SAM hive (with a bogus domain SID)
|
||
// IIS/MTS users created during this boot are bogus
|
||
// and any users from the NT4 account domain/trusted domain
|
||
// can't be resolved at this moment.
|
||
// So do not enumerate current privileges, instead, use
|
||
// the settings from local security database.
|
||
//
|
||
PWSTR NewValue=NULL;
|
||
DWORD NewLen=0;
|
||
|
||
rc = ScepBuildNewPrivilegeList(&LsaPolicy,
|
||
Keyname,
|
||
StrValue ? StrValue : TmpNull,
|
||
SCE_BUILD_ENUMERATE_PRIV,
|
||
&NewValue,
|
||
&NewLen);
|
||
|
||
if ( StrValue ) {
|
||
ScepFree(StrValue);
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
//
|
||
// convert the multi-sz string into comma delimted
|
||
// and write the new multi-sz string back to the file
|
||
//
|
||
|
||
if ( NewValue ) {
|
||
ScepConvertMultiSzToDelim(NewValue, NewLen, L'\0', L',');
|
||
}
|
||
|
||
if ( !WritePrivateProfileString(szPrivilegeRights,
|
||
Keyname,
|
||
NewValue ? (LPCTSTR)NewValue : (LPCTSTR)TmpNull,
|
||
FileName
|
||
) ) {
|
||
rc = ScepDosErrorToSceStatus(GetLastError());
|
||
}
|
||
}
|
||
|
||
if ( NewValue ) {
|
||
ScepFree(NewValue);
|
||
}
|
||
NewValue = NULL;
|
||
}
|
||
|
||
StrValue = NULL;
|
||
|
||
}
|
||
|
||
if (rc != SCESTATUS_SUCCESS)
|
||
ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
|
||
SCEDLL_ERROR_CONVERT, Keyname);
|
||
}
|
||
|
||
} while( rc == SCESTATUS_SUCCESS && SetupFindNextLine(&InfLine, &InfLine));
|
||
|
||
}
|
||
|
||
if ( hSection ) {
|
||
|
||
SceJetCloseSection( &hSection, TRUE );
|
||
}
|
||
|
||
SceInfpCloseProfile(hInf);
|
||
|
||
if ( LsaPolicy ) {
|
||
LsaClose(LsaPolicy);
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepCopyPrivilegesFromDatabase(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Keyname,
|
||
IN DWORD StrLength,
|
||
IN PWSTR StrValue OPTIONAL,
|
||
OUT PWSTR *pOldValue,
|
||
OUT DWORD *pOldLen
|
||
)
|
||
{
|
||
|
||
if ( hSection == NULL ||
|
||
Keyname == NULL ||
|
||
pOldValue == NULL ) {
|
||
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
*pOldValue = NULL;
|
||
*pOldLen = 0;
|
||
|
||
SCESTATUS rc;
|
||
DWORD ValueLen;
|
||
|
||
rc = SceJetGetValue(
|
||
hSection,
|
||
SCEJET_EXACT_MATCH_NO_CASE,
|
||
Keyname,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
&ValueLen
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
DWORD Len = wcslen(SCE_PRIV_ADD);
|
||
|
||
*pOldValue = (PWSTR)ScepAlloc(LPTR, (Len+1+StrLength+1)*sizeof(WCHAR)+ValueLen+2);
|
||
|
||
if ( *pOldValue ) {
|
||
|
||
//
|
||
// add the prefix "Add:" first, terminated with a \0 for multi-sz format
|
||
//
|
||
wcscpy(*pOldValue, SCE_PRIV_ADD );
|
||
(*pOldValue)[Len] = L'\0';
|
||
|
||
//
|
||
// query the value from database
|
||
//
|
||
DWORD NewLen=0;
|
||
|
||
rc = SceJetGetValue(
|
||
hSection,
|
||
SCEJET_CURRENT,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
(*pOldValue+Len+1),
|
||
ValueLen,
|
||
&NewLen
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
if ( NewLen > ValueLen ) {
|
||
NewLen = ValueLen;
|
||
}
|
||
|
||
//
|
||
// make sure the length is a multiple of 2
|
||
//
|
||
if ( NewLen % 2 != 0 ) {
|
||
NewLen++;
|
||
}
|
||
|
||
//
|
||
// process the end of the multi-sz string, make sure that it only contains one \0
|
||
//
|
||
|
||
while ( NewLen > 0 &&
|
||
( *(*pOldValue+Len+1+NewLen/2-1) == L'\0') ) {
|
||
if ( NewLen > 1 ) {
|
||
NewLen -= 2;
|
||
} else {
|
||
NewLen = 0;
|
||
}
|
||
}
|
||
|
||
if ( NewLen != 0 ) {
|
||
//
|
||
// include one \0
|
||
//
|
||
NewLen += 2;
|
||
}
|
||
|
||
if ( StrValue ) {
|
||
|
||
memcpy((*pOldValue+Len+1+NewLen/2), StrValue, StrLength*sizeof(WCHAR));
|
||
*pOldLen = Len+1+NewLen/2+StrLength;
|
||
|
||
} else {
|
||
|
||
if ( NewLen == 0 ) {
|
||
//
|
||
// no value in both database and template
|
||
//
|
||
ScepFree(*pOldValue);
|
||
*pOldValue = NULL;
|
||
*pOldLen = 0;
|
||
|
||
} else {
|
||
//
|
||
// only has value in database, terminate the string with two \0
|
||
//
|
||
*pOldLen = Len+1+NewLen/2+1;
|
||
*(*pOldValue+Len+1+NewLen/2) = L'\0';
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepFree(*pOldValue);
|
||
*pOldValue = NULL;
|
||
|
||
//
|
||
// ignore error (if can't query from the db)
|
||
//
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
} else {
|
||
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// ignore error (if there is no match)
|
||
//
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
ScepLogOutput3(1, ScepSceStatusToDosError(rc), IDS_COPY_ONE_PRIVILEGE, Keyname );
|
||
|
||
return rc;
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepDeleteDomainPolicies()
|
||
{
|
||
|
||
SCESTATUS rc;
|
||
PSCESECTION hTmpSect=NULL;
|
||
DOUBLE SectionID=0;
|
||
|
||
rc = SceJetGetSectionIDByName(
|
||
hProfile,
|
||
szSystemAccess,
|
||
&SectionID
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
rc = SceJetOpenSection(hProfile,
|
||
SectionID,
|
||
SCEJET_TABLE_SCP,
|
||
&hTmpSect
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
|
||
|
||
SceJetCloseSection(&hTmpSect, TRUE);
|
||
}
|
||
|
||
rc = SceJetOpenSection(hProfile,
|
||
SectionID,
|
||
SCEJET_TABLE_SMP,
|
||
&hTmpSect
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
|
||
|
||
SceJetCloseSection(&hTmpSect, TRUE);
|
||
}
|
||
}
|
||
|
||
SectionID = 0;
|
||
|
||
rc = SceJetGetSectionIDByName(
|
||
hProfile,
|
||
szKerberosPolicy,
|
||
&SectionID
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
rc = SceJetOpenSection(hProfile,
|
||
SectionID,
|
||
SCEJET_TABLE_SCP,
|
||
&hTmpSect
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
|
||
|
||
SceJetCloseSection(&hTmpSect, TRUE);
|
||
}
|
||
|
||
rc = SceJetOpenSection(hProfile,
|
||
SectionID,
|
||
SCEJET_TABLE_SMP,
|
||
&hTmpSect
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
SceJetDelete(hTmpSect, NULL, FALSE, SCEJET_DELETE_SECTION);
|
||
|
||
SceJetCloseSection(&hTmpSect, TRUE);
|
||
}
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
SCESTATUS
|
||
ScepSetupResetLocalPolicy(
|
||
IN PSCECONTEXT Context,
|
||
IN AREA_INFORMATION Area,
|
||
IN PCWSTR SectionName OPTIONAL,
|
||
IN SCETYPE ProfileType,
|
||
IN BOOL bKeepBasicPolicy
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
This routine deletes policies from the local policy table (SMP)
|
||
|
||
If a section name is provided, the single section is deleted; otherwise,
|
||
The area information is used.
|
||
|
||
If bKeepBasicPolicy is set to TRUE, the following inforamtion WON'T be
|
||
deleted from the table even if that area is requested to delete.
|
||
Password, Lockout, Kerberos, Audit, User Rights, Security Options,
|
||
and SMB settings (any existing service extensions)
|
||
*/
|
||
{
|
||
|
||
if ( Context == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
SCESTATUS rc;
|
||
|
||
if ( SectionName ) {
|
||
|
||
//
|
||
// delete one section
|
||
//
|
||
|
||
rc = ScepDeleteOneSection(
|
||
Context,
|
||
ProfileType,
|
||
SectionName
|
||
);
|
||
|
||
} else {
|
||
|
||
AREA_INFORMATION Area2;
|
||
|
||
if ( bKeepBasicPolicy && ProfileType == SCE_ENGINE_SMP ) {
|
||
Area2 = Area & ~(AREA_SECURITY_POLICY |
|
||
AREA_PRIVILEGES |
|
||
AREA_SYSTEM_SERVICE);
|
||
} else {
|
||
|
||
Area2 = Area;
|
||
}
|
||
|
||
rc = ScepDeleteInfoForAreas(
|
||
Context,
|
||
ProfileType,
|
||
Area2
|
||
);
|
||
|
||
if ( bKeepBasicPolicy &&
|
||
SCESTATUS_SUCCESS == rc ) {
|
||
|
||
//
|
||
// delete log settings sections
|
||
//
|
||
|
||
ScepDeleteOneSection(
|
||
Context,
|
||
ProfileType,
|
||
szAuditSystemLog
|
||
);
|
||
|
||
ScepDeleteOneSection(
|
||
Context,
|
||
ProfileType,
|
||
szAuditSecurityLog
|
||
);
|
||
|
||
ScepDeleteOneSection(
|
||
Context,
|
||
ProfileType,
|
||
szAuditApplicationLog
|
||
);
|
||
|
||
//
|
||
// delete general service section
|
||
//
|
||
|
||
ScepDeleteOneSection(
|
||
Context,
|
||
ProfileType,
|
||
szServiceGeneral
|
||
);
|
||
}
|
||
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepSetSystemSecurity(
|
||
IN AREA_INFORMATION Area,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCE_PROFILE_INFO pInfo,
|
||
OUT PSCE_ERROR_LOG_INFO *pErrLog
|
||
)
|
||
/*
|
||
Description:
|
||
|
||
Set security settings directly on the system for security policy area
|
||
and user rights area.
|
||
|
||
If some settings fail to be configured, the settings will be logged in the
|
||
error buffer to output.
|
||
*/
|
||
{
|
||
SCESTATUS Saverc = SCESTATUS_SUCCESS;
|
||
SCESTATUS rc;
|
||
|
||
if ( pInfo == NULL || Area == 0 ) {
|
||
//
|
||
// nothing to set
|
||
//
|
||
return(Saverc);
|
||
}
|
||
|
||
if ( Area & AREA_PRIVILEGES ) {
|
||
|
||
rc = ScepConfigurePrivilegesByRight( pInfo->OtherInfo.smp.pPrivilegeAssignedTo,
|
||
ConfigOptions,
|
||
pErrLog
|
||
);
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
}
|
||
}
|
||
|
||
|
||
if ( Area & AREA_SECURITY_POLICY ) {
|
||
|
||
if ( pInfo->LockoutBadCount == 0 ) {
|
||
//
|
||
// make sure the other two settings are ignored
|
||
// they might have value SCE_DELETE_VALUE which is not applicable to this mode
|
||
//
|
||
pInfo->ResetLockoutCount = SCE_NO_VALUE;
|
||
pInfo->LockoutDuration = SCE_NO_VALUE;
|
||
}
|
||
|
||
rc = ScepConfigureSystemAccess(pInfo,
|
||
ConfigOptions | SCE_SYSTEM_SETTINGS,
|
||
pErrLog,
|
||
0 );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
}
|
||
|
||
//
|
||
// System Auditing area
|
||
//
|
||
PPOLICY_AUDIT_EVENTS_INFO auditEvent=NULL;
|
||
|
||
rc = ScepSaveAndOffAuditing(&auditEvent, FALSE, NULL);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS && auditEvent ) {
|
||
|
||
rc = ScepConfigureAuditEvent(pInfo,
|
||
auditEvent,
|
||
ConfigOptions | SCE_SYSTEM_SETTINGS,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
ScepSceStatusToDosError(rc),
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_EVENT_AUDITING
|
||
);
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
ScepSceStatusToDosError(rc),
|
||
pErrLog,
|
||
SCEDLL_ERROR_QUERY_EVENT_AUDITING
|
||
);
|
||
|
||
}
|
||
|
||
|
||
if ( auditEvent ) {
|
||
LsaFreeMemory(auditEvent);
|
||
}
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
}
|
||
|
||
//
|
||
// Kerberos Policy
|
||
//
|
||
rc = ScepConfigureKerberosPolicy( NULL, pInfo->pKerberosInfo, ConfigOptions );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
ScepSceStatusToDosError(rc),
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_KERBEROS
|
||
);
|
||
Saverc = rc;
|
||
}
|
||
|
||
//
|
||
// registry values
|
||
//
|
||
rc = ScepConfigureRegistryValues( NULL,
|
||
pInfo->aRegValues,
|
||
pInfo->RegValueCount,
|
||
pErrLog,
|
||
ConfigOptions,
|
||
NULL );
|
||
|
||
if( rc != SCESTATUS_SUCCESS ) {
|
||
Saverc = rc;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
return(Saverc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepConfigurePrivilegesByRight(
|
||
IN PSCE_PRIVILEGE_ASSIGNMENT pPrivAssign,
|
||
IN DWORD Options,
|
||
IN OUT PSCE_ERROR_LOG_INFO *pErrLog
|
||
)
|
||
/*
|
||
Description:
|
||
|
||
Configure privileges by PSCE_PRIVILEGE_ASSIGNMENT structure which is
|
||
separated by each user right with a list of accounts assigned to.
|
||
*/
|
||
{
|
||
|
||
|
||
if ( pPrivAssign == NULL ) {
|
||
//
|
||
// nothing to configure
|
||
//
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
LSA_HANDLE LsaPolicy=NULL;
|
||
DWORD rc;
|
||
|
||
|
||
rc = RtlNtStatusToDosError( ScepOpenLsaPolicy(
|
||
POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT,
|
||
&LsaPolicy,
|
||
FALSE)
|
||
);
|
||
|
||
if (rc != ERROR_SUCCESS) {
|
||
if ( pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_LSA_POLICY
|
||
);
|
||
}
|
||
return(rc);
|
||
}
|
||
|
||
PSCE_PRIVILEGE_ASSIGNMENT pPriv;
|
||
INT PrivValue;
|
||
PSCE_NAME_LIST pList;
|
||
DWORD SaveRc=SCESTATUS_SUCCESS;
|
||
BOOL bBufferUsed;
|
||
PSID pAccountSid;
|
||
|
||
DWORD PrivLowMask=0;
|
||
DWORD PrivHighMask=0;
|
||
|
||
PSCE_PRIVILEGE_VALUE_LIST pPrivList=NULL;
|
||
|
||
//
|
||
// convert the privilege assignment structure to privilege value list
|
||
// and build the mask for privileges (PrivLowMask and PrivHighMask)
|
||
//
|
||
for ( pPriv=pPrivAssign; pPriv != NULL; pPriv=pPriv->Next ) {
|
||
|
||
//
|
||
// privilege name is empty, ignore it.
|
||
//
|
||
if ( pPriv->Name == NULL ) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// search for the privilege value
|
||
//
|
||
|
||
PrivValue = ScepLookupPrivByName(pPriv->Name);
|
||
|
||
if ( PrivValue == -1 ) {
|
||
//
|
||
// unknown privilege
|
||
//
|
||
if ( pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
0,
|
||
pErrLog,
|
||
SCEERR_INVALID_PRIVILEGE,
|
||
pPriv->Name
|
||
);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// build privilege mask
|
||
//
|
||
|
||
if ( PrivValue < 32 ) {
|
||
|
||
PrivLowMask |= (1 << PrivValue);
|
||
} else {
|
||
PrivHighMask |= (1 << (PrivValue-32) );
|
||
}
|
||
|
||
for ( pList=pPriv->AssignedTo; pList != NULL; pList=pList->Next ) {
|
||
//
|
||
// translate each one to a SID
|
||
//
|
||
if ( pList->Name == NULL ) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// reset error code for this new account
|
||
//
|
||
rc = ERROR_SUCCESS;
|
||
pAccountSid = NULL;
|
||
bBufferUsed = FALSE;
|
||
|
||
if ( pList->Name[0] == L'*' ) {
|
||
//
|
||
// this is a string SID
|
||
//
|
||
if ( !ConvertStringSidToSid( pList->Name+1, &pAccountSid) ) {
|
||
rc = GetLastError();
|
||
}
|
||
|
||
} else {
|
||
//
|
||
// this is a name, could be in the format of domain\account, or
|
||
// just an isolated account
|
||
//
|
||
rc = RtlNtStatusToDosError(
|
||
ScepConvertNameToSid(
|
||
LsaPolicy,
|
||
pList->Name,
|
||
&pAccountSid
|
||
));
|
||
}
|
||
|
||
if ( rc == ERROR_SUCCESS ) {
|
||
|
||
//
|
||
// add the account SID to privilege value list
|
||
//
|
||
rc = ScepDosErrorToSceStatus(
|
||
ScepAddSidToPrivilegeList(
|
||
&pPrivList,
|
||
pAccountSid,
|
||
TRUE, // reuse the buffer
|
||
PrivValue,
|
||
&bBufferUsed
|
||
));
|
||
|
||
}
|
||
|
||
if ( rc != ERROR_SUCCESS ) {
|
||
//
|
||
// something is wrong with this account. Can't be resolved
|
||
// add it to the error log and continue to process others.
|
||
//
|
||
if ( pErrLog ) {
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_INVALID_GROUP,
|
||
pList->Name
|
||
);
|
||
}
|
||
|
||
SaveRc = ScepDosErrorToSceStatus(rc);
|
||
}
|
||
|
||
if ( !bBufferUsed && pAccountSid ) {
|
||
ScepFree(pAccountSid);
|
||
}
|
||
pAccountSid = NULL;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// free LSA handle
|
||
//
|
||
LsaClose(LsaPolicy);
|
||
|
||
//
|
||
// now continue to configure even though there may be errors in
|
||
// the previous processing (the erorrs are logged)
|
||
//
|
||
if ( PrivLowMask > 0 || PrivHighMask > 0 ) {
|
||
|
||
rc = ScepConfigurePrivilegesWithMask(
|
||
&pPrivList,
|
||
FALSE,
|
||
Options | SCE_SYSTEM_SETTINGS,
|
||
PrivLowMask,
|
||
PrivHighMask,
|
||
pErrLog,
|
||
NULL
|
||
);
|
||
}
|
||
|
||
//
|
||
// free privilege list
|
||
//
|
||
|
||
|
||
return(SaveRc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepEnumAttachmentSections(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT PSCE_NAME_LIST *ppList
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
ppList - The output attachment section names
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
WCHAR Buffer[256];
|
||
DWORD Len;
|
||
|
||
if ( cxtProfile == NULL || ppList == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( cxtProfile->JetTblSecID <= 0) {
|
||
//
|
||
// Section table is not opened yet
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
}
|
||
|
||
*ppList = NULL;
|
||
|
||
//
|
||
// set current index to SecID (the ID)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
"SecID"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// Move to the first record
|
||
//
|
||
JetErr = JetMove(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_MoveFirst,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
//
|
||
// find the section record, retrieve column Name
|
||
//
|
||
do {
|
||
|
||
Len = 255;
|
||
memset(Buffer, '\0', 256*sizeof(WCHAR));
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecNameID,
|
||
(void *)Buffer,
|
||
Len*sizeof(WCHAR),
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// add this name to the output list
|
||
//
|
||
if ( _wcsicmp(szSystemAccess, Buffer) == 0 ||
|
||
_wcsicmp(szPrivilegeRights, Buffer) == 0 ||
|
||
_wcsicmp(szGroupMembership, Buffer) == 0 ||
|
||
_wcsicmp(szRegistryKeys, Buffer) == 0 ||
|
||
_wcsicmp(szFileSecurity, Buffer) == 0 ||
|
||
_wcsicmp(szAuditSystemLog, Buffer) == 0 ||
|
||
_wcsicmp(szAuditSecurityLog, Buffer) == 0 ||
|
||
_wcsicmp(szAuditApplicationLog, Buffer) == 0 ||
|
||
_wcsicmp(szAuditEvent, Buffer) == 0 ||
|
||
_wcsicmp(szKerberosPolicy, Buffer) == 0 ||
|
||
_wcsicmp(szRegistryValues, Buffer) == 0 ||
|
||
_wcsicmp(szServiceGeneral, Buffer) == 0 ||
|
||
_wcsicmp(szAccountProfiles, Buffer) == 0 ||
|
||
_wcsicmp(szDSSecurity, Buffer) == 0 ||
|
||
_wcsicmp(szUserList, Buffer) == 0
|
||
) {
|
||
// this is not the attachment section
|
||
} else {
|
||
rc = ScepAddToNameList(ppList, Buffer, 0);
|
||
}
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
//
|
||
// Move to next line
|
||
//
|
||
JetErr = JetMove(cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_MoveNext,
|
||
0);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
} while ( SCESTATUS_SUCCESS == rc );
|
||
}
|
||
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
||
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
} else if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// free the output buffer
|
||
//
|
||
ScepFreeNameList(*ppList);
|
||
*ppList = NULL;
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
ScepTattooUpdatePrivilegeArrayStatus(
|
||
IN DWORD *pStatusArray,
|
||
IN DWORD rc,
|
||
IN DWORD PrivLowMask,
|
||
IN DWORD PrivHighMask
|
||
)
|
||
{
|
||
if ( pStatusArray == NULL ||
|
||
(PrivLowMask == 0 && PrivHighMask == 0) ) {
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
for ( DWORD i=0; i<cPrivCnt; i++) {
|
||
|
||
if ( ( (i < 32) && ( PrivLowMask & (1 << i)) ) ||
|
||
( (i >= 32) && ( PrivHighMask & ( 1 << (i-32)) ) ) ) {
|
||
if ( rc != 0 )
|
||
pStatusArray[i] = rc;
|
||
else if ( pStatusArray[i] == (DWORD)-1 )
|
||
pStatusArray[i] = rc;
|
||
|
||
}
|
||
}
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
SCESTATUS
|
||
ScepTattooRemovePrivilegeValues(
|
||
IN PSCECONTEXT hProfile,
|
||
IN DWORD *pStatusArray
|
||
)
|
||
{
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
DWORD i,Len;
|
||
|
||
|
||
if ( hProfile == NULL || pStatusArray == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
//
|
||
// open domain and tattoo sections
|
||
//
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szPrivilegeRights,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
|
||
if ( hSectionDomain != NULL && hSectionTattoo != NULL ) {
|
||
|
||
for ( i=0; i<cPrivCnt; i++ ) {
|
||
|
||
if ( pStatusArray[i] == 0 ) {
|
||
|
||
//
|
||
// check if this setting comes from domain
|
||
//
|
||
|
||
Len = wcslen(SCE_Privileges[i].Name);
|
||
|
||
BOOL bDomainExist = FALSE;
|
||
|
||
if ( SCESTATUS_SUCCESS == SceJetSeek(
|
||
hSectionDomain,
|
||
SCE_Privileges[i].Name,
|
||
Len*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
) ) {
|
||
|
||
if ( hSectionDomain->JetColumnGpoID > 0 ) {
|
||
|
||
//
|
||
// check if GpoID > 0
|
||
//
|
||
|
||
LONG GpoID = 0;
|
||
DWORD Actual;
|
||
JET_ERR JetErr;
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
hSectionDomain->JetSessionID,
|
||
hSectionDomain->JetTableID,
|
||
hSectionDomain->JetColumnGpoID,
|
||
(void *)&GpoID,
|
||
4,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
if ( JET_errSuccess != JetErr ) {
|
||
//
|
||
// if the column is nil (no value), it will return warning
|
||
// but the buffer pGpoID is trashed
|
||
//
|
||
GpoID = 0;
|
||
}
|
||
|
||
if ( GpoID > 0 ) {
|
||
bDomainExist = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( bDomainExist ) {
|
||
// if the setting comes from domain, don't do anything
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// by now, this setting comes from the tattoo table
|
||
// and has been configured successfully
|
||
// now remove the tattoo setting
|
||
//
|
||
|
||
SceJetDelete(hSectionTattoo,
|
||
SCE_Privileges[i].Name,
|
||
FALSE,
|
||
SCEJET_DELETE_LINE_NO_CASE);
|
||
|
||
ScepLogOutput3(2, 0, SCESRV_POLICY_TATTOO_REMOVE_SETTING, SCE_Privileges[i].Name);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain, TRUE);
|
||
if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo, TRUE);
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
SCESTATUS
|
||
ScepTattooSavePrivilegeValues(
|
||
IN PSCECONTEXT hProfile,
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN DWORD PrivLowMask,
|
||
IN DWORD PrivHighMask,
|
||
IN DWORD ConfigOptions
|
||
)
|
||
{
|
||
PSCESECTION hSectionDomain=NULL;
|
||
PSCESECTION hSectionTattoo=NULL;
|
||
|
||
NTSTATUS NtStatus;
|
||
ULONG CountReturned;
|
||
UNICODE_STRING UserRight;
|
||
PLSA_ENUMERATION_INFORMATION EnumBuffer=NULL;
|
||
|
||
DWORD i,j,Len;
|
||
BOOL bSettingExist;
|
||
DWORD rc,rc2;
|
||
SCESTATUS saveRc=SCESTATUS_SUCCESS;
|
||
PSCE_NAME_LIST pNameList=NULL;
|
||
|
||
|
||
if ( !(ConfigOptions & SCE_POLICY_TEMPLATE) || hProfile == NULL ||
|
||
PolicyHandle == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( PrivLowMask == 0 && PrivHighMask == 0 ) {
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// open domain and tattoo sections
|
||
//
|
||
ScepTattooOpenPolicySections(
|
||
hProfile,
|
||
szPrivilegeRights,
|
||
&hSectionDomain,
|
||
&hSectionTattoo
|
||
);
|
||
|
||
if ( hSectionDomain != NULL && hSectionTattoo != NULL ) {
|
||
|
||
for ( i=0; i<cPrivCnt; i++ ) {
|
||
|
||
if ( ( (i < 32) && ( PrivLowMask & (1 << i)) ) ||
|
||
( (i >= 32) && ( PrivHighMask & ( 1 << (i-32)) ) ) ) {
|
||
|
||
//
|
||
// check if this setting comes from domain
|
||
//
|
||
|
||
Len = wcslen(SCE_Privileges[i].Name);
|
||
|
||
bSettingExist = FALSE;
|
||
if ( SCESTATUS_SUCCESS == SceJetSeek(
|
||
hSectionTattoo,
|
||
SCE_Privileges[i].Name,
|
||
Len*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
) ) {
|
||
bSettingExist = TRUE;
|
||
}
|
||
|
||
// if there is tattoo setting already, no need to save undo value
|
||
if ( bSettingExist ) {
|
||
ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_EXIST, SCE_Privileges[i].Name);
|
||
continue;
|
||
}
|
||
|
||
bSettingExist = FALSE;
|
||
if ( SCESTATUS_SUCCESS == SceJetSeek(
|
||
hSectionDomain,
|
||
SCE_Privileges[i].Name,
|
||
Len*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
) ) {
|
||
//
|
||
// since there is no tattoo value exist
|
||
// so if this setting is found in domain table, it must come from domain
|
||
//
|
||
bSettingExist = TRUE;
|
||
}
|
||
|
||
// if the setting doesn't come from domain, no need to query undo value
|
||
if ( !bSettingExist ) continue;
|
||
|
||
//
|
||
// now we need to query the tattoo value for this privilege
|
||
//
|
||
RtlInitUnicodeString( &UserRight, (PCWSTR)(SCE_Privileges[i].Name));
|
||
|
||
//
|
||
// now enumerate all accounts for this user right.
|
||
//
|
||
|
||
NtStatus = LsaEnumerateAccountsWithUserRight(
|
||
PolicyHandle,
|
||
&UserRight,
|
||
(PVOID *)&EnumBuffer, // account SIDs
|
||
&CountReturned
|
||
);
|
||
|
||
if ( NtStatus == STATUS_NO_MORE_ENTRIES ||
|
||
NtStatus == STATUS_NO_SUCH_PRIVILEGE ||
|
||
NtStatus == STATUS_NOT_FOUND ||
|
||
NT_SUCCESS(NtStatus) ) {
|
||
|
||
rc = ERROR_SUCCESS;
|
||
|
||
} else {
|
||
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
}
|
||
|
||
pNameList = NULL;
|
||
|
||
//
|
||
// if fail to get the account list
|
||
// save NULL as the tattoo value
|
||
//
|
||
if ( NT_SUCCESS(NtStatus) && CountReturned > 0 ) {
|
||
|
||
//
|
||
// add the SIDs
|
||
//
|
||
|
||
for ( j=0; j<CountReturned; j++ ) {
|
||
//
|
||
// build each account into the name list
|
||
// Convert using the Rtl functions
|
||
//
|
||
rc2 = ScepAddSidStringToNameList(&pNameList, EnumBuffer[j].Sid);
|
||
|
||
if ( NO_ERROR != rc2 ) {
|
||
rc = rc2;
|
||
}
|
||
}
|
||
}
|
||
|
||
LsaFreeMemory( EnumBuffer );
|
||
EnumBuffer = NULL;
|
||
|
||
//
|
||
// log an error
|
||
//
|
||
if ( ERROR_SUCCESS != rc ) {
|
||
|
||
saveRc = ScepDosErrorToSceStatus(rc);
|
||
ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_QUERY, rc, SCE_Privileges[i].Name);
|
||
|
||
} else {
|
||
//
|
||
// now save the name list to the tattoo table
|
||
//
|
||
|
||
rc = ScepWriteNameListValue(
|
||
PolicyHandle,
|
||
hSectionTattoo,
|
||
SCE_Privileges[i].Name,
|
||
pNameList,
|
||
SCE_WRITE_EMPTY_LIST,
|
||
4
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
saveRc = rc;
|
||
ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_SETTING, ScepSceStatusToDosError(rc), SCE_Privileges[i].Name);
|
||
} else {
|
||
ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_CHECK, SCE_Privileges[i].Name);
|
||
}
|
||
}
|
||
|
||
if ( pNameList != NULL ) {
|
||
ScepFreeNameList( pNameList );
|
||
pNameList = NULL;
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( hSectionDomain ) SceJetCloseSection(&hSectionDomain, TRUE);
|
||
if ( hSectionTattoo ) SceJetCloseSection(&hSectionTattoo, TRUE);
|
||
|
||
return(saveRc);
|
||
}
|
||
|
||
|
||
DWORD
|
||
ScepTattooCurrentGroupMembers(
|
||
IN PSID ThisDomainSid,
|
||
IN SID_NAME_USE GrpUse,
|
||
IN PULONG MemberRids OPTIONAL,
|
||
IN PSID *MemberAliasSids OPTIONAL,
|
||
IN DWORD MemberCount,
|
||
OUT PSCE_NAME_LIST *ppNameList
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine builds the current group membership into a name list (in SID string
|
||
format).
|
||
|
||
Arguments:
|
||
|
||
ThisDomainSid - The domain SID
|
||
|
||
GrpUse - The "type" of the group
|
||
|
||
MemberRids - the member RIDs (for SidTypeGroup)
|
||
|
||
MemberAliasSids - the member SIDs (for SidTypeAlias)
|
||
|
||
MemberCount - number of members
|
||
|
||
ppNameList - the output name list
|
||
|
||
Return value:
|
||
|
||
WIN32 errors
|
||
-- */
|
||
{
|
||
NTSTATUS NtStatus=ERROR_SUCCESS;
|
||
DWORD j;
|
||
DWORD saveRc=ERROR_SUCCESS;
|
||
DWORD rc;
|
||
|
||
if ( ppNameList == NULL ) {
|
||
return(ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
*ppNameList = NULL;
|
||
|
||
switch ( GrpUse ) {
|
||
case SidTypeGroup:
|
||
//
|
||
// member IDs are passed in as Rids
|
||
// DomainHandle must point to a account domain because builtin domain
|
||
// won't have SidTypeGroup account
|
||
//
|
||
if ( ThisDomainSid == NULL )
|
||
saveRc = ERROR_INVALID_PARAMETER;
|
||
|
||
else if ( MemberRids ) {
|
||
|
||
PSID AccountSid=NULL;
|
||
|
||
for (j=0; j<MemberCount; j++) {
|
||
|
||
NtStatus = ScepDomainIdToSid(
|
||
ThisDomainSid,
|
||
MemberRids[j],
|
||
&AccountSid
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
if ( NT_SUCCESS(NtStatus) ) {
|
||
|
||
rc = ScepAddSidStringToNameList(ppNameList, AccountSid);
|
||
|
||
ScepFree(AccountSid);
|
||
AccountSid = NULL;
|
||
}
|
||
|
||
if ( ERROR_SUCCESS != rc ) saveRc = rc;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case SidTypeAlias:
|
||
//
|
||
// members are passed in as SIDs
|
||
// add them to the output list directly
|
||
//
|
||
if ( MemberAliasSids ) {
|
||
|
||
for ( j=0; j<MemberCount; j++ ) {
|
||
if ( MemberAliasSids[j] != NULL ) {
|
||
//
|
||
// add member to the list
|
||
//
|
||
rc = ScepAddSidStringToNameList(ppNameList, MemberAliasSids[j]);
|
||
|
||
if ( ERROR_SUCCESS != rc ) saveRc = rc;
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
saveRc = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
}
|
||
|
||
|
||
return(saveRc);
|
||
}
|
||
|
||
SCESTATUS
|
||
ScepCheckNetworkLogonRights(
|
||
IN LSA_HANDLE PolicyHandle,
|
||
IN OUT DWORD *pLowMask,
|
||
IN OUT DWORD *pHighMask,
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned
|
||
)
|
||
/*
|
||
Description:
|
||
|
||
This function is to make sure that Authenticated Users already have
|
||
"Network Logon Right" and Authenticated Users & Everyone must not
|
||
have "Deny network logon right".
|
||
|
||
If the network logon right or deny network logon right are not defined
|
||
in the privilege mask, no change is made since the user rights are not
|
||
defined in the configuration.
|
||
|
||
If Authenticated Users or Everyone is not defined in the privilege list,
|
||
this function will add them in (hard coded). The output of this function
|
||
ppPrivilegeAssigned may contain new added nodes for the hard coded accounts.
|
||
|
||
*/
|
||
{
|
||
INT i;
|
||
INT idxAllow = -1;
|
||
INT idxDeny = -1;
|
||
INT idxLocal = -1;
|
||
INT idxDenyLocal = -1;
|
||
|
||
DWORD PrivHighMask = *pHighMask;
|
||
DWORD PrivLowMask = *pLowMask;
|
||
|
||
//
|
||
// check first if Network logon right is defined
|
||
//
|
||
i = ScepLookupPrivByName(SE_NETWORK_LOGON_NAME);
|
||
if ( i != -1 ) {
|
||
if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
|
||
//
|
||
// network logon right is defined
|
||
//
|
||
idxAllow = i;
|
||
}
|
||
}
|
||
|
||
//
|
||
// check if Deny Network logon right is defined
|
||
//
|
||
|
||
i = ScepLookupPrivByName(SE_DENY_NETWORK_LOGON_NAME);
|
||
if ( i != -1 ) {
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
|
||
//
|
||
// deny network logon right is defined
|
||
//
|
||
idxDeny = i;
|
||
|
||
}
|
||
}
|
||
|
||
//
|
||
// check if logon locally right is defined
|
||
//
|
||
|
||
i = ScepLookupPrivByName(SE_INTERACTIVE_LOGON_NAME);
|
||
if ( i != -1 ) {
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
|
||
//
|
||
// logon locally right is defined
|
||
//
|
||
idxLocal = i;
|
||
}
|
||
}
|
||
|
||
//
|
||
// check if deny logon locally right is defined
|
||
//
|
||
|
||
i = ScepLookupPrivByName(SE_DENY_INTERACTIVE_LOGON_NAME);
|
||
if ( i != -1 ) {
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(i,PrivLowMask,PrivHighMask) ) {
|
||
//
|
||
// deny logon locally right is defined
|
||
//
|
||
idxDenyLocal = i;
|
||
}
|
||
}
|
||
|
||
if ( idxAllow == -1 && idxDeny == -1 && idxLocal == -1 && idxDenyLocal == -1 ) {
|
||
|
||
//
|
||
// none of them is defined so do not enforce anything
|
||
//
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// build well known SIDs for the enforcement
|
||
//
|
||
|
||
SID EveryoneSid;
|
||
SID AuthSid;
|
||
SID ControllerSid;
|
||
PSID AdminUserSid=NULL;
|
||
|
||
SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
|
||
SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
|
||
|
||
|
||
//
|
||
// initialize Administrators group sid
|
||
//
|
||
|
||
if ( ! NT_SUCCESS ( RtlAllocateAndInitializeSid( &NtAuth,
|
||
2,
|
||
SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS,
|
||
0,0,0,0,0,0,
|
||
&AdminsSid
|
||
) ) ) {
|
||
ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY,
|
||
SCEDLL_ADMINISTRATORS_SID);
|
||
|
||
//
|
||
// failure to initialize this one SID will still continue to other SIDs
|
||
//
|
||
}
|
||
|
||
//
|
||
// initialize administrator SID
|
||
//
|
||
|
||
if ( idxDenyLocal != -1 ) {
|
||
|
||
NTSTATUS Status;
|
||
|
||
//
|
||
// Query the account domain SID
|
||
// failure to initialize this one SID will still continue to
|
||
// enforce other SIDs
|
||
//
|
||
|
||
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
|
||
|
||
Status = LsaQueryInformationPolicy( PolicyHandle,
|
||
PolicyAccountDomainInformation,
|
||
(PVOID *)&PolicyAccountDomainInfo );
|
||
|
||
|
||
if ( NT_SUCCESS(Status) && PolicyAccountDomainInfo &&
|
||
PolicyAccountDomainInfo->DomainSid ) {
|
||
|
||
Status = ScepDomainIdToSid(
|
||
PolicyAccountDomainInfo->DomainSid,
|
||
DOMAIN_USER_RID_ADMIN,
|
||
&AdminUserSid
|
||
);
|
||
|
||
}
|
||
|
||
if ( PolicyAccountDomainInfo ) {
|
||
LsaFreeMemory( PolicyAccountDomainInfo );
|
||
}
|
||
|
||
if ( AdminUserSid == NULL ) {
|
||
|
||
ScepLogOutput3(0, RtlNtStatusToDosError(Status),
|
||
SCEDLL_ADMINISTRATORS_SID);
|
||
}
|
||
}
|
||
|
||
//
|
||
// initialize well known SIDs
|
||
//
|
||
|
||
RtlInitializeSid ( &EveryoneSid, &WorldAuth, 1);
|
||
*RtlSubAuthoritySid ( &EveryoneSid, 0 ) = SECURITY_WORLD_RID;
|
||
|
||
RtlInitializeSid ( &AuthSid, &NtAuth, 1);
|
||
*RtlSubAuthoritySid ( &AuthSid, 0 ) = SECURITY_AUTHENTICATED_USER_RID;
|
||
|
||
RtlInitializeSid ( &ControllerSid, &NtAuth, 1);
|
||
*RtlSubAuthoritySid ( &ControllerSid, 0 ) = SECURITY_ENTERPRISE_CONTROLLERS_RID;
|
||
|
||
|
||
PSCE_PRIVILEGE_VALUE_LIST pTemp=*ppPrivilegeAssigned;
|
||
PSCE_PRIVILEGE_VALUE_LIST pParent=NULL;
|
||
|
||
BOOL bFindEveryone=FALSE;
|
||
BOOL bFindAuthUsers=FALSE;
|
||
BOOL bFindLocal=FALSE;
|
||
BOOL bFindController=FALSE;
|
||
BOOL bFindAdminUser=FALSE;
|
||
|
||
//
|
||
// loop through each one defined in the list to match the above SIDs
|
||
//
|
||
|
||
for ( ; pTemp != NULL; pParent=pTemp, pTemp=pTemp->Next) {
|
||
|
||
if ( pTemp->Name == NULL ) continue;
|
||
|
||
if ( (idxLocal != -1 || idxDenyLocal != -1) && !bFindLocal && AdminsSid &&
|
||
( bFindLocal = RtlEqualSid( (PSID)(pTemp->Name), AdminsSid) ) ) {
|
||
|
||
//
|
||
// make sure Administrators always have the interactive logon right
|
||
//
|
||
if ( idxLocal != -1 ) {
|
||
|
||
if ( !SCEP_CHECK_PRIV_BIT(idxLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
|
||
SCEP_ADD_PRIV_BIT(idxLocal, pTemp->PrivLowPart, pTemp->PrivHighPart)
|
||
}
|
||
}
|
||
|
||
//
|
||
// make sure administrators don't have deny interactive logon right
|
||
//
|
||
if ( idxDenyLocal != -1 ) {
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
|
||
SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( (idxDeny != -1 || idxDenyLocal != -1) &&
|
||
( !bFindAuthUsers && ( bFindAuthUsers = RtlEqualSid( (PSID)(pTemp->Name), &AuthSid )) ) ||
|
||
( !bFindEveryone && ( bFindEveryone = RtlEqualSid( (PSID)(pTemp->Name), &EveryoneSid )) ) ) {
|
||
|
||
//
|
||
// find Authenticated Users or Everyone
|
||
// make sure they do not have the deny rights
|
||
//
|
||
|
||
if ( idxDenyLocal != -1 ) {
|
||
|
||
//
|
||
// remove the deny logon locally bit
|
||
//
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
|
||
SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
|
||
}
|
||
}
|
||
|
||
if ( (idxDeny != -1) && (ProductType == NtProductLanManNt) ) {
|
||
|
||
//
|
||
// remove the deny network logon bit on domain controllers
|
||
//
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(idxDeny,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_NETWORK_RIGHT, SE_DENY_NETWORK_LOGON_NAME);
|
||
SCEP_REMOVE_PRIV_BIT(idxDeny, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
|
||
}
|
||
}
|
||
|
||
} else if ( !bFindController && (ProductType == NtProductLanManNt) &&
|
||
( bFindController = RtlEqualSid( (PSID)(pTemp->Name), &ControllerSid )) ) {
|
||
|
||
//
|
||
// find domain controller SID
|
||
// make sure it have network logon right and must not have deny network logon right
|
||
//
|
||
|
||
if ( idxDeny != -1 ) {
|
||
|
||
//
|
||
// remove the deny network logon bit
|
||
//
|
||
if ( SCEP_CHECK_PRIV_BIT(idxDeny,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_NETWORK_RIGHT, SE_DENY_NETWORK_LOGON_NAME);
|
||
SCEP_REMOVE_PRIV_BIT(idxDeny, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
|
||
}
|
||
}
|
||
|
||
if ( idxAllow != -1 ) {
|
||
|
||
//
|
||
// add the network logon bit
|
||
//
|
||
if ( !SCEP_CHECK_PRIV_BIT(idxAllow,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
|
||
SCEP_ADD_PRIV_BIT(idxAllow, pTemp->PrivLowPart, pTemp->PrivHighPart)
|
||
}
|
||
}
|
||
|
||
} else if ( idxDenyLocal != -1 && !bFindAdminUser && AdminUserSid &&
|
||
( bFindAdminUser = RtlEqualSid( (PSID)(pTemp->Name), AdminUserSid) ) ) {
|
||
|
||
//
|
||
// make sure administrator account don't have the deny right
|
||
//
|
||
|
||
if ( SCEP_CHECK_PRIV_BIT(idxDenyLocal,pTemp->PrivLowPart,pTemp->PrivHighPart) ) {
|
||
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_DENY_LOCAL_RIGHT, SE_DENY_INTERACTIVE_LOGON_NAME);
|
||
SCEP_REMOVE_PRIV_BIT(idxDenyLocal, &(pTemp->PrivLowPart), &(pTemp->PrivHighPart))
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// all enforcement is done, break the loop now
|
||
//
|
||
|
||
if ( (idxLocal == -1 || bFindLocal) &&
|
||
( (idxDeny == -1 && idxDenyLocal == -1) || (bFindAuthUsers && bFindEveryone) ) &&
|
||
( bFindController || (ProductType != NtProductLanManNt) ) &&
|
||
(idxDenyLocal == -1 || bFindAdminUser) ) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
|
||
if ( idxLocal != -1 && !bFindLocal && AdminsSid ) {
|
||
|
||
//
|
||
// make sure administrators have "logon locally right"
|
||
// add a new node the the end of the list
|
||
//
|
||
|
||
rc = ScepAddAccountRightToList(
|
||
ppPrivilegeAssigned,
|
||
&pParent,
|
||
idxLocal,
|
||
AdminsSid
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
|
||
} else {
|
||
ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY, SCESRV_ERROR_ENFORCE_LOCAL_RIGHT, SE_INTERACTIVE_LOGON_NAME);
|
||
}
|
||
}
|
||
|
||
//
|
||
// if enterprise controllers is not found in the list
|
||
// and it's on a DC, should add it
|
||
//
|
||
|
||
rc=SCESTATUS_SUCCESS;
|
||
|
||
if ( idxAllow != -1 && !bFindController &&
|
||
( ProductType == NtProductLanManNt ) ) {
|
||
|
||
//
|
||
// make sure enterprise controllers have "network logon right"
|
||
//
|
||
|
||
rc = ScepAddAccountRightToList(
|
||
ppPrivilegeAssigned,
|
||
&pParent,
|
||
idxAllow,
|
||
&ControllerSid
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
ScepLogOutput3(0,0, SCESRV_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
|
||
} else {
|
||
ScepLogOutput3(0,ERROR_NOT_ENOUGH_MEMORY, SCESRV_ERROR_ENFORCE_NETWORK_RIGHT, SE_NETWORK_LOGON_NAME);
|
||
}
|
||
}
|
||
|
||
//
|
||
// free memory
|
||
//
|
||
|
||
if ( AdminsSid ) {
|
||
RtlFreeSid( AdminsSid );
|
||
AdminsSid = NULL;
|
||
}
|
||
|
||
if ( AdminUserSid ) {
|
||
RtlFreeSid( AdminUserSid );
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
SCESTATUS
|
||
ScepAddAccountRightToList(
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppPrivilegeAssigned,
|
||
IN OUT PSCE_PRIVILEGE_VALUE_LIST *ppParent,
|
||
IN INT idxRight,
|
||
IN PSID AccountSid
|
||
)
|
||
/*
|
||
Description:
|
||
|
||
Create a new node linked to the end of the link list
|
||
|
||
The new node contains the AccountSid for the specified user right "idxRight"
|
||
|
||
*/
|
||
{
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
|
||
PSCE_PRIVILEGE_VALUE_LIST pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
|
||
sizeof(SCE_PRIVILEGE_VALUE_LIST));
|
||
if ( pPriv != NULL ) {
|
||
|
||
DWORD Length = RtlLengthSid ( AccountSid );
|
||
|
||
//
|
||
// allocate the sid buffer, note it's stored in the name field
|
||
//
|
||
|
||
pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
|
||
|
||
if ( pPriv->Name != NULL ) {
|
||
|
||
//
|
||
// copy the SID in
|
||
//
|
||
|
||
RtlCopySid( Length, (PSID)(pPriv->Name), AccountSid );
|
||
|
||
//
|
||
// add the interactive logon right bit
|
||
//
|
||
|
||
SCEP_ADD_PRIV_BIT(idxRight, pPriv->PrivLowPart, pPriv->PrivHighPart)
|
||
|
||
//
|
||
// link to the list
|
||
//
|
||
|
||
if ( *ppParent != NULL )
|
||
(*ppParent)->Next = pPriv;
|
||
else
|
||
*ppPrivilegeAssigned = pPriv;
|
||
|
||
*ppParent = pPriv;
|
||
|
||
} else {
|
||
|
||
ScepFree(pPriv);
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
}
|
||
|
||
} else {
|
||
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
DWORD
|
||
ScepAddAceToSecurityDescriptor(
|
||
IN DWORD AceType,
|
||
IN ACCESS_MASK AccessMask,
|
||
IN PSID pSid,
|
||
IN OUT PSECURITY_DESCRIPTOR pSDAbsolute,
|
||
IN PSECURITY_DESCRIPTOR pSDSelfRelative,
|
||
OUT PACL *ppNewAcl
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
This routine adds an ACE to a Security Descriptor (at the head only).
|
||
|
||
Two optimizations are attempted in adding the ACE.
|
||
|
||
Arguments:
|
||
|
||
AceType - type of ACE to add
|
||
|
||
AccessMask - access mask of ACE to set
|
||
|
||
pSid - sid for ACE to add
|
||
|
||
pSDAbsolute - absolute SD ptr to build. pSDAbsolute must be empty.
|
||
It's vacuous in the caller's stack hence no SD member
|
||
should be freed outside this routine.
|
||
|
||
pSDSelfRelative - self relative SD to get DACL information from
|
||
|
||
ppNewAcl - ptr to the new DACL which needs to be freed outside
|
||
|
||
Return Value:
|
||
|
||
Win32 error code
|
||
*/
|
||
{
|
||
|
||
DWORD rc = ERROR_SUCCESS;
|
||
BOOL bOrMaskInOldDacl = FALSE;
|
||
|
||
if (ppNewAcl == NULL ||
|
||
pSDAbsolute == NULL ||
|
||
pSDSelfRelative == NULL ||
|
||
(AceType != ACCESS_ALLOWED_ACE_TYPE && AceType != ACCESS_DENIED_ACE_TYPE )
|
||
) {
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
PACL pNewAcl = *ppNewAcl = NULL;
|
||
NTSTATUS NtStatus = STATUS_SUCCESS;
|
||
BOOLEAN bAclPresent = FALSE;
|
||
PACL pOldAcl = NULL;
|
||
BOOLEAN bDaclDefaulted = FALSE;
|
||
DWORD dwNewAclSize = 0;
|
||
DWORD dwAceSize = 0;
|
||
ACE_HEADER *pFirstAce = NULL;
|
||
DWORD dwFirstAceSize = 0;
|
||
|
||
NtStatus = RtlGetDaclSecurityDescriptor(
|
||
pSDSelfRelative,
|
||
&bAclPresent,
|
||
&pOldAcl,
|
||
&bDaclDefaulted);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( rc != ERROR_SUCCESS )
|
||
goto Cleanup;
|
||
|
||
//
|
||
// null DACL should never happen - CliffV
|
||
// we shouldn't set the DACL with the one
|
||
// anonymous ACE only since it will deny
|
||
// all other SID's any access
|
||
//
|
||
|
||
if ( !bAclPresent ||
|
||
pOldAcl == NULL ||
|
||
pOldAcl->AceCount == 0 ) {
|
||
|
||
rc = ERROR_INVALID_ACL;
|
||
goto Cleanup;
|
||
|
||
}
|
||
|
||
NtStatus = RtlGetAce( pOldAcl,
|
||
0,
|
||
(PVOID *) &pFirstAce);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( rc != ERROR_SUCCESS )
|
||
goto Cleanup;
|
||
|
||
//
|
||
// if the first ACE is for the SID passed in attempt two optimizations
|
||
//
|
||
|
||
if ( RtlValidSid((PSID)&((PKNOWN_ACE)pFirstAce)->SidStart) &&
|
||
RtlEqualSid((PSID)&((PKNOWN_ACE)pFirstAce)->SidStart, pSid)) {
|
||
|
||
if (pFirstAce->AceType == AceType) {
|
||
|
||
//
|
||
// Optimization 1:
|
||
// simply OR in the mask
|
||
//
|
||
|
||
((PKNOWN_ACE)pFirstAce)->Mask |= AccessMask;
|
||
|
||
bOrMaskInOldDacl = TRUE;
|
||
|
||
goto SetDacl;
|
||
}
|
||
|
||
else if (((PKNOWN_ACE)pFirstAce)->Mask == AccessMask ) {
|
||
|
||
//
|
||
// Optimization 2:
|
||
// if only AccessMask is turned on, later on
|
||
// (a) prepare a new ACE
|
||
// (b) copy the old ACL except the first ACE
|
||
//
|
||
|
||
//
|
||
// remember the size of the first ACE since we need to skip it
|
||
//
|
||
|
||
dwFirstAceSize = (DWORD)(((PKNOWN_ACE)pFirstAce)->Header.AceSize);
|
||
}
|
||
}
|
||
|
||
|
||
switch (AceType) {
|
||
case ACCESS_ALLOWED_ACE_TYPE:
|
||
dwAceSize = sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(pSid) - sizeof(ULONG);
|
||
break;
|
||
case ACCESS_DENIED_ACE_TYPE:
|
||
dwAceSize = sizeof(ACCESS_DENIED_ACE) + RtlLengthSid(pSid) - sizeof(ULONG);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
dwNewAclSize = dwAceSize + pOldAcl->AclSize - dwFirstAceSize;
|
||
|
||
*ppNewAcl = pNewAcl = (PACL) LocalAlloc(LMEM_ZEROINIT, dwNewAclSize);
|
||
|
||
if ( pNewAcl == NULL ) {
|
||
rc = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// initialize the ACL
|
||
//
|
||
|
||
pNewAcl->AclSize = (USHORT) dwNewAclSize;
|
||
pNewAcl->AclRevision = ACL_REVISION;
|
||
pNewAcl->AceCount = 0;
|
||
|
||
//
|
||
// add allow/deny ACE to the head of the ACL
|
||
//
|
||
|
||
switch (AceType) {
|
||
case ACCESS_ALLOWED_ACE_TYPE:
|
||
|
||
if ( ! AddAccessAllowedAce(
|
||
pNewAcl,
|
||
ACL_REVISION,
|
||
AccessMask,
|
||
pSid
|
||
) ) {
|
||
rc = GetLastError();
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case ACCESS_DENIED_ACE_TYPE:
|
||
|
||
if ( ! AddAccessDeniedAce(
|
||
pNewAcl,
|
||
ACL_REVISION,
|
||
AccessMask,
|
||
pSid
|
||
) ) {
|
||
rc = GetLastError();
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ( rc != ERROR_SUCCESS)
|
||
goto Cleanup;
|
||
|
||
//
|
||
// copy all the ACEs in the old ACL after the newly added ACE
|
||
// (potentially skipping the first ACE in the old ACL)
|
||
//
|
||
|
||
memcpy((PUCHAR)pNewAcl + sizeof(ACL) + dwAceSize,
|
||
(PUCHAR)pOldAcl + sizeof(ACL) + dwFirstAceSize,
|
||
pOldAcl->AclSize - (sizeof(ACL) + dwFirstAceSize) );
|
||
|
||
pNewAcl->AceCount += pOldAcl->AceCount;
|
||
|
||
if ( dwFirstAceSize != 0 )
|
||
--pNewAcl->AceCount;
|
||
|
||
SetDacl:
|
||
|
||
//
|
||
// either set the adjusted-ACE ACL, or the added-ACE ACL in the SD
|
||
//
|
||
|
||
if ( rc == ERROR_SUCCESS ) {
|
||
|
||
NtStatus = RtlSetDaclSecurityDescriptor (
|
||
pSDAbsolute,
|
||
TRUE,
|
||
( bOrMaskInOldDacl ? pOldAcl : pNewAcl),
|
||
FALSE
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError(NtStatus);
|
||
|
||
}
|
||
|
||
if ( rc == ERROR_SUCCESS ) {
|
||
|
||
if ( !IsValidSecurityDescriptor(pSDAbsolute) )
|
||
|
||
rc = ERROR_INVALID_SECURITY_DESCR;
|
||
|
||
}
|
||
|
||
|
||
Cleanup:
|
||
|
||
if (rc != ERROR_SUCCESS) {
|
||
if (pNewAcl)
|
||
LocalFree(pNewAcl);
|
||
*ppNewAcl = NULL;
|
||
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
DWORD
|
||
ScepConfigureLSAPolicyObject(
|
||
IN DWORD dwLSAAnonymousNameLookup,
|
||
IN DWORD ConfigOptions,
|
||
IN PSCE_ERROR_LOG_INFO *pErrLog OPTIONAL,
|
||
OUT BOOL *pbOldLSAPolicyDifferent
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
This routine *actually* configures the LSA policy security descriptor ONLY if required.
|
||
|
||
Arguments:
|
||
|
||
dwLSAAnonymousNameLookup - the value of the desired setting
|
||
|
||
ConfigOptions - configuration options
|
||
|
||
pErrLog - ptr to error log list
|
||
|
||
pbOldLSAPolicyDifferent - ptr to boolean that says whether or not the
|
||
existing setting is different from the desired setting
|
||
this information is required for tattooing
|
||
|
||
Return Value:
|
||
|
||
Win32 error code
|
||
*/
|
||
{
|
||
NTSTATUS NtStatus = STATUS_SUCCESS;
|
||
DWORD rc = ERROR_SUCCESS;
|
||
PACL pNewAcl = NULL;
|
||
DWORD dwAceType;
|
||
BOOL bAddAce = FALSE;
|
||
PSECURITY_DESCRIPTOR pSDCurrentLsaPolicyObject = NULL;
|
||
SECURITY_DESCRIPTOR SDAbsoluteToBuildAndSet;
|
||
|
||
if (pbOldLSAPolicyDifferent == NULL ||
|
||
(dwLSAAnonymousNameLookup != 0 && dwLSAAnonymousNameLookup != 1))
|
||
{
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
}
|
||
|
||
LSA_HANDLE LsaHandle = NULL;
|
||
|
||
if ( LsaPrivatePolicy == NULL ) {
|
||
|
||
NtStatus = ScepOpenLsaPolicy(
|
||
MAXIMUM_ALLOWED,
|
||
&LsaHandle,
|
||
TRUE
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
}
|
||
|
||
else {
|
||
|
||
LsaHandle = LsaPrivatePolicy;
|
||
|
||
}
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_LSA_POLICY
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_LSA_POLICY);
|
||
}
|
||
}
|
||
|
||
if ( rc == ERROR_SUCCESS ) {
|
||
|
||
NtStatus = LsaQuerySecurityObject(
|
||
LsaHandle,
|
||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||
&pSDCurrentLsaPolicyObject
|
||
);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_QUERY
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_QUERY);
|
||
}
|
||
}
|
||
|
||
if ( rc == ERROR_SUCCESS ) {
|
||
|
||
LPTSTR pwszSDlsaPolicyObject = NULL;
|
||
|
||
//
|
||
// log the SDDL SD for diagnostics
|
||
//
|
||
|
||
if ( ConvertSecurityDescriptorToStringSecurityDescriptor(
|
||
pSDCurrentLsaPolicyObject,
|
||
SDDL_REVISION_1,
|
||
DACL_SECURITY_INFORMATION,
|
||
&pwszSDlsaPolicyObject,
|
||
NULL
|
||
) ){
|
||
|
||
ScepLogOutput3(1,0,SCEDLL_SCP_INFO_LSAPOLICY_EXISTING_SDDL, pwszSDlsaPolicyObject);
|
||
|
||
LocalFree(pwszSDlsaPolicyObject);
|
||
|
||
}
|
||
|
||
//
|
||
// use AUTHZ to check if desired access is existing access
|
||
//
|
||
|
||
if ( ghAuthzResourceManager ) {
|
||
|
||
SID AnonymousSid;
|
||
SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
|
||
AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext = NULL;
|
||
LUID Identifier = {0};
|
||
|
||
RtlInitializeSid ( &AnonymousSid, &NtAuth, 1);
|
||
*RtlSubAuthoritySid ( &AnonymousSid, 0 ) = SECURITY_ANONYMOUS_LOGON_RID;
|
||
|
||
if ( AuthzInitializeContextFromSid(AUTHZ_SKIP_TOKEN_GROUPS,
|
||
&AnonymousSid,
|
||
ghAuthzResourceManager,
|
||
0,
|
||
Identifier,
|
||
NULL,
|
||
&hAuthzClientContext) ) {
|
||
|
||
AUTHZ_ACCESS_REPLY AuthzReply;
|
||
AUTHZ_ACCESS_REQUEST AuthzRequest;
|
||
ACCESS_MASK GrantedAccessMask;
|
||
DWORD AuthzError;
|
||
|
||
AuthzReply.ResultListLength = 1;
|
||
AuthzReply.GrantedAccessMask = &GrantedAccessMask;
|
||
AuthzReply.Error = &AuthzError;
|
||
AuthzReply.SaclEvaluationResults = NULL;
|
||
|
||
memset(&AuthzRequest, 0, sizeof(AuthzRequest));
|
||
AuthzRequest.DesiredAccess = POLICY_LOOKUP_NAMES;
|
||
|
||
DWORD AceType = 0;
|
||
|
||
if ( AuthzAccessCheck(0,
|
||
hAuthzClientContext,
|
||
&AuthzRequest,
|
||
NULL,
|
||
pSDCurrentLsaPolicyObject,
|
||
NULL,
|
||
NULL,
|
||
&AuthzReply,
|
||
NULL) ) {
|
||
|
||
//
|
||
// check if existing access is different from desired access
|
||
// if so, add the appropriate ACE or manipulate existing ACEs
|
||
// to get the desired permissions
|
||
//
|
||
|
||
if ( GrantedAccessMask & POLICY_LOOKUP_NAMES ) {
|
||
//ASSERT(AuthzError == ERROR_SUCCESS);
|
||
if ( !dwLSAAnonymousNameLookup ) {
|
||
|
||
bAddAce = TRUE;
|
||
AceType = ACCESS_DENIED_ACE_TYPE;
|
||
|
||
}
|
||
|
||
|
||
} else {
|
||
//ASSERT(AuthzError == ERROR_ACCESS_DENIED || AuthzError == ERROR_PRIVILEGE_NOT_HELD);
|
||
if ( dwLSAAnonymousNameLookup ) {
|
||
|
||
bAddAce = TRUE;
|
||
AceType = ACCESS_ALLOWED_ACE_TYPE;
|
||
|
||
}
|
||
}
|
||
|
||
if ( bAddAce ) {
|
||
|
||
*pbOldLSAPolicyDifferent = TRUE;
|
||
|
||
if ( InitializeSecurityDescriptor( &SDAbsoluteToBuildAndSet, SECURITY_DESCRIPTOR_REVISION) ) {
|
||
|
||
rc = ScepAddAceToSecurityDescriptor(
|
||
AceType,
|
||
POLICY_LOOKUP_NAMES,
|
||
&AnonymousSid,
|
||
&SDAbsoluteToBuildAndSet,
|
||
pSDCurrentLsaPolicyObject,
|
||
&pNewAcl
|
||
);
|
||
|
||
if ( rc == ERROR_SUCCESS) {
|
||
|
||
//
|
||
// log the SDDL SD for diagnostics
|
||
//
|
||
pwszSDlsaPolicyObject = NULL;
|
||
|
||
if ( ConvertSecurityDescriptorToStringSecurityDescriptor(
|
||
&SDAbsoluteToBuildAndSet,
|
||
SDDL_REVISION_1,
|
||
DACL_SECURITY_INFORMATION,
|
||
&pwszSDlsaPolicyObject,
|
||
NULL
|
||
) ){
|
||
|
||
ScepLogOutput3(1,0,SCEDLL_SCP_INFO_LSAPOLICY_COMPUTED_SDDL, pwszSDlsaPolicyObject);
|
||
|
||
LocalFree(pwszSDlsaPolicyObject);
|
||
|
||
}
|
||
|
||
NtStatus = LsaSetSecurityObject(
|
||
LsaHandle,
|
||
DACL_SECURITY_INFORMATION,
|
||
&SDAbsoluteToBuildAndSet
|
||
);
|
||
|
||
LocalFree(pNewAcl);
|
||
|
||
rc = RtlNtStatusToDosError( NtStatus );
|
||
|
||
if ( !NT_SUCCESS( NtStatus ) ) {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_SET
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_SET);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
else {
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_BUILDDACL
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_BUILDDACL);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
else {
|
||
|
||
rc = GetLastError();
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_SD_INIT
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_SD_INIT);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
else {
|
||
|
||
rc = GetLastError();
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
|
||
}
|
||
|
||
}
|
||
|
||
AuthzFreeContext( hAuthzClientContext );
|
||
|
||
} else {
|
||
|
||
rc = GetLastError();
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
else {
|
||
|
||
rc = ERROR_RESOURCE_NOT_PRESENT;
|
||
|
||
if ( (ConfigOptions & SCE_SYSTEM_SETTINGS) && pErrLog ) {
|
||
|
||
ScepBuildErrorLogInfo(
|
||
rc,
|
||
pErrLog,
|
||
SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ
|
||
);
|
||
} else {
|
||
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_LSAPOLICY_AUTHZ);
|
||
}
|
||
|
||
}
|
||
|
||
LsaFreeMemory(pSDCurrentLsaPolicyObject);
|
||
|
||
}
|
||
|
||
if ( LsaPrivatePolicy == NULL ) {
|
||
|
||
LsaClose(LsaHandle);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|