1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Security manager infrastructure 5 * COPYRIGHT: Copyright Timo Kreuzer <timo.kreuzer@reactos.org> 6 * Copyright Eric Kohl 7 * Copyright Aleksey Bragin 8 * Copyright Alex Ionescu <alex@relsoft.net> 9 */ 10 11 /* INCLUDES *******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS ********************************************************************/ 18 19 PTOKEN SeAnonymousLogonToken = NULL; 20 PTOKEN SeAnonymousLogonTokenNoEveryone = NULL; 21 PSE_EXPORTS SeExports = NULL; 22 SE_EXPORTS SepExports; 23 ULONG SidInTokenCalls = 0; 24 25 extern ULONG ExpInitializationPhase; 26 extern ERESOURCE SepSubjectContextLock; 27 28 /* PRIVATE FUNCTIONS **********************************************************/ 29 30 /** 31 * @brief 32 * Initializes all the security exports upon initialization phase of 33 * the module. 34 * 35 * @return 36 * Returns TRUE. 37 */ 38 static 39 CODE_SEG("INIT") 40 BOOLEAN 41 SepInitExports(VOID) 42 { 43 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege; 44 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege; 45 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege; 46 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege; 47 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege; 48 SepExports.SeTcbPrivilege = SeTcbPrivilege; 49 SepExports.SeSecurityPrivilege = SeSecurityPrivilege; 50 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege; 51 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege; 52 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege; 53 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege; 54 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege; 55 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege; 56 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege; 57 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege; 58 SepExports.SeBackupPrivilege = SeBackupPrivilege; 59 SepExports.SeRestorePrivilege = SeRestorePrivilege; 60 SepExports.SeShutdownPrivilege = SeShutdownPrivilege; 61 SepExports.SeDebugPrivilege = SeDebugPrivilege; 62 SepExports.SeAuditPrivilege = SeAuditPrivilege; 63 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege; 64 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege; 65 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege; 66 67 SepExports.SeNullSid = SeNullSid; 68 SepExports.SeWorldSid = SeWorldSid; 69 SepExports.SeLocalSid = SeLocalSid; 70 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid; 71 SepExports.SeCreatorGroupSid = SeCreatorGroupSid; 72 SepExports.SeNtAuthoritySid = SeNtAuthoritySid; 73 SepExports.SeDialupSid = SeDialupSid; 74 SepExports.SeNetworkSid = SeNetworkSid; 75 SepExports.SeBatchSid = SeBatchSid; 76 SepExports.SeInteractiveSid = SeInteractiveSid; 77 SepExports.SeLocalSystemSid = SeLocalSystemSid; 78 SepExports.SeAliasAdminsSid = SeAliasAdminsSid; 79 SepExports.SeAliasUsersSid = SeAliasUsersSid; 80 SepExports.SeAliasGuestsSid = SeAliasGuestsSid; 81 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid; 82 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid; 83 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid; 84 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid; 85 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid; 86 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid; 87 SepExports.SeRestrictedSid = SeRestrictedSid; 88 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid; 89 SepExports.SeLocalServiceSid = SeLocalServiceSid; 90 SepExports.SeNetworkServiceSid = SeNetworkServiceSid; 91 92 SepExports.SeUndockPrivilege = SeUndockPrivilege; 93 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege; 94 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege; 95 SepExports.SeManageVolumePrivilege = SeManageVolumePrivilege; 96 SepExports.SeImpersonatePrivilege = SeImpersonatePrivilege; 97 SepExports.SeCreateGlobalPrivilege = SeCreateGlobalPrivilege; 98 99 SeExports = &SepExports; 100 return TRUE; 101 } 102 103 /** 104 * @brief 105 * Handles the phase 0 procedure of the SRM initialization. 106 * 107 * @return 108 * Returns TRUE if the phase 0 initialization has succeeded and that 109 * we can proceed further with next initialization phase, FALSE 110 * otherwise. 111 */ 112 CODE_SEG("INIT") 113 BOOLEAN 114 NTAPI 115 SepInitializationPhase0(VOID) 116 { 117 PAGED_CODE(); 118 119 if (!ExLuidInitialization()) return FALSE; 120 if (!SepInitSecurityIDs()) return FALSE; 121 if (!SepInitDACLs()) return FALSE; 122 if (!SepInitSDs()) return FALSE; 123 SepInitPrivileges(); 124 if (!SepInitExports()) return FALSE; 125 126 /* Initialize the subject context lock */ 127 ExInitializeResource(&SepSubjectContextLock); 128 129 /* Initialize token objects */ 130 SepInitializeTokenImplementation(); 131 132 /* Initialize logon sessions */ 133 if (!SeRmInitPhase0()) return FALSE; 134 135 /* Clear impersonation info for the idle thread */ 136 PsGetCurrentThread()->ImpersonationInfo = NULL; 137 PspClearCrossThreadFlag(PsGetCurrentThread(), 138 CT_ACTIVE_IMPERSONATION_INFO_BIT); 139 140 /* Initialize the boot token */ 141 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL); 142 ObInitializeFastReference(&PsGetCurrentProcess()->Token, 143 SepCreateSystemProcessToken()); 144 145 /* Initialise the anonymous logon tokens */ 146 SeAnonymousLogonToken = SepCreateSystemAnonymousLogonToken(); 147 if (!SeAnonymousLogonToken) 148 return FALSE; 149 150 SeAnonymousLogonTokenNoEveryone = SepCreateSystemAnonymousLogonTokenNoEveryone(); 151 if (!SeAnonymousLogonTokenNoEveryone) 152 return FALSE; 153 154 return TRUE; 155 } 156 157 /** 158 * @brief 159 * Handles the phase 1 procedure of the SRM initialization. 160 * 161 * @return 162 * Returns TRUE if the phase 1 initialization has succeeded, FALSE 163 * otherwise. 164 */ 165 CODE_SEG("INIT") 166 BOOLEAN 167 NTAPI 168 SepInitializationPhase1(VOID) 169 { 170 OBJECT_ATTRIBUTES ObjectAttributes; 171 UNICODE_STRING Name; 172 HANDLE SecurityHandle; 173 HANDLE EventHandle; 174 NTSTATUS Status; 175 SECURITY_DESCRIPTOR SecurityDescriptor; 176 PACL Dacl; 177 ULONG DaclLength; 178 179 PAGED_CODE(); 180 181 /* Insert the system token into the tree */ 182 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value & 183 ~MAX_FAST_REFS), 184 NULL, 185 0, 186 0, 187 NULL, 188 NULL); 189 ASSERT(NT_SUCCESS(Status)); 190 191 /* Create a security descriptor for the directory */ 192 RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); 193 194 /* Setup the ACL */ 195 DaclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + 196 RtlLengthSid(SeLocalSystemSid) + 197 RtlLengthSid(SeAliasAdminsSid) + 198 RtlLengthSid(SeWorldSid); 199 Dacl = ExAllocatePoolWithTag(NonPagedPool, DaclLength, TAG_SE); 200 if (Dacl == NULL) 201 { 202 return FALSE; 203 } 204 205 Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION); 206 ASSERT(NT_SUCCESS(Status)); 207 208 /* Grant full access to SYSTEM */ 209 Status = RtlAddAccessAllowedAce(Dacl, 210 ACL_REVISION, 211 DIRECTORY_ALL_ACCESS, 212 SeLocalSystemSid); 213 ASSERT(NT_SUCCESS(Status)); 214 215 /* Allow admins to traverse and query */ 216 Status = RtlAddAccessAllowedAce(Dacl, 217 ACL_REVISION, 218 READ_CONTROL | DIRECTORY_TRAVERSE | DIRECTORY_QUERY, 219 SeAliasAdminsSid); 220 ASSERT(NT_SUCCESS(Status)); 221 222 /* Allow anyone to traverse */ 223 Status = RtlAddAccessAllowedAce(Dacl, 224 ACL_REVISION, 225 DIRECTORY_TRAVERSE, 226 SeWorldSid); 227 ASSERT(NT_SUCCESS(Status)); 228 229 /* And link ACL and SD */ 230 Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, FALSE); 231 ASSERT(NT_SUCCESS(Status)); 232 233 /* Create '\Security' directory */ 234 RtlInitUnicodeString(&Name, L"\\Security"); 235 InitializeObjectAttributes(&ObjectAttributes, 236 &Name, 237 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 238 0, 239 &SecurityDescriptor); 240 241 Status = ZwCreateDirectoryObject(&SecurityHandle, 242 DIRECTORY_ALL_ACCESS, 243 &ObjectAttributes); 244 ASSERT(NT_SUCCESS(Status)); 245 246 /* Free the DACL */ 247 ExFreePoolWithTag(Dacl, TAG_SE); 248 249 /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */ 250 RtlInitUnicodeString(&Name, L"LSA_AUTHENTICATION_INITIALIZED"); 251 InitializeObjectAttributes(&ObjectAttributes, 252 &Name, 253 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 254 SecurityHandle, 255 SePublicDefaultSd); 256 257 Status = ZwCreateEvent(&EventHandle, 258 GENERIC_WRITE, 259 &ObjectAttributes, 260 NotificationEvent, 261 FALSE); 262 ASSERT(NT_SUCCESS(Status)); 263 264 Status = ZwClose(EventHandle); 265 ASSERT(NT_SUCCESS(Status)); 266 267 Status = ZwClose(SecurityHandle); 268 ASSERT(NT_SUCCESS(Status)); 269 270 return TRUE; 271 } 272 273 /** 274 * @brief 275 * Main security manager initialization function. 276 * 277 * @return 278 * Returns a boolean value according to the phase initialization 279 * routine that handles it. If TRUE, the routine deems the initialization 280 * phase as complete, FALSE otherwise. 281 */ 282 CODE_SEG("INIT") 283 BOOLEAN 284 NTAPI 285 SeInitSystem(VOID) 286 { 287 /* Check the initialization phase */ 288 switch (ExpInitializationPhase) 289 { 290 case 0: 291 292 /* Do Phase 0 */ 293 return SepInitializationPhase0(); 294 295 case 1: 296 297 /* Do Phase 1 */ 298 return SepInitializationPhase1(); 299 300 default: 301 302 /* Don't know any other phase! Bugcheck! */ 303 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 304 0, 305 ExpInitializationPhase, 306 0, 307 0); 308 return FALSE; 309 } 310 } 311 312 /** 313 * @brief 314 * Internal function that is responsible for querying, deleting, assigning and 315 * setting a security descriptor for an object in the NT kernel. It is the default 316 * security method for objects regarding the security context of objects. 317 * 318 * @param[in] Object 319 * The object that has the default security method, which the function has been 320 * called upon. 321 * 322 * @param[in] OperationType 323 * Operation type to perform to that object. 324 * 325 * @param[in] SecurityInformation 326 * Auxiliary security information of the object. 327 * 328 * @param[in,out] SecurityDescriptor 329 * A security descriptor. This SD is used accordingly to the operation type 330 * requested by the caller. 331 * 332 * @param[in,out] ReturnLength 333 * The length size of the queried security descriptor, in bytes. 334 * 335 * @param[in,out] OldSecurityDescriptor 336 * The old SD that belonged to the object, in case we're either deleting 337 * or replacing it. 338 * 339 * @param[in] PoolType 340 * Pool type allocation for the security descriptor. 341 * 342 * @param[in] GenericMapping 343 * The generic mapping of access rights masks for the object. 344 * 345 * @return 346 * Returns STATUS_SUCCESS if the specific operation tasked has been 347 * completed. Otherwise a failure NTSTATUS code is returned. 348 */ 349 NTSTATUS 350 NTAPI 351 SeDefaultObjectMethod( 352 _In_ PVOID Object, 353 _In_ SECURITY_OPERATION_CODE OperationType, 354 _In_ PSECURITY_INFORMATION SecurityInformation, 355 _Inout_ PSECURITY_DESCRIPTOR SecurityDescriptor, 356 _Inout_opt_ PULONG ReturnLength, 357 _Inout_ PSECURITY_DESCRIPTOR *OldSecurityDescriptor, 358 _In_ POOL_TYPE PoolType, 359 _In_ PGENERIC_MAPPING GenericMapping) 360 { 361 PAGED_CODE(); 362 363 /* Select the operation type */ 364 switch (OperationType) 365 { 366 /* Setting a new descriptor */ 367 case SetSecurityDescriptor: 368 369 /* Sanity check */ 370 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool)); 371 372 /* Set the information */ 373 return ObSetSecurityDescriptorInfo(Object, 374 SecurityInformation, 375 SecurityDescriptor, 376 OldSecurityDescriptor, 377 PoolType, 378 GenericMapping); 379 380 case QuerySecurityDescriptor: 381 382 /* Query the information */ 383 return ObQuerySecurityDescriptorInfo(Object, 384 SecurityInformation, 385 SecurityDescriptor, 386 ReturnLength, 387 OldSecurityDescriptor); 388 389 case DeleteSecurityDescriptor: 390 391 /* De-assign it */ 392 return ObDeassignSecurity(OldSecurityDescriptor); 393 394 case AssignSecurityDescriptor: 395 396 /* Assign it */ 397 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType); 398 return STATUS_SUCCESS; 399 400 default: 401 402 /* Bug check */ 403 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0); 404 } 405 406 /* Should never reach here */ 407 ASSERT(FALSE); 408 return STATUS_SUCCESS; 409 } 410 411 /** 412 * @brief 413 * Queries the access mask from a security information context. 414 * 415 * @param[in] SecurityInformation 416 * The security information context where the access mask is to be 417 * gathered. 418 * 419 * @param[out] DesiredAccess 420 * The queried access mask right. 421 * 422 * @return 423 * Nothing. 424 */ 425 VOID 426 NTAPI 427 SeQuerySecurityAccessMask( 428 _In_ SECURITY_INFORMATION SecurityInformation, 429 _Out_ PACCESS_MASK DesiredAccess) 430 { 431 *DesiredAccess = 0; 432 433 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | 434 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)) 435 { 436 *DesiredAccess |= READ_CONTROL; 437 } 438 439 if (SecurityInformation & SACL_SECURITY_INFORMATION) 440 { 441 *DesiredAccess |= ACCESS_SYSTEM_SECURITY; 442 } 443 } 444 445 /** 446 * @brief 447 * Sets the access mask for a security information context. 448 * 449 * @param[in] SecurityInformation 450 * The security information context to apply a new access right. 451 * 452 * @param[out] DesiredAccess 453 * The returned access mask right. 454 * 455 * @return 456 * Nothing. 457 */ 458 VOID 459 NTAPI 460 SeSetSecurityAccessMask( 461 _In_ SECURITY_INFORMATION SecurityInformation, 462 _Out_ PACCESS_MASK DesiredAccess) 463 { 464 *DesiredAccess = 0; 465 466 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) 467 { 468 *DesiredAccess |= WRITE_OWNER; 469 } 470 471 if (SecurityInformation & DACL_SECURITY_INFORMATION) 472 { 473 *DesiredAccess |= WRITE_DAC; 474 } 475 476 if (SecurityInformation & SACL_SECURITY_INFORMATION) 477 { 478 *DesiredAccess |= ACCESS_SYSTEM_SECURITY; 479 } 480 } 481 482 /** 483 * @unimplemented 484 * @brief 485 * Report a security event to the security manager. 486 * 487 * @param[in] Flags 488 * Flags that influence how the event should be reported. 489 * 490 * @param[in] SourceName 491 * A Unicode string that represents the source name of the event. 492 * 493 * @param[in] UserSid 494 * The SID that represents a user that initiated the reporting. 495 * 496 * @param[in] AuditParameters 497 * An array of parameters for auditing purposes. This is used 498 * for reporting the event which the security manager will take 499 * care subsequently of doing eventual security auditing. 500 * 501 * @return 502 * Returns STATUS_SUCCESS if the security event has been reported. 503 * STATUS_INVALID_PARAMETER is returned if one of the parameters 504 * do not satisfy the requirements expected by the function. 505 */ 506 NTSTATUS 507 NTAPI 508 SeReportSecurityEvent( 509 _In_ ULONG Flags, 510 _In_ PUNICODE_STRING SourceName, 511 _In_opt_ PSID UserSid, 512 _In_ PSE_ADT_PARAMETER_ARRAY AuditParameters) 513 { 514 SECURITY_SUBJECT_CONTEXT SubjectContext; 515 PTOKEN EffectiveToken; 516 PISID Sid; 517 NTSTATUS Status; 518 519 /* Validate parameters */ 520 if ((Flags != 0) || 521 (SourceName == NULL) || 522 (SourceName->Buffer == NULL) || 523 (SourceName->Length == 0) || 524 (AuditParameters == NULL) || 525 (AuditParameters->ParameterCount > SE_MAX_AUDIT_PARAMETERS - 4)) 526 { 527 return STATUS_INVALID_PARAMETER; 528 } 529 530 /* Validate the source name */ 531 Status = RtlValidateUnicodeString(0, SourceName); 532 if (!NT_SUCCESS(Status)) 533 { 534 return Status; 535 } 536 537 /* Check if we have a user SID */ 538 if (UserSid != NULL) 539 { 540 /* Validate it */ 541 if (!RtlValidSid(UserSid)) 542 { 543 return STATUS_INVALID_PARAMETER; 544 } 545 546 /* Use the user SID */ 547 Sid = UserSid; 548 } 549 else 550 { 551 /* No user SID, capture the security subject context */ 552 SeCaptureSubjectContext(&SubjectContext); 553 554 /* Extract the effective token */ 555 EffectiveToken = SubjectContext.ClientToken ? 556 SubjectContext.ClientToken : SubjectContext.PrimaryToken; 557 558 /* Use the user-and-groups SID */ 559 Sid = EffectiveToken->UserAndGroups->Sid; 560 } 561 562 UNIMPLEMENTED; 563 564 /* Check if we captured the subject context */ 565 if (Sid != UserSid) 566 { 567 /* Release it */ 568 SeReleaseSubjectContext(&SubjectContext); 569 } 570 571 /* Return success */ 572 return STATUS_SUCCESS; 573 } 574 575 /** 576 * @unimplemented 577 * @brief 578 * Sets an array of audit parameters for later security auditing use. 579 * 580 * @param[in,out] AuditParameters 581 * An array of audit parameters to be set. 582 * 583 * @param[in] Type 584 * The type of audit parameters to be set. 585 * 586 * @param[in] Index 587 * Index number that represents an instance of an audit parameters. 588 * Such index must be within the maximum range of audit parameters. 589 * 590 * @param[in] Data 591 * An arbitrary buffer data that is bounds to what kind of audit parameter 592 * type must be set. 593 * 594 * @return 595 * To be added... 596 */ 597 _Const_ 598 NTSTATUS 599 NTAPI 600 SeSetAuditParameter( 601 _Inout_ PSE_ADT_PARAMETER_ARRAY AuditParameters, 602 _In_ SE_ADT_PARAMETER_TYPE Type, 603 _In_range_(<, SE_MAX_AUDIT_PARAMETERS) ULONG Index, 604 _In_reads_(_Inexpressible_("depends on SE_ADT_PARAMETER_TYPE")) PVOID Data) 605 { 606 UNIMPLEMENTED; 607 return STATUS_SUCCESS; 608 } 609 610 /* EOF */ 611