Fixed NtAdjustPrivilegeToken() and SeSinglePrivilegeCheck().

svn path=/trunk/; revision=4916
This commit is contained in:
Eric Kohl 2003-06-17 10:42:37 +00:00
parent a2be00bf0e
commit b905ce98aa
2 changed files with 265 additions and 175 deletions

View file

@ -1,4 +1,4 @@
/* $Id: priv.c,v 1.6 2003/05/31 11:10:30 ekohl Exp $ /* $Id: priv.c,v 1.7 2003/06/17 10:42:37 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -105,47 +105,48 @@ SepPrivilegeCheck (PACCESS_TOKEN Token,
ULONG PrivilegeControl, ULONG PrivilegeControl,
KPROCESSOR_MODE PreviousMode) KPROCESSOR_MODE PreviousMode)
{ {
PLUID_AND_ATTRIBUTES Current;
ULONG i; ULONG i;
ULONG j; ULONG j;
ULONG k; ULONG k;
DPRINT ("SepPrivilegeCheck() called\n");
if (PreviousMode == KernelMode) if (PreviousMode == KernelMode)
{ {
return TRUE; return TRUE;
} }
j = 0; k = 0;
if (PrivilegeCount != 0) if (PrivilegeCount > 0)
{ {
k = PrivilegeCount;
do
{
i = Token->PrivilegeCount;
Current = Token->Privileges;
for (i = 0; i < Token->PrivilegeCount; i++) for (i = 0; i < Token->PrivilegeCount; i++)
{ {
if (!(Current[i].Attributes & SE_PRIVILEGE_ENABLED) && for (j = 0; j < PrivilegeCount; j++)
Privileges[i].Luid.LowPart == Current[i].Luid.LowPart &&
Privileges[i].Luid.HighPart == Current[i].Luid.HighPart)
{ {
Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS; if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
j++; Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
break; {
DPRINT ("Found privilege\n");
DPRINT ("Privilege attributes %lx\n",
Token->Privileges[i].Attributes);
if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
{
Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
k++;
}
} }
} }
k--;
} }
while (k > 0);
} }
if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) && if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
PrivilegeCount == j) PrivilegeCount == k)
{ {
return TRUE; return TRUE;
} }
if (j > 0 && if (k > 0 &&
!(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY)) !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
{ {
return TRUE; return TRUE;
@ -173,34 +174,38 @@ SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
{ {
*Dest = 0; *Dest = 0;
*Length = 0; *Length = 0;
return(STATUS_SUCCESS); return STATUS_SUCCESS;
} }
if (PreviousMode == 0 && d == 0)
if (PreviousMode == KernelMode && d == 0)
{ {
*Dest = Src; *Dest = Src;
return(STATUS_SUCCESS); return STATUS_SUCCESS;
} }
SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc; SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
*Length = SrcLength; *Length = SrcLength;
if (AllocatedMem == NULL) if (AllocatedMem == NULL)
{ {
NewMem = ExAllocatePool(PoolType, SrcLength); NewMem = ExAllocatePool (PoolType,
SrcLength);
*Dest = (PLUID_AND_ATTRIBUTES)NewMem; *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
if (NewMem == NULL) if (NewMem == NULL)
{ {
return(STATUS_UNSUCCESSFUL); return STATUS_UNSUCCESSFUL;
} }
} }
else else
{ {
if (SrcLength > AllocatedLength) if (SrcLength > AllocatedLength)
{ {
return(STATUS_UNSUCCESSFUL); return STATUS_UNSUCCESSFUL;
} }
*Dest = AllocatedMem; *Dest = AllocatedMem;
} }
memmove (*Dest, Src, SrcLength); memmove (*Dest, Src, SrcLength);
return(STATUS_SUCCESS);
return STATUS_SUCCESS;
} }
@ -218,13 +223,12 @@ NtPrivilegeCheck(IN HANDLE ClientToken,
IN PPRIVILEGE_SET RequiredPrivileges, IN PPRIVILEGE_SET RequiredPrivileges,
IN PBOOLEAN Result) IN PBOOLEAN Result)
{ {
NTSTATUS Status; PLUID_AND_ATTRIBUTES Privilege;
PACCESS_TOKEN Token; PACCESS_TOKEN Token;
ULONG PrivilegeCount; ULONG PrivilegeCount;
BOOLEAN TResult;
ULONG PrivilegeControl; ULONG PrivilegeControl;
PLUID_AND_ATTRIBUTES Privilege;
ULONG Length; ULONG Length;
NTSTATUS Status;
Status = ObReferenceObjectByHandle (ClientToken, Status = ObReferenceObjectByHandle (ClientToken,
0, 0,
@ -234,14 +238,16 @@ NtPrivilegeCheck(IN HANDLE ClientToken,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return Status;
} }
if (Token->TokenType == TokenImpersonation && if (Token->TokenType == TokenImpersonation &&
Token->ImpersonationLevel < SecurityAnonymous) Token->ImpersonationLevel < SecurityAnonymous)
{ {
ObDereferenceObject (Token); ObDereferenceObject (Token);
return(STATUS_UNSUCCESSFUL); return STATUS_UNSUCCESSFUL;
} }
PrivilegeCount = RequiredPrivileges->PrivilegeCount; PrivilegeCount = RequiredPrivileges->PrivilegeCount;
PrivilegeControl = RequiredPrivileges->Control; PrivilegeControl = RequiredPrivileges->Control;
Privilege = 0; Privilege = 0;
@ -257,17 +263,24 @@ NtPrivilegeCheck(IN HANDLE ClientToken,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ObDereferenceObject (Token); ObDereferenceObject (Token);
return(STATUS_UNSUCCESSFUL); return STATUS_UNSUCCESSFUL;
} }
TResult = SepPrivilegeCheck(Token,
*Result = SepPrivilegeCheck (Token,
Privilege, Privilege,
PrivilegeCount, PrivilegeCount,
PrivilegeControl, PrivilegeControl,
UserMode); UserMode);
memmove(RequiredPrivileges->Privilege, Privilege, Length);
*Result = TResult; memmove (RequiredPrivileges->Privilege,
SeReleaseLuidAndAttributesArray(Privilege, UserMode, 1); Privilege,
return(STATUS_SUCCESS); Length);
SeReleaseLuidAndAttributesArray (Privilege,
UserMode,
1);
return STATUS_SUCCESS;
} }
@ -287,15 +300,15 @@ SePrivilegeCheck(PPRIVILEGE_SET Privileges,
Token = SubjectContext->ClientToken; Token = SubjectContext->ClientToken;
if (SubjectContext->ImpersonationLevel < 2) if (SubjectContext->ImpersonationLevel < 2)
{ {
return(FALSE); return FALSE;
} }
} }
return(SepPrivilegeCheck(Token, return SepPrivilegeCheck (Token,
Privileges->Privilege, Privileges->Privilege,
Privileges->PrivilegeCount, Privileges->PrivilegeCount,
Privileges->Control, Privileges->Control,
PreviousMode)); PreviousMode);
} }
@ -304,30 +317,32 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
IN KPROCESSOR_MODE PreviousMode) IN KPROCESSOR_MODE PreviousMode)
{ {
SECURITY_SUBJECT_CONTEXT SubjectContext; SECURITY_SUBJECT_CONTEXT SubjectContext;
BOOLEAN r;
PRIVILEGE_SET Priv; PRIVILEGE_SET Priv;
BOOLEAN Result;
SeCaptureSubjectContext (&SubjectContext); SeCaptureSubjectContext (&SubjectContext);
Priv.PrivilegeCount = 1; Priv.PrivilegeCount = 1;
Priv.Control = 1; Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
Priv.Privilege[0].Luid = PrivilegeValue; Priv.Privilege[0].Luid = PrivilegeValue;
Priv.Privilege[0].Attributes = 0; Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
r = SePrivilegeCheck(&Priv, Result = SePrivilegeCheck (&Priv,
&SubjectContext, &SubjectContext,
PreviousMode); PreviousMode);
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
#if 0 #if 0
SePrivilegeServiceAuditAlarm(0, SePrivilegedServiceAuditAlarm (0,
&SubjectContext, &SubjectContext,
&PrivilegeValue); &PrivilegeValue);
#endif #endif
} }
SeReleaseSubjectContext (&SubjectContext); SeReleaseSubjectContext (&SubjectContext);
return(r);
return Result;
} }
/* EOF */ /* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: token.c,v 1.24 2003/06/07 12:23:14 chorns Exp $ /* $Id: token.c,v 1.25 2003/06/17 10:42:37 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -883,14 +883,17 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
IN BOOLEAN DisableAllPrivileges, IN BOOLEAN DisableAllPrivileges,
IN PTOKEN_PRIVILEGES NewState, IN PTOKEN_PRIVILEGES NewState,
IN ULONG BufferLength, IN ULONG BufferLength,
OUT PTOKEN_PRIVILEGES PreviousState, OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
OUT PULONG ReturnLength) OUT PULONG ReturnLength OPTIONAL)
{ {
PLUID_AND_ATTRIBUTES Privileges; // PLUID_AND_ATTRIBUTES Privileges;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode;
ULONG PrivilegeCount; // ULONG PrivilegeCount;
PACCESS_TOKEN Token; PACCESS_TOKEN Token;
ULONG Length; // ULONG Length;
ULONG i;
ULONG j;
ULONG k;
#if 0 #if 0
ULONG a; ULONG a;
ULONG b; ULONG b;
@ -898,19 +901,19 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
#endif #endif
NTSTATUS Status; NTSTATUS Status;
DPRINT1("NtAdjustPrivilegesToken() called\n"); DPRINT ("NtAdjustPrivilegesToken() called\n");
PrivilegeCount = NewState->PrivilegeCount; // PrivilegeCount = NewState->PrivilegeCount;
PreviousMode = KeGetPreviousMode (); PreviousMode = KeGetPreviousMode ();
SeCaptureLuidAndAttributesArray(NewState->Privileges, // SeCaptureLuidAndAttributesArray(NewState->Privileges,
PrivilegeCount, // PrivilegeCount,
PreviousMode, // PreviousMode,
NULL, // NULL,
0, // 0,
NonPagedPool, // NonPagedPool,
1, // 1,
&Privileges, // &Privileges,
&Length); // &Length);
Status = ObReferenceObjectByHandle (TokenHandle, Status = ObReferenceObjectByHandle (TokenHandle,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
@ -921,10 +924,10 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1 ("Failed to reference token (Status %lx)\n", Status); DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
SeReleaseLuidAndAttributesArray(Privileges, // SeReleaseLuidAndAttributesArray(Privileges,
PreviousMode, // PreviousMode,
0); // 0);
return(Status); return Status;
} }
@ -940,13 +943,85 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
&c); &c);
#endif #endif
k = 0;
if (DisableAllPrivileges == TRUE)
{
for (i = 0; i < Token->PrivilegeCount; i++)
{
if (Token->Privileges[i].Attributes != 0)
{
DPRINT ("Attributes differ\n");
/* Save current privilege */
if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
{
PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
k++;
}
/* Update current privlege */
Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
}
}
}
else
{
for (i = 0; i < Token->PrivilegeCount; i++)
{
for (j = 0; j < NewState->PrivilegeCount; j++)
{
if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
{
DPRINT ("Found privilege\n");
if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
(NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
{
DPRINT ("Attributes differ\n");
DPRINT ("Current attributes %lx desired attributes %lx\n",
Token->Privileges[i].Attributes,
NewState->Privileges[j].Attributes);
/* Save current privilege */
if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
{
PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
k++;
}
/* Update current privlege */
Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
Token->Privileges[i].Attributes |=
(NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
DPRINT ("New attributes %lx\n",
Token->Privileges[i].Attributes);
}
}
}
}
}
if (ReturnLength != NULL)
{
*ReturnLength = sizeof(TOKEN_PRIVILEGES) +
(sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
}
ObDereferenceObject (Token); ObDereferenceObject (Token);
SeReleaseLuidAndAttributesArray(Privileges, // SeReleaseLuidAndAttributesArray(Privileges,
PreviousMode, // PreviousMode,
0); // 0);
DPRINT1("NtAdjustPrivilegesToken() done\n"); DPRINT ("NtAdjustPrivilegesToken() done\n");
if (k < NewState->PrivilegeCount)
{
return STATUS_NOT_ALL_ASSIGNED;
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }