818 lines
21 KiB
C++
818 lines
21 KiB
C++
|
//Copyright (c) 1998 - 1999 Microsoft Corporation
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
*
|
||
|
* acl.c
|
||
|
*
|
||
|
* Generic routines to manage ACL's
|
||
|
*
|
||
|
* Author: John Richardson 04/25/97
|
||
|
*
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* Includes
|
||
|
*/
|
||
|
#include "stdafx.h"
|
||
|
/*
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <rpc.h>
|
||
|
#include <stdio.h>
|
||
|
#include <process.h>
|
||
|
|
||
|
#include <lmaccess.h>
|
||
|
#include <lmapibuf.h>
|
||
|
#include <lmerr.h>
|
||
|
|
||
|
#undef DBG
|
||
|
#define DBG 1
|
||
|
#define DBGTRACE 1
|
||
|
|
||
|
#define DbgPrint(x)
|
||
|
#if DBG
|
||
|
//ULONG
|
||
|
//DbgPrint(
|
||
|
// PCH Format,
|
||
|
// ...
|
||
|
// );
|
||
|
|
||
|
#define DBGPRINT(x) DbgPrint(x)
|
||
|
#if DBGTRACE
|
||
|
#define TRACE0(x) DbgPrint x
|
||
|
#define TRACE1(x) DbgPrint x
|
||
|
#else
|
||
|
#define TRACE0(x)
|
||
|
#define TRACE1(x)
|
||
|
#endif
|
||
|
#else
|
||
|
#define DBGPRINT(x)
|
||
|
#define TRACE0(x)
|
||
|
#define TRACE1(x)
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Forward references
|
||
|
*/
|
||
|
BOOL
|
||
|
xxxLookupAccountName(
|
||
|
PWCHAR pSystemName,
|
||
|
PWCHAR pAccountName,
|
||
|
PSID *ppSid
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
SelfRelativeToAbsoluteSD(
|
||
|
PSECURITY_DESCRIPTOR SecurityDescriptorIn,
|
||
|
PSECURITY_DESCRIPTOR *SecurityDescriptorOut,
|
||
|
PULONG ReturnedLength
|
||
|
);
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* AddTerminalServerUserToSD
|
||
|
*
|
||
|
* Add the given user for the given domain to the security descriptor.
|
||
|
* The callers security descriptor may be re-allocated.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* Param1 (input/output)
|
||
|
* Comments
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
BOOL
|
||
|
AddTerminalServerUserToSD(
|
||
|
PSECURITY_DESCRIPTOR *ppSd,
|
||
|
DWORD NewAccess,
|
||
|
PACL *ppDacl
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
BOOL Result;
|
||
|
BOOL DaclPresent;
|
||
|
BOOL DaclDefaulted;
|
||
|
DWORD Length;
|
||
|
DWORD NewAclLength;
|
||
|
PACE_HEADER OldAce;
|
||
|
PACE_HEADER NewAce;
|
||
|
ACL_SIZE_INFORMATION AclInfo;
|
||
|
PSID pSid = NULL;
|
||
|
PACL Dacl = NULL;
|
||
|
PACL NewDacl = NULL;
|
||
|
PACL NewAceDacl = NULL;
|
||
|
PSECURITY_DESCRIPTOR NewSD = NULL;
|
||
|
PSECURITY_DESCRIPTOR OldSD = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
OldSD = *ppSd;
|
||
|
|
||
|
pSid = LocalAlloc(LMEM_FIXED, 1024);
|
||
|
if (!pSid || !InitializeSid(pSid, &SepNtAuthority, 1))
|
||
|
{
|
||
|
return( FALSE );
|
||
|
};
|
||
|
|
||
|
*(GetSidSubAuthority(pSid, 0 )) = SECURITY_TERMINAL_SERVER_RID;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Convert SecurityDescriptor to absolute format. It generates
|
||
|
* a new SecurityDescriptor for its output which we must free.
|
||
|
*/
|
||
|
Result = SelfRelativeToAbsoluteSD( OldSD, &NewSD, NULL );
|
||
|
if ( !Result ) {
|
||
|
LOGMESSAGE1(_T("Could not convert to AbsoluteSD %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
// Must get DACL pointer again from new (absolute) SD
|
||
|
Result = GetSecurityDescriptorDacl(
|
||
|
NewSD,
|
||
|
&DaclPresent,
|
||
|
&Dacl,
|
||
|
&DaclDefaulted
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Could not get Dacl %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If no DACL, no need to add the user since no DACL
|
||
|
// means all accesss
|
||
|
//
|
||
|
if( !DaclPresent ) {
|
||
|
LOGMESSAGE2(_T("SD has no DACL, Present %d, Defaulted %d\n"),DaclPresent,DaclDefaulted);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Code can return DaclPresent, but a NULL which means
|
||
|
// a NULL Dacl is present. This allows all access to the object.
|
||
|
//
|
||
|
if( Dacl == NULL ) {
|
||
|
LOGMESSAGE2(_T("SD has NULL DACL, Present %d, Defaulted %d\n"),DaclPresent,DaclDefaulted);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
// Get the current ACL's size
|
||
|
Result = GetAclInformation(
|
||
|
Dacl,
|
||
|
&AclInfo,
|
||
|
sizeof(AclInfo),
|
||
|
AclSizeInformation
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error GetAclInformation %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a new ACL to put the new access allowed ACE on
|
||
|
// to get the right structures and sizes.
|
||
|
//
|
||
|
NewAclLength = sizeof(ACL) +
|
||
|
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) +
|
||
|
GetLengthSid( pSid );
|
||
|
|
||
|
NewAceDacl = (PACL) LocalAlloc( LMEM_FIXED, NewAclLength );
|
||
|
if ( NewAceDacl == NULL ) {
|
||
|
LOGMESSAGE1(_T("Error LocalAlloc %d bytes\n"),NewAclLength);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = InitializeAcl( NewAceDacl, NewAclLength, ACL_REVISION );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Initializing Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = AddAccessAllowedAce(
|
||
|
NewAceDacl,
|
||
|
ACL_REVISION,
|
||
|
NewAccess,
|
||
|
pSid
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error adding Ace %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
LOGMESSAGE1(_T("Added 0x%x Access to ACL\n"),NewAccess);
|
||
|
|
||
|
Result = GetAce( NewAceDacl, 0, (void **)&NewAce );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error getting Ace %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/* add CONTAINER_INHERIT_ACE TO AceFlags */
|
||
|
NewAce->AceFlags |= CONTAINER_INHERIT_ACE;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Allocate new DACL and copy existing ACE list
|
||
|
*/
|
||
|
Length = AclInfo.AclBytesInUse + NewAce->AceSize;
|
||
|
NewDacl = (PACL) LocalAlloc( LMEM_FIXED, Length );
|
||
|
if( NewDacl == NULL ) {
|
||
|
LOGMESSAGE1(_T("Error LocalAlloc %d bytes\n"),Length);
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = InitializeAcl( NewDacl, Length, ACL_REVISION );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Initializing Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Insert new ACE at the front of the DACL
|
||
|
*/
|
||
|
Result = AddAce( NewDacl, ACL_REVISION, 0, NewAce, NewAce->AceSize );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Adding New Ace to Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now put the ACE's on the old Dacl to the new Dacl
|
||
|
*/
|
||
|
for ( i = 0; i < AclInfo.AceCount; i++ ) {
|
||
|
|
||
|
Result = GetAce( Dacl, i, (void **) &OldAce );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error getting old Ace from Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = AddAce( NewDacl, ACL_REVISION, i+1, OldAce, OldAce->AceSize );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error setting old Ace to Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set new DACL for Security Descriptor
|
||
|
*/
|
||
|
Result = SetSecurityDescriptorDacl(
|
||
|
NewSD,
|
||
|
TRUE,
|
||
|
NewDacl,
|
||
|
FALSE
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error setting New Dacl to SD %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
// the DACL must be passed back so that it can be saved to the registry using the new
|
||
|
// GetNamedSecurityInfo() func.
|
||
|
*ppDacl = Dacl = NewDacl;
|
||
|
|
||
|
|
||
|
// Release the callers old security descriptor
|
||
|
// LocalFree( OldSD );
|
||
|
|
||
|
|
||
|
// There was a bug in W2K such that keys created under our install hive had the
|
||
|
// incorrect DACL headers which caused the DACL to be basically open to all users
|
||
|
// for full control.
|
||
|
// The prolem was due to the wrong SD->Control flag which was NT4 style though ACLs
|
||
|
// were in NT5 style
|
||
|
SetSecurityDescriptorControl(NewSD,
|
||
|
SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
|
||
|
SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
|
||
|
|
||
|
*ppSd = NewSD;
|
||
|
|
||
|
// The new SD is in absolute format, so don't free the SID.
|
||
|
// LocalFree( pSid );
|
||
|
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* AddUserToSD
|
||
|
*
|
||
|
* Add the given user for the given domain to the security descriptor.
|
||
|
* The callers security descriptor may be re-allocated.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* Param1 (input/output)
|
||
|
* Comments
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
AddUserToSD(
|
||
|
PSECURITY_DESCRIPTOR *ppSd,
|
||
|
PWCHAR pAccount,
|
||
|
PWCHAR pDomain,
|
||
|
DWORD NewAccess
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
BOOL Result;
|
||
|
BOOL DaclPresent;
|
||
|
BOOL DaclDefaulted;
|
||
|
DWORD Length;
|
||
|
// NET_API_STATUS Status;
|
||
|
DWORD /*NewAceLength,*/ NewAclLength;
|
||
|
PACE_HEADER OldAce;
|
||
|
PACE_HEADER NewAce;
|
||
|
ACL_SIZE_INFORMATION AclInfo;
|
||
|
PWCHAR pDC = NULL;
|
||
|
PSID pSid = NULL;
|
||
|
PACL Dacl = NULL;
|
||
|
PACL NewDacl = NULL;
|
||
|
PACL NewAceDacl = NULL;
|
||
|
PSECURITY_DESCRIPTOR NewSD = NULL;
|
||
|
PSECURITY_DESCRIPTOR OldSD = NULL;
|
||
|
|
||
|
OldSD = *ppSd;
|
||
|
/*
|
||
|
// Get our domain controller
|
||
|
Status = NetGetAnyDCName(
|
||
|
NULL, // Local computer
|
||
|
pDomain,
|
||
|
(LPBYTE*)&pDC
|
||
|
);
|
||
|
if( Status != NERR_Success ) {
|
||
|
LOGMESSAGE2(_T("SUSERVER: Could not get domain controller %d for domain %ws\n"),Status,pDomain);
|
||
|
return( FALSE );
|
||
|
}
|
||
|
*/
|
||
|
// Get Users SID
|
||
|
Result = xxxLookupAccountName(
|
||
|
pDomain,
|
||
|
pAccount,
|
||
|
&pSid
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE2(_T("SUSERVER: Could not get users SID %d, %ws\n"),GetLastError(),pAccount);
|
||
|
NetApiBufferFree( pDC );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
NetApiBufferFree( pDC );
|
||
|
|
||
|
/*
|
||
|
* Convert SecurityDescriptor to absolute format. It generates
|
||
|
* a new SecurityDescriptor for its output which we must free.
|
||
|
*/
|
||
|
Result = SelfRelativeToAbsoluteSD( OldSD, &NewSD, NULL );
|
||
|
if ( !Result ) {
|
||
|
LOGMESSAGE1(_T("Could not convert to AbsoluteSD %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
// Must get DACL pointer again from new (absolute) SD
|
||
|
Result = GetSecurityDescriptorDacl(
|
||
|
NewSD,
|
||
|
&DaclPresent,
|
||
|
&Dacl,
|
||
|
&DaclDefaulted
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Could not get Dacl %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If no DACL, no need to add the user since no DACL
|
||
|
// means all accesss
|
||
|
//
|
||
|
if( !DaclPresent ) {
|
||
|
LOGMESSAGE2(_T("SD has no DACL, Present %d, Defaulted %d\n"),DaclPresent,DaclDefaulted);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Code can return DaclPresent, but a NULL which means
|
||
|
// a NULL Dacl is present. This allows all access to the object.
|
||
|
//
|
||
|
if( Dacl == NULL ) {
|
||
|
LOGMESSAGE2(_T("SD has NULL DACL, Present %d, Defaulted %d\n"),DaclPresent,DaclDefaulted);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
// Get the current ACL's size
|
||
|
Result = GetAclInformation(
|
||
|
Dacl,
|
||
|
&AclInfo,
|
||
|
sizeof(AclInfo),
|
||
|
AclSizeInformation
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error GetAclInformation %d\n"),GetLastError());
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a new ACL to put the new access allowed ACE on
|
||
|
// to get the right structures and sizes.
|
||
|
//
|
||
|
NewAclLength = sizeof(ACL) +
|
||
|
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) +
|
||
|
GetLengthSid( pSid );
|
||
|
|
||
|
NewAceDacl = (PACL) LocalAlloc( LMEM_FIXED, NewAclLength );
|
||
|
if ( NewAceDacl == NULL ) {
|
||
|
LOGMESSAGE1(_T("Error LocalAlloc %d bytes\n"),NewAclLength);
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = InitializeAcl( NewAceDacl, NewAclLength, ACL_REVISION );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Initializing Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = AddAccessAllowedAce(
|
||
|
NewAceDacl,
|
||
|
ACL_REVISION,
|
||
|
NewAccess,
|
||
|
pSid
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error adding Ace %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
LOGMESSAGE1(_T("Added 0x%x Access to ACL\n"),NewAccess);
|
||
|
|
||
|
Result = GetAce( NewAceDacl, 0, (void **)&NewAce );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error getting Ace %d\n"),GetLastError());
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/* add CONTAINER_INHERIT_ACE TO AceFlags */
|
||
|
NewAce->AceFlags |= CONTAINER_INHERIT_ACE;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Allocate new DACL and copy existing ACE list
|
||
|
*/
|
||
|
Length = AclInfo.AclBytesInUse + NewAce->AceSize;
|
||
|
NewDacl = (PACL) LocalAlloc( LMEM_FIXED, Length );
|
||
|
if( NewDacl == NULL ) {
|
||
|
LOGMESSAGE1(_T("Error LocalAlloc %d bytes\n"),Length);
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = InitializeAcl( NewDacl, Length, ACL_REVISION );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Initializing Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Insert new ACE at the front of the DACL
|
||
|
*/
|
||
|
Result = AddAce( NewDacl, ACL_REVISION, 0, NewAce, NewAce->AceSize );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error Adding New Ace to Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now put the ACE's on the old Dacl to the new Dacl
|
||
|
*/
|
||
|
for ( i = 0; i < AclInfo.AceCount; i++ ) {
|
||
|
|
||
|
Result = GetAce( Dacl, i, (void **) &OldAce );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error getting old Ace from Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Result = AddAce( NewDacl, ACL_REVISION, i+1, OldAce, OldAce->AceSize );
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error setting old Ace to Acl %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set new DACL for Security Descriptor
|
||
|
*/
|
||
|
Result = SetSecurityDescriptorDacl(
|
||
|
NewSD,
|
||
|
TRUE,
|
||
|
NewDacl,
|
||
|
FALSE
|
||
|
);
|
||
|
if( !Result ) {
|
||
|
LOGMESSAGE1(_T("Error setting New Dacl to SD %d\n"),GetLastError());
|
||
|
LocalFree( NewDacl );
|
||
|
LocalFree( NewAceDacl );
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( NewSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
Dacl = NewDacl;
|
||
|
|
||
|
// Release the callers old security descriptor
|
||
|
// LocalFree( OldSD );
|
||
|
|
||
|
*ppSd = NewSD;
|
||
|
|
||
|
// The new SD is in absolute format, so don't free the SID.
|
||
|
// LocalFree( pSid );
|
||
|
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* SelfRelativeToAbsoluteSD
|
||
|
*
|
||
|
* Convert a Security Descriptor from self-relative format to absolute.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* SecurityDescriptorIn (input)
|
||
|
* Pointer to self-relative SD to convert
|
||
|
* SecurityDescriptorIn (output)
|
||
|
* Pointer to location to return absolute SD
|
||
|
* ReturnLength (output)
|
||
|
* Pointer to location to return length of absolute SD
|
||
|
*
|
||
|
* EXIT:
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
SelfRelativeToAbsoluteSD(
|
||
|
PSECURITY_DESCRIPTOR SecurityDescriptorIn,
|
||
|
PSECURITY_DESCRIPTOR *SecurityDescriptorOut,
|
||
|
PULONG ReturnedLength
|
||
|
)
|
||
|
{
|
||
|
BOOL Result;
|
||
|
PACL pDacl, pSacl;
|
||
|
PSID pOwner, pGroup;
|
||
|
PSECURITY_DESCRIPTOR pSD;
|
||
|
ULONG SdSize, DaclSize, SaclSize, OwnerSize, GroupSize;
|
||
|
|
||
|
/*
|
||
|
* Determine buffer size needed to convert self-relative SD to absolute.
|
||
|
* We use try-except here since if the input security descriptor value
|
||
|
* is sufficiently messed up, it is possible for this call to trap.
|
||
|
*/
|
||
|
SdSize = DaclSize = SaclSize = OwnerSize = GroupSize = 0;
|
||
|
|
||
|
__try {
|
||
|
|
||
|
Result = MakeAbsoluteSD(
|
||
|
SecurityDescriptorIn,
|
||
|
NULL, &SdSize,
|
||
|
NULL, &DaclSize,
|
||
|
NULL, &SaclSize,
|
||
|
NULL, &OwnerSize,
|
||
|
NULL, &GroupSize
|
||
|
);
|
||
|
|
||
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
SetLastError( ERROR_INVALID_SECURITY_DESCR );
|
||
|
Result = FALSE;
|
||
|
}
|
||
|
|
||
|
if ( Result || (GetLastError() != ERROR_INSUFFICIENT_BUFFER) ) {
|
||
|
LOGMESSAGE1(_T("SUSERVER: SelfRelativeToAbsoluteSD, Error %d\n"),GetLastError());
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Allocate memory for the absolute SD and setup various pointers
|
||
|
*/
|
||
|
pSD = LocalAlloc( LMEM_FIXED, SdSize + DaclSize + SaclSize + OwnerSize + GroupSize );
|
||
|
if ( pSD == NULL )
|
||
|
return( FALSE );
|
||
|
|
||
|
pDacl = (PACL)((PCHAR)pSD + SdSize);
|
||
|
pSacl = (PACL)((PCHAR)pDacl + DaclSize);
|
||
|
pOwner = (PSID)((PCHAR)pSacl + SaclSize);
|
||
|
pGroup = (PSID)((PCHAR)pOwner + OwnerSize);
|
||
|
|
||
|
/*
|
||
|
* Now convert self-relative SD to absolute format.
|
||
|
* We use try-except here since if the input security descriptor value
|
||
|
* is sufficiently messed up, it is possible for this call to trap.
|
||
|
*/
|
||
|
__try {
|
||
|
Result = MakeAbsoluteSD(
|
||
|
SecurityDescriptorIn,
|
||
|
pSD, &SdSize,
|
||
|
pDacl, &DaclSize,
|
||
|
pSacl, &SaclSize,
|
||
|
pOwner, &OwnerSize,
|
||
|
pGroup, &GroupSize
|
||
|
);
|
||
|
|
||
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
SetLastError( ERROR_INVALID_SECURITY_DESCR );
|
||
|
Result = FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !Result ) {
|
||
|
LOGMESSAGE1(_T("SUSERVER: SelfRelativeToAbsoluteSD, Error %d\n"),GetLastError());
|
||
|
LocalFree( pSD );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
*SecurityDescriptorOut = pSD;
|
||
|
|
||
|
if ( ReturnedLength )
|
||
|
*ReturnedLength = SdSize + DaclSize + SaclSize + OwnerSize + GroupSize;
|
||
|
|
||
|
return( TRUE );
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* xxxLookupAccountName
|
||
|
*
|
||
|
* Wrapper to lookup the SID for a given account name
|
||
|
*
|
||
|
* Returns a pointer to the SID in newly allocated memory
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* Param1 (input/output)
|
||
|
* Comments
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - no error
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
xxxLookupAccountName(
|
||
|
PWCHAR pSystemName,
|
||
|
PWCHAR pAccountName,
|
||
|
PSID *ppSid
|
||
|
)
|
||
|
{
|
||
|
BOOL rc;
|
||
|
DWORD Size, DomainSize, Error;
|
||
|
SID_NAME_USE Type;
|
||
|
PWCHAR pDomain = NULL;
|
||
|
PSID pSid = NULL;
|
||
|
WCHAR Buf;
|
||
|
|
||
|
Size = 0;
|
||
|
DomainSize = 0;
|
||
|
|
||
|
rc = LookupAccountNameW(
|
||
|
pSystemName,
|
||
|
pAccountName,
|
||
|
&Buf, // pSid
|
||
|
&Size,
|
||
|
&Buf, // pDomain
|
||
|
&DomainSize,
|
||
|
&Type
|
||
|
);
|
||
|
|
||
|
if( rc ) {
|
||
|
return( FALSE );
|
||
|
}
|
||
|
else {
|
||
|
Error = GetLastError();
|
||
|
if( Error != ERROR_INSUFFICIENT_BUFFER ) {
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
pSid = LocalAlloc( LMEM_FIXED, Size );
|
||
|
if( pSid == NULL ) {
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
pDomain = (WCHAR *)LocalAlloc( LMEM_FIXED, DomainSize*sizeof(WCHAR) );
|
||
|
if( pDomain == NULL ) {
|
||
|
LocalFree( pSid );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
rc = LookupAccountNameW(
|
||
|
pSystemName,
|
||
|
pAccountName,
|
||
|
pSid,
|
||
|
&Size,
|
||
|
pDomain,
|
||
|
&DomainSize,
|
||
|
&Type
|
||
|
);
|
||
|
|
||
|
if( !rc ) {
|
||
|
LocalFree( pSid );
|
||
|
LocalFree( pDomain );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
*ppSid = pSid;
|
||
|
|
||
|
LocalFree( pDomain );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
}
|
||
|
|