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; for (i = 0; i < Token->PrivilegeCount; i++)
do
{ {
i = Token->PrivilegeCount; for (j = 0; j < PrivilegeCount; j++)
Current = Token->Privileges;
for (i = 0; i < Token->PrivilegeCount; i++)
{ {
if (!(Current[i].Attributes & SE_PRIVILEGE_ENABLED) && if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
Privileges[i].Luid.LowPart == Current[i].Luid.LowPart && Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
Privileges[i].Luid.HighPart == Current[i].Luid.HighPart)
{ {
Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS; DPRINT ("Found privilege\n");
j++; DPRINT ("Privilege attributes %lx\n",
break; 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;
@ -166,86 +167,91 @@ SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
PLUID_AND_ATTRIBUTES* Dest, PLUID_AND_ATTRIBUTES* Dest,
PULONG Length) PULONG Length)
{ {
PLUID_AND_ATTRIBUTES* NewMem; PLUID_AND_ATTRIBUTES* NewMem;
ULONG SrcLength; ULONG SrcLength;
if (PrivilegeCount == 0) if (PrivilegeCount == 0)
{ {
*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; {
return(STATUS_SUCCESS); *Dest = Src;
} return STATUS_SUCCESS;
SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc; }
*Length = SrcLength;
if (AllocatedMem == NULL) SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
{ *Length = SrcLength;
NewMem = ExAllocatePool(PoolType, SrcLength); if (AllocatedMem == NULL)
*Dest = (PLUID_AND_ATTRIBUTES)NewMem; {
if (NewMem == NULL) NewMem = ExAllocatePool (PoolType,
{ SrcLength);
return(STATUS_UNSUCCESSFUL); *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
} if (NewMem == NULL)
} {
else return STATUS_UNSUCCESSFUL;
{ }
if (SrcLength > AllocatedLength) }
{ else
return(STATUS_UNSUCCESSFUL); {
} if (SrcLength > AllocatedLength)
*Dest = AllocatedMem; {
} return STATUS_UNSUCCESSFUL;
memmove(*Dest, Src, SrcLength); }
return(STATUS_SUCCESS); *Dest = AllocatedMem;
}
memmove (*Dest, Src, SrcLength);
return STATUS_SUCCESS;
} }
VOID VOID
SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
KPROCESSOR_MODE PreviousMode, KPROCESSOR_MODE PreviousMode,
ULONG a) ULONG a)
{ {
ExFreePool(Privilege); ExFreePool (Privilege);
} }
NTSTATUS STDCALL NTSTATUS STDCALL
NtPrivilegeCheck(IN HANDLE ClientToken, 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; ULONG Length;
PLUID_AND_ATTRIBUTES Privilege; NTSTATUS Status;
ULONG Length;
Status = ObReferenceObjectByHandle (ClientToken,
Status = ObReferenceObjectByHandle(ClientToken,
0, 0,
SepTokenObjectType, SepTokenObjectType,
UserMode, UserMode,
(PVOID*)&Token, (PVOID*)&Token,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return Status;
} }
if (Token->TokenType == TokenImpersonation &&
Token->ImpersonationLevel < SecurityAnonymous) if (Token->TokenType == TokenImpersonation &&
{ Token->ImpersonationLevel < SecurityAnonymous)
ObDereferenceObject(Token); {
return(STATUS_UNSUCCESSFUL); ObDereferenceObject (Token);
} return STATUS_UNSUCCESSFUL;
PrivilegeCount = RequiredPrivileges->PrivilegeCount; }
PrivilegeControl = RequiredPrivileges->Control;
Privilege = 0; PrivilegeCount = RequiredPrivileges->PrivilegeCount;
Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege, PrivilegeControl = RequiredPrivileges->Control;
Privilege = 0;
Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
PrivilegeCount, PrivilegeCount,
1, 1,
0, 0,
@ -254,80 +260,89 @@ NtPrivilegeCheck(IN HANDLE ClientToken,
1, 1,
&Privilege, &Privilege,
&Length); &Length);
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;
} }
BOOLEAN STDCALL BOOLEAN STDCALL
SePrivilegeCheck(PPRIVILEGE_SET Privileges, SePrivilegeCheck (PPRIVILEGE_SET Privileges,
PSECURITY_SUBJECT_CONTEXT SubjectContext, PSECURITY_SUBJECT_CONTEXT SubjectContext,
KPROCESSOR_MODE PreviousMode) KPROCESSOR_MODE PreviousMode)
{ {
PACCESS_TOKEN Token = NULL; PACCESS_TOKEN Token = NULL;
if (SubjectContext->ClientToken == NULL) if (SubjectContext->ClientToken == NULL)
{ {
Token = SubjectContext->PrimaryToken; Token = SubjectContext->PrimaryToken;
} }
else else
{ {
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);
} }
BOOLEAN STDCALL BOOLEAN STDCALL
SeSinglePrivilegeCheck(IN LUID PrivilegeValue, 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);
return(r); SeReleaseSubjectContext (&SubjectContext);
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
@ -879,18 +879,21 @@ SepAdjustPrivileges(PACCESS_TOKEN Token,
NTSTATUS STDCALL NTSTATUS STDCALL
NtAdjustPrivilegesToken(IN HANDLE TokenHandle, 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,33 +901,33 @@ 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,
SepTokenObjectType, SepTokenObjectType,
PreviousMode, PreviousMode,
(PVOID*)&Token, (PVOID*)&Token,
NULL); NULL);
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
ObDereferenceObject(Token); k = 0;
if (DisableAllPrivileges == TRUE)
{
for (i = 0; i < Token->PrivilegeCount; i++)
{
if (Token->Privileges[i].Attributes != 0)
{
DPRINT ("Attributes differ\n");
SeReleaseLuidAndAttributesArray(Privileges, /* Save current privilege */
PreviousMode, if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
0); {
PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
k++;
}
DPRINT1("NtAdjustPrivilegesToken() done\n"); /* 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);
// SeReleaseLuidAndAttributesArray(Privileges,
// PreviousMode,
// 0);
DPRINT ("NtAdjustPrivilegesToken() done\n");
if (k < NewState->PrivilegeCount)
{
return STATUS_NOT_ALL_ASSIGNED;
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }