Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

419 lines
12 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
sepriv.c
Abstract:
Security Runtime Library Privilege Routines
(Temporary copy of \nt\private\ntos\rtl\sepriv.c to allow
ntdailybld version of ntdll.dll to be used)
These routines perform operations with privilege sets
Author:
Scott Birrell (ScottBi) June 17, 1991
Environment:
Revision History:
Pete Skelly (petesk) Modified LsapRtlAddPrivileges to work within a preallocated
buffer for performance reasons
--*/
#include <lsapch2.h>
#include <string.h>
#define LsapRtlEqualPrivileges(FirstPrivilege, SecondPrivilege) \
(RtlEqualLuid(&(FirstPrivilege)->Luid, &(SecondPrivilege)->Luid))
#define PRIVILEGE_SET_STEP_SIZE 20
NTSTATUS
LsapRtlAddPrivileges(
IN OUT PPRIVILEGE_SET * RunningPrivileges,
IN OUT PULONG MaxRunningPrivileges,
IN PPRIVILEGE_SET PrivilegesToAdd,
IN ULONG Options,
OUT OPTIONAL BOOLEAN * Changed
)
/*++
Routine Description:
This function adds and/or updates privileges in a privilege set. The
existing privilege set is unaltered, a new privilege set being generated.
Existing privileges and Udpate privilege sets may point to the same location.
The memory for the new privilege set must already be allocated by the
caller. To assist in calculating the size of buffer required, the
routine may be called in 'query' mode by supplying buffer size of 0. In
this mode, the amount of memory required is returned and no copying
takes place.
WARNING: Privileges within each privilege set must all be distinct, that
is, there must not be two privileges in the same set having the same LUID.
Arguments:
RunningPrivileges - Pointer to a pointer pointing to a running privilege set.
MaxRunningPrivileges - maximum number of privileges that can be copied into the current privilege set
before it must be grown.
PrivilegesToAdd - Pointer to privilege set specifying privileges to
be added. The attributes of privileges in this set that also exist
in the ExistingPrivileges set supersede the attributes therein.
Options - Specifies optional actions.
RTL_COMBINE_PRIVILEGE_ATTRIBUTES - If the two privilege sets have
privileges in common, combine the attributes
RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES - If the two privilege sets
have privileges in common, supersede the existing attributes
with those specified in PrivilegesToAdd.
Changed - Used to indicate whether any change has been made
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INVALID_PARAMETER
STATUS_INSUFFICIENT_RESOURCES
Environment:
User or Kernel modes.
--*/
{
PLUID_AND_ATTRIBUTES Privilege;
ULONG AddIndex = 0L;
NTSTATUS Status = STATUS_SUCCESS;
ULONG CurrentPrivilegeCount = 0;
DWORD OldPrivilegeSetSize = 0;
//
// Verify that mandatory parameters have been specified.
// specified.
//
if (RunningPrivileges == NULL ||
MaxRunningPrivileges == NULL) {
return STATUS_INVALID_PARAMETER;
}
//
// Validate the Options parameter.
//
if ((Options != RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES) &&
(Options != RTL_COMBINE_PRIVILEGE_ATTRIBUTES)) {
return STATUS_INVALID_PARAMETER;
}
if ( Changed ) {
*Changed = FALSE;
}
if((PrivilegesToAdd == NULL) || (PrivilegesToAdd->PrivilegeCount == 0))
{
return STATUS_SUCCESS;
}
if(*RunningPrivileges == NULL)
{
PPRIVILEGE_SET UpdatedPrivileges = NULL;
ASSERT(PrivilegesToAdd->PrivilegeCount > 0);
OldPrivilegeSetSize = sizeof (PRIVILEGE_SET) + sizeof(LUID_AND_ATTRIBUTES)*
(PrivilegesToAdd->PrivilegeCount - ANYSIZE_ARRAY);
// We need to grow our privilege set
UpdatedPrivileges = (PPRIVILEGE_SET)MIDL_user_allocate( OldPrivilegeSetSize +
sizeof(LUID_AND_ATTRIBUTES)* PRIVILEGE_SET_STEP_SIZE);
if (UpdatedPrivileges == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(UpdatedPrivileges, PrivilegesToAdd, OldPrivilegeSetSize);
*RunningPrivileges = UpdatedPrivileges;
*MaxRunningPrivileges = PrivilegesToAdd->PrivilegeCount + PRIVILEGE_SET_STEP_SIZE;
if ( Changed ) {
*Changed = TRUE;
}
return STATUS_SUCCESS;
}
CurrentPrivilegeCount = (*RunningPrivileges)->PrivilegeCount;
//
// For each privilege to add, see if it's in the running privilege list,
// set the attributes if it is, append it if it isn't.
//
//
// Note, we dont' modify the count of RunningPrivileges until the end, so we don't
// inefficiently search things we are currently adding (there should be no duplicates in what
// we're currently adding);
//
for(AddIndex = 0;
AddIndex < PrivilegesToAdd->PrivilegeCount;
AddIndex++) {
Privilege = NULL;
if ((Privilege = LsapRtlGetPrivilege(
&PrivilegesToAdd->Privilege[AddIndex],
*RunningPrivileges
)) != NULL) {
if( Options & RTL_SUPERSEDE_PRIVILEGE_ATTRIBUTES &&
Privilege->Attributes != PrivilegesToAdd->Privilege[AddIndex].Attributes ) {
if ( Changed ) {
*Changed = TRUE;
}
Privilege->Attributes = PrivilegesToAdd->Privilege[AddIndex].Attributes;
}
}
else
{
// This is a new privilege, so add it to the end
ASSERT(*MaxRunningPrivileges >= CurrentPrivilegeCount);
if((CurrentPrivilegeCount+1) > *MaxRunningPrivileges)
{
// We need to grow our privilege set
PPRIVILEGE_SET UpdatedPrivileges = (PPRIVILEGE_SET)MIDL_user_allocate( sizeof (PRIVILEGE_SET) +
sizeof(LUID_AND_ATTRIBUTES)*
(*MaxRunningPrivileges +
PRIVILEGE_SET_STEP_SIZE - 1));
if (UpdatedPrivileges == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
if(*MaxRunningPrivileges > 0)
{
RtlCopyMemory(UpdatedPrivileges, *RunningPrivileges, sizeof (PRIVILEGE_SET) +
sizeof(LUID_AND_ATTRIBUTES)*
(*MaxRunningPrivileges - 1));
}
else
{
RtlCopyMemory(UpdatedPrivileges, *RunningPrivileges, sizeof (PRIVILEGE_SET));
}
MIDL_user_free(*RunningPrivileges);
*RunningPrivileges = UpdatedPrivileges;
*MaxRunningPrivileges += PRIVILEGE_SET_STEP_SIZE;
}
(*RunningPrivileges)->Privilege[CurrentPrivilegeCount++] = PrivilegesToAdd->Privilege[AddIndex];
if ( Changed ) {
*Changed = TRUE;
}
}
}
(*RunningPrivileges)->PrivilegeCount = CurrentPrivilegeCount;
return Status;
}
NTSTATUS
LsapRtlRemovePrivileges(
IN OUT PPRIVILEGE_SET ExistingPrivileges,
IN PPRIVILEGE_SET PrivilegesToRemove
)
/*++
Routine Description:
This function removes privileges in a privilege set. The existing
privilege set is unaltered, a new privilege set being generated.
WARNING: Privileges within each privilege set must all be distinct, that
is, there must not be two privileges in the same set having the same LUID.
Arguments:
ExistingPrivileges - Pointer to existing privilege set
PrivilegesToRemove - Pointer to privilege set specifying privileges to
be removed. The privilege attributes are ignored. Privileges
in the PrivilegesToRemove set that are not present in the
ExistingPrivileges set will be ignored.
UpdatedPrivileges - Pointer to buffer that will receive the updated
privilege set. Care must be taken to ensure that UpdatedPrivileges
occupies memory disjoint from that occupied by ExistingPrivileges
and PrivilegesToChange.
UpdatedPrivilegesSize - Pointer to variable that contains a size.
On input, the size is the size of the UpdatedPrivileges buffer
(if any). On output, the size is the size needed/used for the
updated privilege set. If the updated privilege set will be
NULL, 0 is returned.
Return Value:
NTSTATUS - Standard Nt Result Code
- STATUS_INVALID_PARAMETER - Invalid parameter(s)
Mandatory parameters not specified
UpdatedPrivileges buffer not specified (except on
query-only calls
- STATUS_INSUFFICIENT_RESOURCES - Ran out of memory
Environment:
User or Kernel modes.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG ExistingIndex = 0;
ULONG ExistingNew = 0;
ULONG RemoveIndex;
//
// Verify that mandatory parameters have been specified.
//
if (ExistingPrivileges == NULL ||
PrivilegesToRemove == NULL) {
return STATUS_INVALID_PARAMETER;
}
//
// Scan through the privileges in the existing privilege set. Look up
// each privilege in the list of privileges to be removed. If the
// privilege is not found there, it is to be retained, so copy it
// to the output buffer/count it.
//
for (ExistingIndex = 0, ExistingNew = 0;
ExistingIndex < ExistingPrivileges->PrivilegeCount;
ExistingIndex++)
{
//
// If the next privilege is not in the set to be deleted,
// copy it to output/count it
//
for(RemoveIndex = 0; RemoveIndex < PrivilegesToRemove->PrivilegeCount; RemoveIndex++)
{
if(LsapRtlEqualPrivileges(
&(ExistingPrivileges->Privilege[ExistingIndex]),
&(PrivilegesToRemove->Privilege[RemoveIndex])))
{
break;
}
}
if(RemoveIndex == PrivilegesToRemove->PrivilegeCount)
{
// We don't need to remove this one, so move it if necessary
if(ExistingIndex != ExistingNew)
{
ExistingPrivileges->Privilege[ExistingNew] = ExistingPrivileges->Privilege[ExistingIndex];
}
ExistingNew++;
}
}
ExistingPrivileges->PrivilegeCount = ExistingNew;
return Status;
}
PLUID_AND_ATTRIBUTES
LsapRtlGetPrivilege(
IN PLUID_AND_ATTRIBUTES Privilege,
IN PPRIVILEGE_SET Privileges
)
/*++
Routine Description:
WARNING: THIS ROUTINE IS NOT YET AVAILABLE
This function locates a privilege in a privilege set. If found,
a pointer to the privilege wihtin the set is returned, otherwise NULL
is returned.
Arguments:
Privilege - Pointer to the privilege to be looked up.
Privileges - Pointer to the privilege set to be scanned.
Return Value:
PLUID_AND_ATTRIBUTES - If the privilege is found, a pointer to its
LUID and ATTRIBUTES structure within the privilege set is returned,
otherwise NULL is returned.
Environment:
User or Kernel modes.
--*/
{
ULONG PrivilegeIndex;
for (PrivilegeIndex = 0;
PrivilegeIndex < Privileges->PrivilegeCount;
PrivilegeIndex++) {
if (LsapRtlEqualPrivileges(
Privilege,
&(Privileges->Privilege[PrivilegeIndex])
)) {
return &(Privileges->Privilege[PrivilegeIndex]);
}
}
//
// The privilege was no found. Return NULL
//
return NULL;
}