windows-nt/Source/XPSP1/NT/ds/security/services/scerpc/server/setupsrv.cpp
2020-09-26 16:20:57 +08:00

613 lines
15 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
setupsrv.cpp
Abstract:
Routines for secedit integration with system setup and component setup
Author:
Jin Huang (jinhuang) 15-Aug-1997
Revision History:
jinhuang 26-Jan-1998 splitted to client-server
--*/
#include "headers.h"
#include "serverp.h"
#include "srvrpcp.h"
#include "pfp.h"
#include <io.h>
SCESTATUS
ScepUpdateObjectInSection(
IN PSCECONTEXT hProfile,
IN SCETYPE ProfileType,
IN PWSTR ObjectName,
IN SE_OBJECT_TYPE ObjectType,
IN UINT nFlag,
IN PWSTR SDText,
OUT UINT *pStatus
);
//
// implementations
//
DWORD
ScepSetupUpdateObject(
IN PSCECONTEXT Context,
IN PWSTR ObjectFullName,
IN SE_OBJECT_TYPE ObjectType,
IN UINT nFlag,
IN PWSTR SDText
)
/*
Routine Description:
This routine is the private API called from the RPC interface to
update object information in the database.
Arguments:
Context - the database context handle
ObjectFullName - the object's name
Objecttype - the object type
nFlag - the flag on how to update this object
SDText - the security descriptor in SDDL text
Return Value:
*/
{
if ( !ObjectFullName || NULL == SDText ) {
return ERROR_INVALID_PARAMETER;
}
switch ( ObjectType ) {
case SE_SERVICE:
case SE_REGISTRY_KEY:
case SE_FILE_OBJECT:
break;
default:
return ERROR_INVALID_PARAMETER;
}
SCESTATUS rc;
DWORD dwInSetup=0;
ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
TEXT("System\\Setup"),
TEXT("SystemSetupInProgress"),
&dwInSetup
);
//
// convert SDText to security descriptor
//
PSECURITY_DESCRIPTOR pSD=NULL;
DWORD SDSize;
SECURITY_INFORMATION SeInfo=0;
HANDLE Token=NULL;
DWORD Win32rc=ERROR_SUCCESS;
if ( !(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
//
// security will be set, so compute the security descriptor
//
Win32rc = ConvertTextSecurityDescriptor (
SDText,
&pSD,
&SDSize,
&SeInfo
);
if ( NO_ERROR == Win32rc ) {
ScepChangeAclRevision(pSD, ACL_REVISION);
//
// get current thread/process's token
//
if (!OpenThreadToken( GetCurrentThread(),
TOKEN_QUERY,
FALSE,
&Token)) {
if (!OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY,
&Token)) {
Win32rc = GetLastError();
}
}
if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) ) {
SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
}
}
}
if ( NO_ERROR == Win32rc ) {
//
// only update DB if it's in setup
//
//
// on 64-bit platform, only update database if setup does not indicate SCE_SETUP_32KEY flag
//
#ifdef _WIN64
if ( dwInSetup && !(nFlag & SCE_SETUP_32KEY) ) {
#else
if ( dwInSetup ) {
#endif
// save this into SCP and SMP, do not overwrite the status/container flag
// if there is one exist, else use SCE_STATUS_CHECK and check for container
//
//
// start a transaction since there are multiple operations
//
rc = SceJetStartTransaction( Context );
if ( rc == SCESTATUS_SUCCESS ) {
UINT Status=SCE_STATUS_CHECK;
rc = ScepUpdateObjectInSection(
Context,
SCE_ENGINE_SMP,
ObjectFullName,
ObjectType,
nFlag,
SDText,
&Status
);
if ( rc == SCESTATUS_SUCCESS &&
(Context->JetSapID != JET_tableidNil) ) {
//
// the SAP table ID points to the tattoo table
// should update the tattoo table too if it exist
//
rc = ScepUpdateObjectInSection(
Context,
SCE_ENGINE_SAP,
ObjectFullName,
ObjectType,
nFlag,
SDText,
NULL
);
}
}
} else {
rc = SCESTATUS_SUCCESS;
}
if ( rc == SCESTATUS_SUCCESS &&
!(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
//
// set security to the object
//
//
// if 64-bit platform, no synchronization is done and setup will have
// to call the exported API with SCE_SETUP_32KEY if 32-bit hive is desired
//
#ifdef _WIN64
if ( ObjectType == SE_REGISTRY_KEY && (nFlag & SCE_SETUP_32KEY) ){
ObjectType = SE_REGISTRY_WOW64_32KEY;
}
#endif
Win32rc = ScepSetSecurityWin32(
ObjectFullName,
SeInfo,
pSD,
ObjectType
);
} else
Win32rc = ScepSceStatusToDosError(rc);
if ( Win32rc == ERROR_SUCCESS ||
Win32rc == ERROR_FILE_NOT_FOUND ||
Win32rc == ERROR_PATH_NOT_FOUND ||
Win32rc == ERROR_INVALID_OWNER ||
Win32rc == ERROR_INVALID_PRIMARY_GROUP ||
Win32rc == ERROR_INVALID_HANDLE ) {
if ( Win32rc )
gWarningCode = Win32rc;
if ( dwInSetup ) { // in setup, update DB
Win32rc = ScepSceStatusToDosError(
SceJetCommitTransaction( Context, 0));
} else {
Win32rc = ERROR_SUCCESS;
}
} else if ( dwInSetup ) { // in setup
SceJetRollback( Context, 0 );
}
if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) )
SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
}
CloseHandle(Token);
if ( pSD ) {
LocalFree(pSD);
pSD = NULL;
}
return(Win32rc);
}
SCESTATUS
ScepUpdateObjectInSection(
IN PSCECONTEXT Context,
IN SCETYPE ProfileType,
IN PWSTR ObjectName,
IN SE_OBJECT_TYPE ObjectType,
IN UINT nFlag,
IN PWSTR SDText,
OUT UINT *pStatus
)
/*
Routine Description:
Update SCP and SMP. if the table does not exist at all, ignore the update.
Delete SAP entry for the object. If table or record not found, ignore the error.
Arguments:
Return Value:
*/
{
if ( Context == NULL || ObjectName == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
SCESTATUS rc;
PSCESECTION hSection=NULL;
PCWSTR SectionName;
switch ( ObjectType ) {
case SE_FILE_OBJECT:
SectionName = szFileSecurity;
break;
case SE_REGISTRY_KEY:
SectionName = szRegistryKeys;
break;
case SE_SERVICE:
SectionName = szServiceGeneral;
break;
default:
return(SCESTATUS_INVALID_PARAMETER);
}
rc = ScepOpenSectionForName(
Context,
ProfileType,
SectionName,
&hSection
);
if ( rc == SCESTATUS_BAD_FORMAT ||
rc == SCESTATUS_RECORD_NOT_FOUND ) {
return(SCESTATUS_SUCCESS);
}
if ( rc == SCESTATUS_SUCCESS ) {
WCHAR StatusFlag=L'\0';
DWORD ValueLen;
BYTE Status=SCE_STATUS_CHECK;
BOOL IsContainer=TRUE;
BYTE StartType;
rc = SceJetGetValue(
hSection,
SCEJET_EXACT_MATCH_NO_CASE,
ObjectName,
NULL,
0,
NULL,
(PWSTR)&StatusFlag,
2,
&ValueLen
);
if ( rc == SCESTATUS_SUCCESS ||
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
rc = SCESTATUS_SUCCESS;
Status = *((BYTE *)&StatusFlag);
if ( pStatus ) {
*pStatus = Status;
}
if ( ObjectType == SE_SERVICE ) {
StartType = *((BYTE *)&StatusFlag+1);
} else {
IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
}
}
if ( ObjectType == SE_SERVICE ) {
DWORD SDLen, Len;
PWSTR ValueToSet;
StartType = (BYTE)nFlag;
if ( SDText != NULL ) {
SDLen = wcslen(SDText);
Len = ( SDLen+1)*sizeof(WCHAR);
} else
Len = sizeof(WCHAR);
ValueToSet = (PWSTR)ScepAlloc( (UINT)0, Len+sizeof(WCHAR) );
if ( ValueToSet != NULL ) {
//
// The first byte is the flag, the second byte is IsContainer (1,0)
//
*((BYTE *)ValueToSet) = Status;
*((BYTE *)ValueToSet+1) = StartType;
if ( SDText != NULL ) {
swprintf(ValueToSet+1, L"%s", SDText );
ValueToSet[SDLen+1] = L'\0'; //terminate this string
} else {
ValueToSet[1] = L'\0';
}
if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
//
// only update tattoo table (pointed by SAP handle) if it finds a record there
// for other table (SMP), ignore the error code, just set
//
rc = SceJetSetLine( hSection,
ObjectName,
FALSE,
ValueToSet,
Len,
0);
}
ScepFree( ValueToSet );
} else {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
} else if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
//
// only update tattoo table (pointed by SAP handle) if it finds a record there
// for other table (SMP), ignore the error code, just set
//
rc = ScepSaveObjectString(
hSection,
ObjectName,
IsContainer,
Status,
SDText,
(SDText == NULL ) ? 0 : wcslen(SDText)
);
}
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
rc = SCESTATUS_SUCCESS;
SceJetCloseSection(&hSection, TRUE);
}
return(rc);
}
DWORD
ScepSetupMoveFile(
IN PSCECONTEXT Context,
PWSTR OldName,
PWSTR NewName OPTIONAL,
PWSTR SDText OPTIONAL
)
/*
Routine Description:
Set security to OldName but save with NewName in SCE database if SDText
is not NULL. If NewName is NULL, delete OldName from SCE database.
Arguments:
Context - the databaes context handle
SectionName - the section name
OldName - the object's old name
NewName - the new name to rename to, if NULL, delete the old object
SDText - security string
Return Value:
Win32 error code
*/
{
if ( !Context || !OldName ) {
return ERROR_INVALID_PARAMETER;
}
DWORD rc32=ERROR_SUCCESS;
if ( NewName && SDText ) {
//
// set security on OldName with SDText
//
rc32 = ScepSetupUpdateObject(
Context,
OldName,
SE_FILE_OBJECT,
0,
SDText
);
}
if ( rc32 == ERROR_SUCCESS ) {
//
// save this into SCP and SMP, do not overwrite the status/container flag
// if there is one exist, else use SCE_STATUS_CHECK and check for container
//
SCESTATUS rc = SceJetStartTransaction( Context );
if ( rc == SCESTATUS_SUCCESS ) {
PSCESECTION hSection=NULL;
//
// process SMP section first
//
rc = ScepOpenSectionForName(
Context,
SCE_ENGINE_SMP,
szFileSecurity,
&hSection
);
if ( rc == SCESTATUS_SUCCESS ) {
if ( NewName ) {
//
// rename this line
//
rc = SceJetRenameLine(
hSection,
OldName,
NewName,
FALSE);
} else {
//
// delete this line first
//
rc = SceJetDelete(
hSection,
OldName,
FALSE,
SCEJET_DELETE_LINE_NO_CASE
);
}
SceJetCloseSection( &hSection, TRUE);
}
if ( (SCESTATUS_SUCCESS == rc ||
SCESTATUS_RECORD_NOT_FOUND == rc ||
SCESTATUS_BAD_FORMAT == rc) &&
(Context->JetSapID != JET_tableidNil) ) {
//
// process tattoo table
//
rc = ScepOpenSectionForName(
Context,
SCE_ENGINE_SAP,
szFileSecurity,
&hSection
);
if ( rc == SCESTATUS_SUCCESS ) {
if ( NewName ) {
//
// rename this line
//
rc = SceJetRenameLine(
hSection,
OldName,
NewName,
FALSE);
} else {
//
// delete this line first
//
rc = SceJetDelete(
hSection,
OldName,
FALSE,
SCEJET_DELETE_LINE_NO_CASE
);
}
SceJetCloseSection( &hSection, TRUE);
}
}
if ( SCESTATUS_RECORD_NOT_FOUND == rc ||
SCESTATUS_BAD_FORMAT == rc ) {
rc = SCESTATUS_SUCCESS;
}
if ( SCESTATUS_SUCCESS == rc ) {
//
// commit the transaction
//
rc = SceJetCommitTransaction( Context, 0 );
} else {
//
// rollback the transaction
//
SceJetRollback( Context, 0 );
}
}
rc32 = ScepSceStatusToDosError(rc);
}
return(rc32);
}