Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpriv.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/se/priv.c 00005 * PURPOSE: Security manager 00006 * 00007 * PROGRAMMERS: No programmer listed. 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 #if defined (ALLOC_PRAGMA) 00017 #pragma alloc_text(INIT, SepInitPrivileges) 00018 #endif 00019 00020 /* GLOBALS ********************************************************************/ 00021 00022 LUID SeCreateTokenPrivilege; 00023 LUID SeAssignPrimaryTokenPrivilege; 00024 LUID SeLockMemoryPrivilege; 00025 LUID SeIncreaseQuotaPrivilege; 00026 LUID SeUnsolicitedInputPrivilege; 00027 LUID SeTcbPrivilege; 00028 LUID SeSecurityPrivilege; 00029 LUID SeTakeOwnershipPrivilege; 00030 LUID SeLoadDriverPrivilege; 00031 LUID SeCreatePagefilePrivilege; 00032 LUID SeIncreaseBasePriorityPrivilege; 00033 LUID SeSystemProfilePrivilege; 00034 LUID SeSystemtimePrivilege; 00035 LUID SeProfileSingleProcessPrivilege; 00036 LUID SeCreatePermanentPrivilege; 00037 LUID SeBackupPrivilege; 00038 LUID SeRestorePrivilege; 00039 LUID SeShutdownPrivilege; 00040 LUID SeDebugPrivilege; 00041 LUID SeAuditPrivilege; 00042 LUID SeSystemEnvironmentPrivilege; 00043 LUID SeChangeNotifyPrivilege; 00044 LUID SeRemoteShutdownPrivilege; 00045 LUID SeUndockPrivilege; 00046 LUID SeSyncAgentPrivilege; 00047 LUID SeEnableDelegationPrivilege; 00048 00049 /* PRIVATE FUNCTIONS **********************************************************/ 00050 00051 VOID 00052 INIT_FUNCTION 00053 NTAPI 00054 SepInitPrivileges(VOID) 00055 { 00056 SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE; 00057 SeCreateTokenPrivilege.HighPart = 0; 00058 SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE; 00059 SeAssignPrimaryTokenPrivilege.HighPart = 0; 00060 SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE; 00061 SeLockMemoryPrivilege.HighPart = 0; 00062 SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE; 00063 SeIncreaseQuotaPrivilege.HighPart = 0; 00064 SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE; 00065 SeUnsolicitedInputPrivilege.HighPart = 0; 00066 SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE; 00067 SeTcbPrivilege.HighPart = 0; 00068 SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE; 00069 SeSecurityPrivilege.HighPart = 0; 00070 SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; 00071 SeTakeOwnershipPrivilege.HighPart = 0; 00072 SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE; 00073 SeLoadDriverPrivilege.HighPart = 0; 00074 SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE; 00075 SeSystemProfilePrivilege.HighPart = 0; 00076 SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE; 00077 SeSystemtimePrivilege.HighPart = 0; 00078 SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE; 00079 SeProfileSingleProcessPrivilege.HighPart = 0; 00080 SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE; 00081 SeIncreaseBasePriorityPrivilege.HighPart = 0; 00082 SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE; 00083 SeCreatePagefilePrivilege.HighPart = 0; 00084 SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE; 00085 SeCreatePermanentPrivilege.HighPart = 0; 00086 SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE; 00087 SeBackupPrivilege.HighPart = 0; 00088 SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE; 00089 SeRestorePrivilege.HighPart = 0; 00090 SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE; 00091 SeShutdownPrivilege.HighPart = 0; 00092 SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE; 00093 SeDebugPrivilege.HighPart = 0; 00094 SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE; 00095 SeAuditPrivilege.HighPart = 0; 00096 SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE; 00097 SeSystemEnvironmentPrivilege.HighPart = 0; 00098 SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE; 00099 SeChangeNotifyPrivilege.HighPart = 0; 00100 SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE; 00101 SeRemoteShutdownPrivilege.HighPart = 0; 00102 SeUndockPrivilege.LowPart = SE_UNDOCK_PRIVILEGE; 00103 SeUndockPrivilege.HighPart = 0; 00104 SeSyncAgentPrivilege.LowPart = SE_SYNC_AGENT_PRIVILEGE; 00105 SeSyncAgentPrivilege.HighPart = 0; 00106 SeEnableDelegationPrivilege.LowPart = SE_ENABLE_DELEGATION_PRIVILEGE; 00107 SeEnableDelegationPrivilege.HighPart = 0; 00108 } 00109 00110 00111 BOOLEAN 00112 NTAPI 00113 SepPrivilegeCheck(PTOKEN Token, 00114 PLUID_AND_ATTRIBUTES Privileges, 00115 ULONG PrivilegeCount, 00116 ULONG PrivilegeControl, 00117 KPROCESSOR_MODE PreviousMode) 00118 { 00119 ULONG i; 00120 ULONG j; 00121 ULONG Required; 00122 00123 DPRINT("SepPrivilegeCheck() called\n"); 00124 00125 PAGED_CODE(); 00126 00127 if (PreviousMode == KernelMode) 00128 return TRUE; 00129 00130 /* Get the number of privileges that are required to match */ 00131 Required = (PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) ? PrivilegeCount : 1; 00132 00133 /* Loop all requested privileges until we found the required ones */ 00134 for (i = 0; i < PrivilegeCount && Required > 0; i++) 00135 { 00136 /* Loop the privileges of the token */ 00137 for (j = 0; j < Token->PrivilegeCount; j++) 00138 { 00139 /* Check if the LUIDs match */ 00140 if (Token->Privileges[j].Luid.LowPart == Privileges[i].Luid.LowPart && 00141 Token->Privileges[j].Luid.HighPart == Privileges[i].Luid.HighPart) 00142 { 00143 DPRINT("Found privilege. Attributes: %lx\n", 00144 Token->Privileges[j].Attributes); 00145 00146 /* Check if the privilege is enabled */ 00147 if (Token->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED) 00148 { 00149 Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS; 00150 Required--; 00151 } 00152 00153 /* Leave the inner loop */ 00154 break; 00155 } 00156 } 00157 } 00158 00159 /* Return whether we found all required privileges */ 00160 return (Required == 0); 00161 } 00162 00163 NTSTATUS 00164 NTAPI 00165 SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, 00166 ULONG PrivilegeCount, 00167 KPROCESSOR_MODE PreviousMode, 00168 PLUID_AND_ATTRIBUTES AllocatedMem, 00169 ULONG AllocatedLength, 00170 POOL_TYPE PoolType, 00171 BOOLEAN CaptureIfKernel, 00172 PLUID_AND_ATTRIBUTES *Dest, 00173 PULONG Length) 00174 { 00175 ULONG BufferSize; 00176 NTSTATUS Status = STATUS_SUCCESS; 00177 00178 PAGED_CODE(); 00179 00180 if (PrivilegeCount == 0) 00181 { 00182 *Dest = 0; 00183 *Length = 0; 00184 return STATUS_SUCCESS; 00185 } 00186 00187 if (PreviousMode == KernelMode && !CaptureIfKernel) 00188 { 00189 *Dest = Src; 00190 return STATUS_SUCCESS; 00191 } 00192 00193 /* FIXME - check PrivilegeCount for a valid number so we don't 00194 cause an integer overflow or exhaust system resources! */ 00195 00196 BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); 00197 *Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */ 00198 00199 /* probe the buffer */ 00200 if (PreviousMode != KernelMode) 00201 { 00202 _SEH2_TRY 00203 { 00204 ProbeForRead(Src, 00205 BufferSize, 00206 sizeof(ULONG)); 00207 } 00208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00209 { 00210 /* Return the exception code */ 00211 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00212 } 00213 _SEH2_END; 00214 } 00215 00216 /* allocate enough memory or check if the provided buffer is 00217 large enough to hold the array */ 00218 if (AllocatedMem != NULL) 00219 { 00220 if (AllocatedLength < BufferSize) 00221 { 00222 return STATUS_BUFFER_TOO_SMALL; 00223 } 00224 00225 *Dest = AllocatedMem; 00226 } 00227 else 00228 { 00229 *Dest = ExAllocatePool(PoolType, 00230 BufferSize); 00231 if (*Dest == NULL) 00232 { 00233 return STATUS_INSUFFICIENT_RESOURCES; 00234 } 00235 } 00236 00237 /* copy the array to the buffer */ 00238 _SEH2_TRY 00239 { 00240 RtlCopyMemory(*Dest, 00241 Src, 00242 BufferSize); 00243 } 00244 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00245 { 00246 Status = _SEH2_GetExceptionCode(); 00247 } 00248 _SEH2_END; 00249 00250 if (!NT_SUCCESS(Status) && AllocatedMem == NULL) 00251 { 00252 ExFreePool(*Dest); 00253 } 00254 00255 return Status; 00256 } 00257 00258 VOID 00259 NTAPI 00260 SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, 00261 KPROCESSOR_MODE PreviousMode, 00262 BOOLEAN CaptureIfKernel) 00263 { 00264 PAGED_CODE(); 00265 00266 if (Privilege != NULL && 00267 (PreviousMode != KernelMode || CaptureIfKernel)) 00268 { 00269 ExFreePool(Privilege); 00270 } 00271 } 00272 00273 /* PUBLIC FUNCTIONS ***********************************************************/ 00274 00275 /* 00276 * @implemented 00277 */ 00278 NTSTATUS 00279 NTAPI 00280 SeAppendPrivileges(IN OUT PACCESS_STATE AccessState, 00281 IN PPRIVILEGE_SET Privileges) 00282 { 00283 PAUX_ACCESS_DATA AuxData; 00284 ULONG OldPrivilegeSetSize; 00285 ULONG NewPrivilegeSetSize; 00286 PPRIVILEGE_SET PrivilegeSet; 00287 00288 PAGED_CODE(); 00289 00290 /* Get the Auxiliary Data */ 00291 AuxData = AccessState->AuxData; 00292 00293 /* Calculate the size of the old privilege set */ 00294 OldPrivilegeSetSize = sizeof(PRIVILEGE_SET) + 00295 (AuxData->PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); 00296 00297 if (AuxData->PrivilegeSet->PrivilegeCount + 00298 Privileges->PrivilegeCount > INITIAL_PRIVILEGE_COUNT) 00299 { 00300 /* Calculate the size of the new privilege set */ 00301 NewPrivilegeSetSize = OldPrivilegeSetSize + 00302 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); 00303 00304 /* Allocate a new privilege set */ 00305 PrivilegeSet = ExAllocatePool(PagedPool, NewPrivilegeSetSize); 00306 if (PrivilegeSet == NULL) 00307 return STATUS_INSUFFICIENT_RESOURCES; 00308 00309 /* Copy original privileges from the acess state */ 00310 RtlCopyMemory(PrivilegeSet, 00311 AuxData->PrivilegeSet, 00312 OldPrivilegeSetSize); 00313 00314 /* Append privileges from the privilege set*/ 00315 RtlCopyMemory((PVOID)((ULONG_PTR)PrivilegeSet + OldPrivilegeSetSize), 00316 (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)), 00317 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 00318 00319 /* Adjust the number of privileges in the new privilege set */ 00320 PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount; 00321 00322 /* Free the old privilege set if it was allocated */ 00323 if (AccessState->PrivilegesAllocated == TRUE) 00324 ExFreePool(AuxData->PrivilegeSet); 00325 00326 /* Now we are using an allocated privilege set */ 00327 AccessState->PrivilegesAllocated = TRUE; 00328 00329 /* Assign the new privileges to the access state */ 00330 AuxData->PrivilegeSet = PrivilegeSet; 00331 } 00332 else 00333 { 00334 /* Append privileges */ 00335 RtlCopyMemory((PVOID)((ULONG_PTR)AuxData->PrivilegeSet + OldPrivilegeSetSize), 00336 (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)), 00337 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 00338 00339 /* Adjust the number of privileges in the target privilege set */ 00340 AuxData->PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount; 00341 } 00342 00343 return STATUS_SUCCESS; 00344 } 00345 00346 /* 00347 * @implemented 00348 */ 00349 VOID 00350 NTAPI 00351 SeFreePrivileges(IN PPRIVILEGE_SET Privileges) 00352 { 00353 PAGED_CODE(); 00354 ExFreePool(Privileges); 00355 } 00356 00357 /* 00358 * @implemented 00359 */ 00360 BOOLEAN 00361 NTAPI 00362 SePrivilegeCheck(PPRIVILEGE_SET Privileges, 00363 PSECURITY_SUBJECT_CONTEXT SubjectContext, 00364 KPROCESSOR_MODE PreviousMode) 00365 { 00366 PACCESS_TOKEN Token = NULL; 00367 00368 PAGED_CODE(); 00369 00370 if (SubjectContext->ClientToken == NULL) 00371 { 00372 Token = SubjectContext->PrimaryToken; 00373 } 00374 else 00375 { 00376 Token = SubjectContext->ClientToken; 00377 if (SubjectContext->ImpersonationLevel < 2) 00378 { 00379 return FALSE; 00380 } 00381 } 00382 00383 return SepPrivilegeCheck(Token, 00384 Privileges->Privilege, 00385 Privileges->PrivilegeCount, 00386 Privileges->Control, 00387 PreviousMode); 00388 } 00389 00390 /* 00391 * @implemented 00392 */ 00393 BOOLEAN 00394 NTAPI 00395 SeSinglePrivilegeCheck(IN LUID PrivilegeValue, 00396 IN KPROCESSOR_MODE PreviousMode) 00397 { 00398 SECURITY_SUBJECT_CONTEXT SubjectContext; 00399 PRIVILEGE_SET Priv; 00400 BOOLEAN Result; 00401 00402 PAGED_CODE(); 00403 00404 SeCaptureSubjectContext(&SubjectContext); 00405 00406 Priv.PrivilegeCount = 1; 00407 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY; 00408 Priv.Privilege[0].Luid = PrivilegeValue; 00409 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 00410 00411 Result = SePrivilegeCheck(&Priv, 00412 &SubjectContext, 00413 PreviousMode); 00414 00415 if (PreviousMode != KernelMode) 00416 { 00417 #if 0 00418 SePrivilegedServiceAuditAlarm(0, 00419 &SubjectContext, 00420 &PrivilegeValue); 00421 #endif 00422 } 00423 00424 SeReleaseSubjectContext(&SubjectContext); 00425 00426 return Result; 00427 } 00428 00429 BOOLEAN 00430 NTAPI 00431 SeCheckPrivilegedObject(IN LUID PrivilegeValue, 00432 IN HANDLE ObjectHandle, 00433 IN ACCESS_MASK DesiredAccess, 00434 IN KPROCESSOR_MODE PreviousMode) 00435 { 00436 SECURITY_SUBJECT_CONTEXT SubjectContext; 00437 PRIVILEGE_SET Priv; 00438 BOOLEAN Result; 00439 00440 PAGED_CODE(); 00441 00442 SeCaptureSubjectContext(&SubjectContext); 00443 00444 Priv.PrivilegeCount = 1; 00445 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY; 00446 Priv.Privilege[0].Luid = PrivilegeValue; 00447 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 00448 00449 Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode); 00450 if (PreviousMode != KernelMode) 00451 { 00452 #if 0 00453 SePrivilegeObjectAuditAlarm(ObjectHandle, 00454 &SubjectContext, 00455 DesiredAccess, 00456 &PrivilegeValue, 00457 Result, 00458 PreviousMode); 00459 #endif 00460 } 00461 00462 SeReleaseSubjectContext(&SubjectContext); 00463 00464 return Result; 00465 } 00466 00467 /* SYSTEM CALLS ***************************************************************/ 00468 00469 NTSTATUS 00470 NTAPI 00471 NtPrivilegeCheck(IN HANDLE ClientToken, 00472 IN PPRIVILEGE_SET RequiredPrivileges, 00473 OUT PBOOLEAN Result) 00474 { 00475 PLUID_AND_ATTRIBUTES Privileges; 00476 PTOKEN Token; 00477 ULONG PrivilegeCount = 0; 00478 ULONG PrivilegeControl = 0; 00479 ULONG Length; 00480 BOOLEAN CheckResult; 00481 KPROCESSOR_MODE PreviousMode; 00482 NTSTATUS Status; 00483 00484 PAGED_CODE(); 00485 00486 PreviousMode = KeGetPreviousMode(); 00487 00488 /* probe the buffers */ 00489 if (PreviousMode != KernelMode) 00490 { 00491 _SEH2_TRY 00492 { 00493 ProbeForWrite(RequiredPrivileges, 00494 FIELD_OFFSET(PRIVILEGE_SET, 00495 Privilege), 00496 sizeof(ULONG)); 00497 00498 PrivilegeCount = RequiredPrivileges->PrivilegeCount; 00499 PrivilegeControl = RequiredPrivileges->Control; 00500 00501 /* Check PrivilegeCount to avoid an integer overflow! */ 00502 if (FIELD_OFFSET(PRIVILEGE_SET, 00503 Privilege[PrivilegeCount]) / 00504 sizeof(RequiredPrivileges->Privilege[0]) != PrivilegeCount) 00505 { 00506 _SEH2_YIELD(return STATUS_INVALID_PARAMETER); 00507 } 00508 00509 /* probe all of the array */ 00510 ProbeForWrite(RequiredPrivileges, 00511 FIELD_OFFSET(PRIVILEGE_SET, 00512 Privilege[PrivilegeCount]), 00513 sizeof(ULONG)); 00514 00515 ProbeForWriteBoolean(Result); 00516 } 00517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00518 { 00519 /* Return the exception code */ 00520 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00521 } 00522 _SEH2_END; 00523 } 00524 else 00525 { 00526 PrivilegeCount = RequiredPrivileges->PrivilegeCount; 00527 PrivilegeControl = RequiredPrivileges->Control; 00528 } 00529 00530 /* reference the token and make sure we're 00531 not doing an anonymous impersonation */ 00532 Status = ObReferenceObjectByHandle(ClientToken, 00533 TOKEN_QUERY, 00534 SeTokenObjectType, 00535 PreviousMode, 00536 (PVOID*)&Token, 00537 NULL); 00538 if (!NT_SUCCESS(Status)) 00539 { 00540 return Status; 00541 } 00542 00543 if (Token->TokenType == TokenImpersonation && 00544 Token->ImpersonationLevel < SecurityIdentification) 00545 { 00546 ObDereferenceObject(Token); 00547 return STATUS_BAD_IMPERSONATION_LEVEL; 00548 } 00549 00550 /* capture the privileges */ 00551 Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege, 00552 PrivilegeCount, 00553 PreviousMode, 00554 NULL, 00555 0, 00556 PagedPool, 00557 TRUE, 00558 &Privileges, 00559 &Length); 00560 if (!NT_SUCCESS(Status)) 00561 { 00562 ObDereferenceObject (Token); 00563 return Status; 00564 } 00565 00566 CheckResult = SepPrivilegeCheck(Token, 00567 Privileges, 00568 PrivilegeCount, 00569 PrivilegeControl, 00570 PreviousMode); 00571 00572 ObDereferenceObject(Token); 00573 00574 /* return the array */ 00575 _SEH2_TRY 00576 { 00577 RtlCopyMemory(RequiredPrivileges->Privilege, 00578 Privileges, 00579 PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 00580 *Result = CheckResult; 00581 Status = STATUS_SUCCESS; 00582 } 00583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00584 { 00585 Status = _SEH2_GetExceptionCode(); 00586 } 00587 _SEH2_END; 00588 00589 SeReleaseLuidAndAttributesArray(Privileges, 00590 PreviousMode, 00591 TRUE); 00592 00593 return Status; 00594 } 00595 00596 /* EOF */ Generated on Fri May 25 2012 04:36:06 for ReactOS by
1.7.6.1
|