diff --git a/ntoskrnl/se/access.c b/ntoskrnl/se/access.c index a4f5cb0ee67..42c2ab8d1c8 100644 --- a/ntoskrnl/se/access.c +++ b/ntoskrnl/se/access.c @@ -1,11 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/access.c - * PURPOSE: Access state functions - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - - * Based on patch by Javier M. Mellid + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security access state functions support + * COPYRIGHT: Copyright Alex Ionescu */ /* INCLUDES *******************************************************************/ @@ -20,6 +17,32 @@ ERESOURCE SepSubjectContextLock; /* PRIVATE FUNCTIONS **********************************************************/ +/** + * @brief + * Checks if a SID is present in a token. + * + * @param[in] _Token + * A valid token object. + * + * @param[in] PrincipalSelfSid + * A principal self SID. + * + * @param[in] _Sid + * A regular SID. + * + * @param[in] Deny + * If set to TRUE, the caller expected that a SID in a token + * must be a deny-only SID, that is, access checks are performed + * only for deny-only ACEs of the said SID. + * + * @param[in] Restricted + * If set to TRUE, the caller expects that a SID in a token is + * restricted. + * + * @return + * Returns TRUE if the specified SID in the call is present in the token, + * FALSE otherwise. + */ BOOLEAN NTAPI SepSidInTokenEx(IN PACCESS_TOKEN _Token, @@ -106,6 +129,20 @@ SepSidInTokenEx(IN PACCESS_TOKEN _Token, return FALSE; } +/** + * @brief + * Checks if a SID is present in a token. + * + * @param[in] _Token + * A valid token object. + * + * @param[in] _Sid + * A regular SID. + * + * @return + * Returns TRUE if the specified SID in the call is present in the token, + * FALSE otherwise. + */ BOOLEAN NTAPI SepSidInToken(IN PACCESS_TOKEN _Token, @@ -115,6 +152,24 @@ SepSidInToken(IN PACCESS_TOKEN _Token, return SepSidInTokenEx(_Token, NULL, Sid, FALSE, FALSE); } +/** + * @brief + * Checks if a token belongs to the main user, being the owner. + * + * @param[in] _Token + * A valid token object. + * + * @param[in] SecurityDescriptor + * A security descriptor where the owner is to be found. + * + * @param[in] TokenLocked + * If set to TRUE, the token has been already locked and there's + * no need to lock it again. Otherwise the function will acquire + * the lock. + * + * @return + * Returns TRUE if the token belongs to a owner, FALSE otherwise. + */ BOOLEAN NTAPI SepTokenIsOwner(IN PACCESS_TOKEN _Token, @@ -146,6 +201,19 @@ SepTokenIsOwner(IN PACCESS_TOKEN _Token, return Result; } +/** + * @brief + * Retrieves token control information. + * + * @param[in] _Token + * A valid token object. + * + * @param[out] SecurityDescriptor + * The returned token control information. + * + * @return + * Nothing. + */ VOID NTAPI SeGetTokenControlInformation(IN PACCESS_TOKEN _Token, @@ -169,6 +237,41 @@ SeGetTokenControlInformation(IN PACCESS_TOKEN _Token, SepReleaseTokenLock(Token); } +/** + * @brief + * Creates a client security context based upon an access token. + * + * @param[in] Token + * A valid token object. + * + * @param[in] ClientSecurityQos + * The Quality of Service (QoS) of a client security context. + * + * @param[in] ServerIsRemote + * If the client is a remote server (TRUE), the function will retrieve the + * control information of an access token, that is, we're doing delegation + * and that the server isn't local. + * + * @param[in] TokenType + * Type of token. + * + * @param[in] ThreadEffectiveOnly + * If set to TRUE, the client wants that the current thread wants to modify + * (enable or disable) privileges and groups. + * + * @param[in] ImpersonationLevel + * Security impersonation level filled in the QoS context. + * + * @param[out] ClientContext + * The returned security client context. + * + * @return + * Returns STATUS_SUCCESS if client security creation has completed successfully. + * STATUS_INVALID_PARAMETER is returned if one or more of the parameters are bogus. + * STATUS_BAD_IMPERSONATION_LEVEL is returned if the current impersonation level + * within QoS context doesn't meet with the conditions required. A failure + * NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SepCreateClientSecurity(IN PACCESS_TOKEN Token, @@ -258,8 +361,24 @@ SepCreateClientSecurity(IN PACCESS_TOKEN Token, /* PUBLIC FUNCTIONS ***********************************************************/ -/* - * @implemented +/** + * @brief + * An extended function that captures the security subject context based upon + * the specified thread and process. + * + * @param[in] Thread + * A thread where the calling thread's token is to be referenced for + * the security context. + * + * @param[in] Process + * A process where the main process' token is to be referenced for + * the security context. + * + * @param[out] SubjectContext + * The returned security subject context. + * + * @return + * Nothing. */ VOID NTAPI @@ -293,8 +412,16 @@ SeCaptureSubjectContextEx(IN PETHREAD Thread, SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process); } -/* - * @implemented +/** + * @brief + * Captures the security subject context of the calling thread and calling + * process. + * + * @param[out] SubjectContext + * The returned security subject context. + * + * @return + * Nothing. */ VOID NTAPI @@ -306,8 +433,16 @@ SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext) SubjectContext); } -/* - * @implemented +/** + * @brief + * Locks both the referenced primary and client access tokens of a + * security subject context. + * + * @param[in] SubjectContext + * A valid security context with both referenced tokens. + * + * @return + * Nothing. */ VOID NTAPI @@ -328,8 +463,16 @@ SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext) SepAcquireTokenLockShared(ClientToken); } -/* - * @implemented +/** + * @brief + * Unlocks both the referenced primary and client access tokens of a + * security subject context. + * + * @param[in] SubjectContext + * A valid security context with both referenced tokens. + * + * @return + * Nothing. */ VOID NTAPI @@ -352,8 +495,16 @@ SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext) SepReleaseTokenLock(PrimaryToken); } -/* - * @implemented +/** + * @brief + * Releases both the primary and client tokens of a security + * subject context. + * + * @param[in] SubjectContext + * The captured security context. + * + * @return + * Nothing. */ VOID NTAPI @@ -370,8 +521,30 @@ SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext) SubjectContext->ClientToken = NULL; } -/* - * @implemented +/** + * @brief + * An extended function that creates an access state. + * + * @param[in] Thread + * Valid thread object where subject context is to be captured. + * + * @param[in] Process + * Valid process object where subject context is to be captured. + * + * @param[in, out] AccessState + * An initialized returned parameter to an access state. + * + * @param[in] AuxData + * Auxiliary security data for access state. + * + * @param[in] Access + * Type of access mask to assign. + * + * @param[in] GenericMapping + * Generic mapping for the access state to assign. + * + * @return + * Returns STATUS_SUCCESS. */ NTSTATUS NTAPI @@ -431,8 +604,24 @@ SeCreateAccessStateEx(IN PETHREAD Thread, return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Creates an access state. + * + * @param[in, out] AccessState + * An initialized returned parameter to an access state. + * + * @param[in] AuxData + * Auxiliary security data for access state. + * + * @param[in] Access + * Type of access mask to assign. + * + * @param[in] GenericMapping + * Generic mapping for the access state to assign. + * + * @return + * See SeCreateAccessStateEx. */ NTSTATUS NTAPI @@ -452,8 +641,15 @@ SeCreateAccessState(IN OUT PACCESS_STATE AccessState, GenericMapping); } -/* - * @implemented +/** + * @brief + * Deletes an allocated access state from the memory. + * + * @param[in] AccessState + * A valid access state. + * + * @return + * Nothing. */ VOID NTAPI @@ -484,8 +680,18 @@ SeDeleteAccessState(IN PACCESS_STATE AccessState) SeReleaseSubjectContext(&AccessState->SubjectSecurityContext); } -/* - * @implemented +/** + * @brief + * Sets a new generic mapping for an allocated access state. + * + * @param[in] AccessState + * A valid access state. + * + * @param[in] GenericMapping + * New generic mapping to assign. + * + * @return + * Nothing. */ VOID NTAPI @@ -498,8 +704,24 @@ SeSetAccessStateGenericMapping(IN PACCESS_STATE AccessState, ((PAUX_ACCESS_DATA)AccessState->AuxData)->GenericMapping = *GenericMapping; } -/* - * @implemented +/** + * @brief + * Creates a client security context. + * + * @param[in] Thread + * Thread object of the client where impersonation has to begin. + * + * @param[in] Qos + * Quality of service to specify what kind of impersonation to be done. + * + * @param[in] RemoteClient + * If set to TRUE, the client that we're going to impersonate is remote. + * + * @param[out] ClientContext + * The returned security client context. + * + * @return + * See SepCreateClientSecurity. */ NTSTATUS NTAPI @@ -541,8 +763,26 @@ SeCreateClientSecurity(IN PETHREAD Thread, return Status; } -/* - * @implemented +/** + * @brief + * Creates a client security context based upon the captured security + * subject context. + * + * @param[in] SubjectContext + * The captured subject context where client security is to be created + * from. + * + * @param[in] ClientSecurityQos + * Quality of service to specify what kind of impersonation to be done. + * + * @param[in] ServerIsRemote + * If set to TRUE, the client that we're going to impersonate is remote. + * + * @param[out] ClientContext + * The returned security client context. + * + * @return + * See SepCreateClientSecurity. */ NTSTATUS NTAPI @@ -581,8 +821,19 @@ SeCreateClientSecurityFromSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectCon return Status; } -/* - * @implemented +/** + * @brief + * Extended function that impersonates a client. + * + * @param[in] ClientContext + * A valid client context. + * + * @param[in] ServerThread + * The thread where impersonation is to be done. + * + * @return + * STATUS_SUCCESS is returned if the calling thread successfully impersonates + * the client. A failure NTSTATUS code is returned otherwise. */ NTSTATUS NTAPI @@ -615,8 +866,18 @@ SeImpersonateClientEx(IN PSECURITY_CLIENT_CONTEXT ClientContext, ClientContext->SecurityQos.ImpersonationLevel); } -/* - * @implemented +/** + * @brief + * Impersonates a client user. + * + * @param[in] ClientContext + * A valid client context. + * + * @param[in] ServerThread + * The thread where impersonation is to be done. + * * + * @return + * Nothing. */ VOID NTAPI diff --git a/ntoskrnl/se/accesschk.c b/ntoskrnl/se/accesschk.c index a7784b1c2b6..26e5630469b 100644 --- a/ntoskrnl/se/accesschk.c +++ b/ntoskrnl/se/accesschk.c @@ -1,10 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/accesschk.c - * PURPOSE: Security manager - * - * PROGRAMMERS: No programmer listed. + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security access check control implementation + * COPYRIGHT: Copyright Timo Kreuzer + * Copyright Eric Kohl */ /* INCLUDES *******************************************************************/ @@ -18,8 +17,53 @@ /* PRIVATE FUNCTIONS **********************************************************/ -/* - * FIXME: Incomplete! +/** + * @brief + * Private function that determines whether security access rights can be given + * to an object depending on the security descriptor and other security context + * entities, such as an owner. + * + * @param[in] SecurityDescriptor + * Security descriptor of the object that is being accessed. + * + * @param[in] SubjectSecurityContext + * The captured subject security context. + * + * @param[in] DesiredAccess + * Access right bitmask that the calling thread wants to acquire. + * + * @param[in] ObjectTypeListLength + * The length of a object type list. + * + * @param[in] PreviouslyGrantedAccess + * The access rights previously acquired in the past. + * + * @param[out] Privileges + * The returned set of privileges. + * + * @param[in] GenericMapping + * The generic mapping of access rights of an object type. + * + * @param[in] AccessMode + * The processor request level mode. + * + * @param[out] GrantedAccessList + * A list of granted access rights. + * + * @param[out] AccessStatusList + * The returned status code specifying why access cannot be made + * onto an object (if said access is denied in the first place). + * + * @param[in] UseResultList + * If set to TRUE, the function will return complete lists of + * access status codes and granted access rights. + * + * @return + * Returns TRUE if access onto the specific object is allowed, FALSE + * otherwise. + * + * @remarks + * The function is currently incomplete! */ BOOLEAN NTAPI SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, @@ -286,6 +330,17 @@ ReturnCommonStatus: return NT_SUCCESS(Status); } +/** + * @brief + * Retrieves the main user from a security descriptor. + * + * @param[in] SecurityDescriptor + * A valid allocated security descriptor structure where the owner + * is to be retrieved. + * + * @return + * Returns a SID that represents the main user (owner). + */ static PSID SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor) { @@ -301,6 +356,17 @@ SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor) return Owner; } +/** + * @brief + * Retrieves the group from a security descriptor. + * + * @param[in] SecurityDescriptor + * A valid allocated security descriptor structure where the group + * is to be retrieved. + * + * @return + * Returns a SID that represents a group. + */ static PSID SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor) { @@ -316,6 +382,16 @@ SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor) return Group; } +/** + * @brief + * Retrieves the length size of a set list of privileges structure. + * + * @param[in] PrivilegeSet + * A valid set of privileges. + * + * @return + * Returns the total length of a set of privileges. + */ static ULONG SepGetPrivilegeSetLength(IN PPRIVILEGE_SET PrivilegeSet) @@ -332,8 +408,47 @@ SepGetPrivilegeSetLength(IN PPRIVILEGE_SET PrivilegeSet) /* PUBLIC FUNCTIONS ***********************************************************/ -/* - * @implemented +/** + * @brief + * Determines whether security access rights can be given to an object + * depending on the security descriptor and other security context + * entities, such as an owner. + * + * @param[in] SecurityDescriptor + * Security descriptor of the object that is being accessed. + * + * @param[in] SubjectSecurityContext + * The captured subject security context. + * + * @param[in] SubjectContextLocked + * If set to TRUE, a lock must be acquired for the security subject + * context. + * + * @param[in] DesiredAccess + * Access right bitmask that the calling thread wants to acquire. + * + * @param[in] PreviouslyGrantedAccess + * The access rights previously acquired in the past. + * + * @param[out] Privileges + * The returned set of privileges. + * + * @param[in] GenericMapping + * The generic mapping of access rights of an object type. + * + * @param[in] AccessMode + * The processor request level mode. + * + * @param[out] GrantedAccess + * A list of granted access rights. + * + * @param[out] AccessStatus + * The returned status code specifying why access cannot be made + * onto an object (if said access is denied in the first place). + * + * @return + * Returns TRUE if access onto the specific object is allowed, FALSE + * otherwise. */ BOOLEAN NTAPI @@ -452,8 +567,29 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return ret; } -/* - * @implemented +/** + * @brief + * Determines whether security access rights can be given to an object + * depending on the security descriptor. Unlike the regular access check + * procedure in the NT kernel, the fast traverse check is a faster way + * to quickly check if access can be made into an object. + * + * @param[in] SecurityDescriptor + * Security descriptor of the object that is being accessed. + * + * @param[in] AccessState + * An access state to determine if the access token in the current + * security context of the object is an restricted token. + * + * @param[in] DesiredAccess + * The access right bitmask where the calling thread wants to acquire. + * + * @param[in] AccessMode + * Process level request mode. + * + * @return + * Returns TRUE if access onto the specific object is allowed, FALSE + * otherwise. */ BOOLEAN NTAPI @@ -521,8 +657,48 @@ SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, /* SYSTEM CALLS ***************************************************************/ -/* - * @implemented +/** + * @brief + * Determines whether security access rights can be given to an object + * depending on the security descriptor and a valid handle to an access + * token. + * + * @param[in] SecurityDescriptor + * Security descriptor of the object that is being accessed. + * + * @param[in] TokenHandle + * A handle to a token. + * + * @param[in] DesiredAccess + * The access right bitmask where the calling thread wants to acquire. + * + * @param[in] GenericMapping + * The generic mapping of access rights of an object type. + * + * @param[out] PrivilegeSet + * The returned set of privileges. + * + * @param[in,out] PrivilegeSetLength + * The total length size of a set of privileges. + * + * @param[out] GrantedAccess + * A list of granted access rights. + * + * @param[out] AccessStatus + * The returned status code specifying why access cannot be made + * onto an object (if said access is denied in the first place). + * + * @return + * Returns STATUS_SUCCESS if access check has been done without problems + * and that the object can be accessed. STATUS_GENERIC_NOT_MAPPED is returned + * if no generic access right is mapped. STATUS_NO_IMPERSONATION_TOKEN is returned + * if the token from the handle is not an impersonation token. + * STATUS_BAD_IMPERSONATION_LEVEL is returned if the token cannot be impersonated + * because the current security impersonation level doesn't permit so. + * STATUS_INVALID_SECURITY_DESCR is returned if the security descriptor given + * to the call is not a valid one. STATUS_BUFFER_TOO_SMALL is returned if + * the buffer to the captured privileges has a length that is less than the required + * size of the set of privileges. A failure NTSTATUS code is returned otherwise. */ NTSTATUS NTAPI @@ -768,7 +944,48 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_SUCCESS; } - +/** + * @brief + * Determines whether security access could be granted or not on + * an object by the requestor who wants such access through type. + * + * @param[in] SecurityDescriptor + * A security descriptor with information data for auditing. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] ClientToken + * A client access token. + * + * @param[in] DesiredAccess + * The desired access masks rights requested by the caller. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping list of access masks rights. + * + * @param[in] PrivilegeSet + * An array set of privileges. + * + * @param[in,out] PrivilegeSetLength + * The length size of the array set of privileges. + * + * @param[out] GrantedAccess + * The returned granted access rights. + * + * @param[out] AccessStatus + * The returned NTSTATUS code indicating the final results + * of auditing. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor, @@ -787,6 +1004,49 @@ NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_NOT_IMPLEMENTED; } +/** + * @brief + * Determines whether security access could be granted or not on + * an object by the requestor who wants such access through + * type list. + * + * @param[in] SecurityDescriptor + * A security descriptor with information data for auditing. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] ClientToken + * A client access token. + * + * @param[in] DesiredAccess + * The desired access masks rights requested by the caller. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping list of access masks rights. + * + * @param[in] PrivilegeSet + * An array set of privileges. + * + * @param[in,out] PrivilegeSetLength + * The length size of the array set of privileges. + * + * @param[out] GrantedAccess + * The returned granted access rights. + * + * @param[out] AccessStatus + * The returned NTSTATUS code indicating the final results + * of auditing. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor, diff --git a/ntoskrnl/se/acl.c b/ntoskrnl/se/acl.c index 1da423b43c2..f68cc40695e 100644 --- a/ntoskrnl/se/acl.c +++ b/ntoskrnl/se/acl.c @@ -1,10 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/acl.c - * PURPOSE: Security manager - * - * PROGRAMMERS: David Welch + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Access control lists (ACLs) implementation + * COPYRIGHT: Copyright David Welch */ /* INCLUDES *******************************************************************/ @@ -25,6 +23,15 @@ PACL SeSystemAnonymousLogonDacl = NULL; /* FUNCTIONS ******************************************************************/ +/** + * @brief + * Initializes known discretionary access control lists in the system upon + * kernel and Executive initialization procedure. + * + * @return + * Returns TRUE if all the DACLs have been successfully initialized, + * FALSE otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -246,6 +253,25 @@ SepInitDACLs(VOID) return TRUE; } +/** + * @brief + * Allocates a discretionary access control list based on certain properties + * of a regular and primary access tokens. + * + * @param[in] Token + * An access token. + * + * @param[in] PrimaryToken + * A primary access token. + * + * @param[out] Dacl + * The returned allocated DACL. + * + * @return + * Returns STATUS_SUCCESS if DACL creation from tokens has completed + * successfully. STATUS_INSUFFICIENT_RESOURCES is returned if DACL + * allocation from memory pool fails otherwise. + */ NTSTATUS NTAPI SepCreateImpersonationTokenDacl( @@ -294,6 +320,33 @@ SepCreateImpersonationTokenDacl( return STATUS_SUCCESS; } +/** + * @brief + * Captures an access control list from an already valid input ACL. + * + * @param[in] InputAcl + * A valid ACL. + * + * @param[in] AccessMode + * Processor level access mode. The processor mode determines how + * are the input arguments probed. + * + * @param[in] PoolType + * Pool type for new captured ACL for creation. The pool type determines + * how the ACL data should reside in the pool memory. + * + * @param[in] CaptureIfKernel + * If set to TRUE and the processor access mode being KernelMode, we're + * capturing an ACL directly in the kernel. Otherwise we're capturing + * within a kernel mode driver. + * + * @param[out] CapturedAcl + * The returned and allocated captured ACL. + * + * @return + * Returns STATUS_SUCCESS if the ACL has been successfully captured. + * STATUS_INSUFFICIENT_RESOURCES is returned otherwise. + */ NTSTATUS NTAPI SepCaptureAcl(IN PACL InputAcl, @@ -382,6 +435,24 @@ SepCaptureAcl(IN PACL InputAcl, return Status; } +/** + * @brief + * Releases (frees) a captured ACL from the memory pool. + * + * @param[in] CapturedAcl + * A valid captured ACL to free. + * + * @param[in] AccessMode + * Processor level access mode. + * + * @param[in] CaptureIfKernel + * If set to TRUE and the processor access mode being KernelMode, we're + * releasing an ACL directly in the kernel. Otherwise we're releasing + * within a kernel mode driver. + * + * @return + * Nothing. + */ VOID NTAPI SepReleaseAcl(IN PACL CapturedAcl, @@ -398,6 +469,29 @@ SepReleaseAcl(IN PACL CapturedAcl, } } +/** + * @brief + * Determines if a certain ACE can or cannot be propagated based on + * ACE inheritation flags and whatnot. + * + * @param[in] AceFlags + * Bit flags of an ACE to perform propagation checks. + * + * @param[out] NewAceFlags + * New ACE bit blags based on the specific ACE flags of the first + * argument parameter. + * + * @param[in] IsInherited + * If set to TRUE, an ACE is deemed as directly inherited from another + * instance. In that case we're allowed to propagate. + * + * @param[in] IsDirectoryObject + * If set to TRUE, an object directly inherits this ACE so we can propagate + * it. + * + * @return + * Returns TRUE if an ACE can be propagated, FALSE otherwise. + */ BOOLEAN SepShouldPropagateAce( _In_ UCHAR AceFlags, @@ -446,6 +540,42 @@ SepShouldPropagateAce( return FALSE; } +/** + * @brief + * Propagates (copies) an access control list. + * + * @param[out] AclDest + * The destination parameter with propagated ACL. + * + * @param[in,out] AclLength + * The length of the ACL that we propagate. + * + * @param[in] AclSource + * The source instance of a valid ACL. + * + * @param[in] Owner + * A SID that represents the main user that identifies the ACL. + * + * @param[in] Group + * A SID that represents a group that identifies the ACL. + * + * @param[in] IsInherited + * If set to TRUE, that means the ACL is directly inherited. + * + * @param[in] IsDirectoryObject + * If set to TRUE, that means the ACL is directly inherited because + * of the object that inherits it. + * + * @param[in] GenericMapping + * Generic mapping of access rights to map only certain effective + * ACEs. + * + * @return + * Returns STATUS_SUCCESS if ACL has been propagated successfully. + * STATUS_BUFFER_TOO_SMALL is returned if the ACL length is not greater + * than the maximum written size of the buffer for ACL propagation + * otherwise. + */ NTSTATUS SepPropagateAcl( _Out_writes_bytes_opt_(AclLength) PACL AclDest, @@ -609,6 +739,60 @@ SepPropagateAcl( return STATUS_SUCCESS; } +/** + * @brief + * Selects an ACL and returns it to the caller. + * + * @param[in] ExplicitAcl + * If specified, the specified ACL to the call will be + * the selected ACL for the caller. + * + * @param[in] ExplicitPresent + * If set to TRUE and with specific ACL filled to the call, the + * function will immediately return the specific ACL as the selected + * ACL for the caller. + * + * @param[in] ExplicitDefaulted + * If set to FALSE and with specific ACL filled to the call, the ACL + * is not a default ACL. Otherwise it's a default ACL that we cannot + * select it as is. + * + * @param[in] ParentAcl + * If specified, the parent ACL will be used to determine the exact ACL + * length to check if the ACL in question is not empty. If the list + * is not empty then the function will select such ACL to the caller. + * + * @param[in] DefaultAcl + * If specified, the default ACL will be the selected one for the caller. + * + * @param[out] AclLength + * The size length of an ACL. + * + * @param[in] Owner + * A SID that represents the main user that identifies the ACL. + * + * @param[in] Group + * A SID that represents a group that identifies the ACL. + * + * @param[out] AclPresent + * The returned boolean value, indicating if the ACL that we want to select + * does actually exist. + * + * @param[out] IsInherited + * The returned boolean value, indicating if the ACL we want to select it + * is actually inherited or not. + * + * @param[in] IsDirectoryObject + * If set to TRUE, the object inherits this ACL. + * + * @param[in] GenericMapping + * Generic mapping of access rights to map only certain effective + * ACEs of an ACL that we want to select it. + * + * @return + * Returns the selected access control list (ACL) to the caller, + * NULL otherwise. + */ PACL SepSelectAcl( _In_opt_ PACL ExplicitAcl, diff --git a/ntoskrnl/se/audit.c b/ntoskrnl/se/audit.c index 03604d30259..a7123d0a19b 100644 --- a/ntoskrnl/se/audit.c +++ b/ntoskrnl/se/audit.c @@ -1,11 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/audit.c - * PURPOSE: Audit functions - * - * PROGRAMMERS: Eric Kohl - * Timo Kreuzer (timo.kreuzer@reactos.org) + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security auditing functions + * COPYRIGHT: Copyright Eric Kohl + * Copyright Timo Kreuzer */ /* INCLUDES *******************************************************************/ @@ -20,6 +18,17 @@ UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security"); /* PRIVATE FUNCTIONS***********************************************************/ +/** + * @unimplemented + * @brief + * Peforms a detailed security auditing with an access token. + * + * @param[in] Token + * A valid token object. + * + * @return + * To be added... + */ BOOLEAN NTAPI SeDetailedAuditingWithToken(IN PTOKEN Token) @@ -28,6 +37,19 @@ SeDetailedAuditingWithToken(IN PTOKEN Token) return FALSE; } +/** + * @unimplemented + * @brief + * Peforms a security auditing against a process that is about to + * be created. + * + * @param[in] Process + * An object that points to a process which is in process of + * creation. + * + * @return + * Nothing. + */ VOID NTAPI SeAuditProcessCreate(IN PEPROCESS Process) @@ -35,6 +57,19 @@ SeAuditProcessCreate(IN PEPROCESS Process) /* FIXME */ } +/** + * @unimplemented + * @brief + * Peforms a security auditing against a process that is about to + * be terminated. + * + * @param[in] Process + * An object that points to a process which is in process of + * termination. + * + * @return + * Nothing. + */ VOID NTAPI SeAuditProcessExit(IN PEPROCESS Process) @@ -42,6 +77,26 @@ SeAuditProcessExit(IN PEPROCESS Process) /* FIXME */ } +/** + * @brief + * Initializes a process audit name and returns it to the caller. + * + * @param[in] FileObject + * File object that points to a name to be queried. + * + * @param[in] DoAudit + * If set to TRUE, the function will perform various security + * auditing onto the audit name. + * + * @param[out] AuditInfo + * The returned audit info data. + * + * @return + * Returns STATUS_SUCCESS if process audit name initialization + * has completed successfully. STATUS_NO_MEMORY is returned if + * pool allocation for object name info has failed. A failure + * NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject, @@ -117,6 +172,24 @@ SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject, return Status; } +/** + * @brief + * Finds the process image name of a specific process. + * + * @param[in] Process + * Process object submitted by the caller, where the image name + * is to be located. + * + * @param[out] ProcessImageName + * An output Unicode string structure with the located process + * image name. + * + * @return + * Returns STATUS_SUCCESS if process image name has been located + * successfully. STATUS_NO_MEMORY is returned if pool allocation + * for the image name has failed. A failure NTSTATUS code is + * returned otherwise. + */ NTSTATUS NTAPI SeLocateProcessImageName(IN PEPROCESS Process, @@ -185,6 +258,25 @@ SeLocateProcessImageName(IN PEPROCESS Process, return Status; } +/** + * @brief + * Closes an audit alarm event of an object. + * + * @param[in] SubsystemName + * A Unicode string pointing to the name of the subsystem where auditing + * alarm event has to be closed. + * + * @param[in] HandleId + * A handle to an ID where such ID represents the identification of the + * object where audit alarm is to be closed. + * + * @param[in] Sid + * A SID that represents the user who attempted to close the audit + * alarm. + * + * @return + * Nothing. + */ VOID NTAPI SepAdtCloseObjectAuditAlarm( @@ -195,6 +287,41 @@ SepAdtCloseObjectAuditAlarm( UNIMPLEMENTED; } +/** + * @brief + * Performs an audit alarm to a privileged service request. + * This is a worker function. + * + * @param[in] SubjectContext + * A security subject context used for the auditing process. + * + * @param[in] SubsystemName + * A Unicode string that represents the name of a subsystem that + * actuated the procedure of alarm auditing of a privileged + * service. + * + * @param[in] ServiceName + * A Unicode string that represents the name of a privileged + * service request for auditing. + * + * @param[in] Token + * An access token. + * + * @param[in] PrimaryToken + * A primary access token. + * + * @param[in] Privileges + * An array set of privileges used to check if the privileged + * service does actually have all the required set of privileges + * for security access. + * + * @param[in] AccessGranted + * When auditing is done, the function will return TRUE to the caller + * if access is granted, FALSE otherwise. + * + * @return + * Nothing. + */ VOID NTAPI SepAdtPrivilegedServiceAuditAlarm( @@ -209,6 +336,29 @@ SepAdtPrivilegedServiceAuditAlarm( DPRINT("SepAdtPrivilegedServiceAuditAlarm is unimplemented\n"); } +/** + * @brief + * Performs an audit alarm to a privileged service request. + * + * @param[in] ServiceName + * A Unicode string that represents the name of a privileged + * service request for auditing. + * + * @param[in] SubjectContext + * A security subject context used for the auditing process. + * + * @param[in] PrivilegeSet + * An array set of privileges used to check if the privileged + * service does actually have all the required set of privileges + * for security access. + * + * @param[in] AccessGranted + * When auditing is done, the function will return TRUE to the caller + * if access is granted, FALSE otherwise. + * + * @return + * Nothing. + */ VOID NTAPI SePrivilegedServiceAuditAlarm( @@ -256,7 +406,28 @@ SePrivilegedServiceAuditAlarm( } - +/** + * @brief + * Captures a list of object types. + * + * @param[in] ObjectTypeList + * An existing list of object types. + * + * @param[in] ObjectTypeListLength + * The length size of the list. + * + * @param[in] PreviousMode + * Processor access level mode. + * + * @param[out] CapturedObjectTypeList + * The captured list of object types. + * + * @return + * Returns STATUS_SUCCESS if the list of object types has been captured + * successfully. STATUS_INVALID_PARAMETER is returned if the caller hasn't + * supplied a buffer list of object types. STATUS_INSUFFICIENT_RESOURCES + * is returned if pool memory allocation for the captured list has failed. + */ static NTSTATUS SeCaptureObjectTypeList( @@ -313,6 +484,19 @@ SeCaptureObjectTypeList( return STATUS_SUCCESS; } +/** + * @brief + * Releases a buffer list of object types. + * + * @param[in] CapturedObjectTypeList + * A list of object types to free. + * + * @param[in] PreviousMode + * Processor access level mode. + * + * @return + * Nothing. + */ static VOID SeReleaseObjectTypeList( @@ -323,6 +507,78 @@ SeReleaseObjectTypeList( ExFreePoolWithTag(CapturedObjectTypeList, TAG_SEPA); } +/** + * @unimplemented + * @brief + * Worker function that serves as the main heart and brain of the whole + * concept and implementation of auditing in the kernel. + * + * @param[in] SubsystemName + * A Unicode string that represents the name of a subsystem that + * actuates the auditing process. + * + * @param[in] HandleId + * A handle to an ID used to identify an object where auditing + * is to be done. + * + * @param[in] SubjectContext + * Security subject context. + * + * @param[in] ObjectTypeName + * A Unicode string that represents the name of an object type. + * + * @param[in] ObjectName + * The name of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor with internal security information details + * for audit. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] AuditType + * Type of audit to start. This parameter influences how an audit + * should be done. + * + * @param[in] HaveAuditPrivilege + * If set to TRUE, the security subject context has the audit privilege thus + * it is allowed the ability to perform the audit. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeListLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping table of access rights used whilst performing auditing + * sequence procedure. + * + * @param[out] GrantedAccessList + * This parameter is used to return to the caller a list of actual granted access + * rights masks that the audited object has. + * + * @param[out] AccessStatusList + * This parameter is used to return to the caller a list of status return codes. + * The function may actually return a single NTSTATUS code if the calling thread + * sets UseResultList parameter to FALSE. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @param[in] UseResultList + * If set to TRUE, the caller wants that the function should only return a single + * NTSTATUS code. + * + * @return + * Returns STATUS_SUCCESS if the function has completed the whole internal + * auditing procedure mechanism with success. + */ _Must_inspect_result_ static NTSTATUS @@ -365,6 +621,89 @@ SepAccessCheckAndAuditAlarmWorker( return STATUS_SUCCESS; } +/** + * @brief + * Performs security auditing, if the specific object can be granted + * security access or not. + * + * @param[in] SubsystemName + * A Unicode string that represents the name of a subsystem that + * actuates the auditing process. + * + * @param[in] HandleId + * A handle to an ID used to identify an object where auditing + * is to be done. + * + * @param[in] SubjectContext + * Security subject context. + * + * @param[in] ObjectTypeName + * A Unicode string that represents the name of an object type. + * + * @param[in] ObjectName + * The name of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor with internal security information details + * for audit. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] AuditType + * Type of audit to start. This parameter influences how an audit + * should be done. + * + * @param[in] Flags + * Flag bitmask parameter. + * + * @param[in] HaveAuditPrivilege + * If set to TRUE, the security subject context has the audit privilege thus + * it is allowed the ability to perform the audit. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeListLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping table of access rights used whilst performing auditing + * sequence procedure. + * + * @param[out] GrantedAccessList + * This parameter is used to return to the caller a list of actual granted access + * rights masks that the audited object has. + * + * @param[out] AccessStatusList + * This parameter is used to return to the caller a list of status return codes. + * The function may actually return a single NTSTATUS code if the calling thread + * sets UseResultList parameter to FALSE. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @param[in] UseResultList + * If set to TRUE, the caller wants that the function should only return a single + * NTSTATUS code. + * + * @return + * Returns STATUS_SUCCESS if the function has completed the whole internal + * auditing procedure mechanism with success. STATUS_INVALID_PARAMETER is + * returned if one of the parameters do not satisfy the general requirements + * by the function. STATUS_INSUFFICIENT_RESOURCES is returned if pool memory + * allocation has failed. STATUS_PRIVILEGE_NOT_HELD is returned if the current + * security subject context does not have the required audit privilege to actually + * perform auditing in the first place. STATUS_INVALID_SECURITY_DESCR is returned + * if the security descriptor provided by the caller is not valid, that is, such + * descriptor doesn't belong to the main user (owner) and current group. + * STATUS_GENERIC_NOT_MAPPED is returned if the access rights masks aren't actually + * mapped. A failure NTSTATUS code is returned otherwise. + */ _Must_inspect_result_ NTSTATUS NTAPI @@ -700,8 +1039,24 @@ Cleanup: /* PUBLIC FUNCTIONS ***********************************************************/ -/* +/** * @unimplemented + * @brief + * Performs an audit against a hard link creation. + * + * @param[in] FileName + * A Unicode string that points to the name of the file. + * + * @param[in] LinkName + * A Unicode string that points to a link. + * + * @param[out] bSuccess + * If TRUE, the function has successfully audited + * the hard link and security access can be granted, + * FALSE otherwise. + * + * @return + * Nothing. */ VOID NTAPI @@ -712,8 +1067,21 @@ SeAuditHardLinkCreation(IN PUNICODE_STRING FileName, UNIMPLEMENTED; } -/* +/** * @unimplemented + * @brief + * Determines whether auditing against file events is being + * done or not. + * + * @param[in] AccessGranted + * If set to TRUE, the access attempt is deemed as successful + * otherwise set it to FALSE. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @return + * Returns TRUE if auditing is being currently done, FALSE otherwise. */ BOOLEAN NTAPI @@ -724,8 +1092,25 @@ SeAuditingFileEvents(IN BOOLEAN AccessGranted, return FALSE; } -/* +/** * @unimplemented + * @brief + * Determines whether auditing against file events with subject context + * is being done or not. + * + * @param[in] AccessGranted + * If set to TRUE, the access attempt is deemed as successful + * otherwise set it to FALSE. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] SubjectSecurityContext + * If specified, the function will check if security auditing is currently + * being done with this context. + * + * @return + * Returns TRUE if auditing is being currently done, FALSE otherwise. */ BOOLEAN NTAPI @@ -737,8 +1122,21 @@ SeAuditingFileEventsWithContext(IN BOOLEAN AccessGranted, return FALSE; } -/* +/** * @unimplemented + * @brief + * Determines whether auditing against hard links events is being + * done or not. + * + * @param[in] AccessGranted + * If set to TRUE, the access attempt is deemed as successful + * otherwise set it to FALSE. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @return + * Returns TRUE if auditing is being currently done, FALSE otherwise. */ BOOLEAN NTAPI @@ -749,8 +1147,25 @@ SeAuditingHardLinkEvents(IN BOOLEAN AccessGranted, return FALSE; } -/* +/** * @unimplemented + * @brief + * Determines whether auditing against hard links events with subject context + * is being done or not. + * + * @param[in] AccessGranted + * If set to TRUE, the access attempt is deemed as successful + * otherwise set it to FALSE. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] SubjectSecurityContext + * If specified, the function will check if security auditing is currently + * being done with this context. + * + * @return + * Returns TRUE if auditing is being currently done, FALSE otherwise. */ BOOLEAN NTAPI @@ -762,8 +1177,25 @@ SeAuditingHardLinkEventsWithContext(IN BOOLEAN AccessGranted, return FALSE; } -/* +/** * @unimplemented + * @brief + * Determines whether auditing against files or global events with + * subject context is being done or not. + * + * @param[in] AccessGranted + * If set to TRUE, the access attempt is deemed as successful + * otherwise set it to FALSE. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] SubjectSecurityContext + * If specified, the function will check if security auditing is currently + * being done with this context. + * + * @return + * Returns TRUE if auditing is being currently done, FALSE otherwise. */ BOOLEAN NTAPI @@ -775,8 +1207,23 @@ SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted, return FALSE; } -/* +/** * @unimplemented + * @brief + * Closes an alarm audit of an object. + * + * @param[in] Object + * An arbitrary pointer data that points to the object. + * + * @param[in] Handle + * A handle of the said object. + * + * @param[in] PerformAction + * Set this to TRUE to perform any auxiliary action, otherwise + * set to FALSE. + * + * @return + * Nothing. */ VOID NTAPI @@ -787,8 +1234,19 @@ SeCloseObjectAuditAlarm(IN PVOID Object, UNIMPLEMENTED; } -/* +/** * @unimplemented + * @brief + * Deletes an alarm audit of an object. + * + * @param[in] Object + * An arbitrary pointer data that points to the object. + * + * @param[in] Handle + * A handle of the said object. + * + * @return + * Nothing. */ VOID NTAPI SeDeleteObjectAuditAlarm(IN PVOID Object, @@ -797,8 +1255,46 @@ SeDeleteObjectAuditAlarm(IN PVOID Object, UNIMPLEMENTED; } -/* +/** * @unimplemented + * @brief + * Creates an audit with alarm notification of an object + * that is being opened. + * + * @param[in] ObjectTypeName + * A Unicode string that points to the object type name. + * + * @param[in] Object + * If specified, the function will use this parameter to + * directly open the object. + * + * @param[in] AbsoluteObjectName + * If specified, the function will use this parameter to + * directly open the object through the absolute name + * of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] AccessState + * An access state right mask when opening the object. + * + * @param[in] ObjectCreated + * Set this to TRUE if the object has been fully created, + * FALSE otherwise. + * + * @param[in] AccessGranted + * Set this to TRUE if access was deemed as granted. + * + * @param[in] AccessMode + * Processor level access mode. + * + * @param[out] GenerateOnClose + * A boolean flag returned to the caller once audit generation procedure + * finishes. + * + * @return + * Nothing. */ VOID NTAPI @@ -822,8 +1318,46 @@ SeOpenObjectAuditAlarm(IN PUNICODE_STRING ObjectTypeName, return; } -/* +/** * @unimplemented + * @brief + * Creates an audit with alarm notification of an object + * that is being opened for deletion. + * + * @param[in] ObjectTypeName + * A Unicode string that points to the object type name. + * + * @param[in] Object + * If specified, the function will use this parameter to + * directly open the object. + * + * @param[in] AbsoluteObjectName + * If specified, the function will use this parameter to + * directly open the object through the absolute name + * of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] AccessState + * An access state right mask when opening the object. + * + * @param[in] ObjectCreated + * Set this to TRUE if the object has been fully created, + * FALSE otherwise. + * + * @param[in] AccessGranted + * Set this to TRUE if access was deemed as granted. + * + * @param[in] AccessMode + * Processor level access mode. + * + * @param[out] GenerateOnClose + * A boolean flag returned to the caller once audit generation procedure + * finishes. + * + * @return + * Nothing. */ VOID NTAPI SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName, @@ -839,8 +1373,34 @@ SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName, UNIMPLEMENTED; } -/* +/** * @unimplemented + * @brief + * Raises an audit with alarm notification message + * when an object tries to acquire this privilege. + * + * @param[in] Handle + * A handle to an object. + * + * @param[in] SubjectContext + * The security subject context for auditing. + * + * @param[in] DesiredAccess + * The desired right access masks requested by the caller. + * + * @param[in] Privileges + * An array set of privileges for auditing. + * + * @param[out] AccessGranted + * When the auditing procedure routine ends, it returns TRUE to the + * caller if the object has the required privileges for access, + * FALSE otherwise. + * + * @param[in] CurrentMode + * Processor level access mode. + * + * @return + * Nothing. */ VOID NTAPI @@ -856,6 +1416,28 @@ SePrivilegeObjectAuditAlarm(IN HANDLE Handle, /* SYSTEM CALLS ***************************************************************/ +/** + * @brief + * Raises an alarm audit message when an object is about + * to be closed. + * + * @param[in] SubsystemName + * A Unicode string that points to the name of the subsystem. + * + * @param[in] HandleId + * A handle of an ID used for identification instance for auditing. + * + * @param[in] GenerateOnClose + * A boolean value previously created by the "open" equivalent of this + * function. If the caller explicitly sets this to FALSE, the function + * assumes that the object is not opened. + * + * @return + * Returns STATUS_SUCCESS if all the operations have completed successfully. + * STATUS_PRIVILEGE_NOT_HELD is returned if the security subject context + * does not have the audit privilege to actually begin auditing procedures + * in the first place. + */ NTSTATUS NTAPI NtCloseObjectAuditAlarm( @@ -954,7 +1536,26 @@ Cleanup: return Status; } - +/** + * @unimplemented + * @brief + * Raises an alarm audit message when an object is about + * to be deleted. + * + * @param[in] SubsystemName + * A Unicode string that points to the name of the subsystem. + * + * @param[in] HandleId + * A handle of an ID used for identification instance for auditing. + * + * @param[in] GenerateOnClose + * A boolean value previously created by the "open" equivalent of this + * function. If the caller explicitly sets this to FALSE, the function + * assumes that the object is not opened. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, IN PVOID HandleId, @@ -964,6 +1565,55 @@ NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, return STATUS_NOT_IMPLEMENTED; } +/** + * @unimplemented + * @brief + * Raises an alarm audit message when an object is about + * to be opened. + * + * @param[in] SubjectContext + * A security subject context for auditing. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID used for identification instance for auditing. + * + * @param[in] ObjectTypeName + * A Unicode string that points to an object type name. + * + * @param[in] ObjectName + * The name of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] ClientToken + * A client access token, representing the client we want to impersonate. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] GrantedAccess + * The granted access mask rights. + * + * @param[in] Privileges + * If specified, the function will use this set of privileges to audit. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[in] AccessGranted + * Set this to TRUE if the access attempt was deemed as granted. + * + * @param[out] GenerateOnClose + * A boolean flag returned to the caller once audit generation procedure + * finishes. + * + * @return + * Nothing. + */ VOID NTAPI SepOpenObjectAuditAlarm( @@ -997,6 +1647,59 @@ SepOpenObjectAuditAlarm( *GenerateOnClose = FALSE; } +/** + * @brief + * Raises an alarm audit message when an object is about + * to be opened. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID used for identification instance for auditing. + * + * @param[in] ObjectTypeName + * A Unicode string that points to an object type name. + * + * @param[in] ObjectName + * The name of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] ClientTokenHandle + * A handle to a client access token. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] GrantedAccess + * The granted access mask rights. + * + * @param[in] PrivilegeSet + * If specified, the function will use this set of privileges to audit. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[in] AccessGranted + * Set this to TRUE if the access attempt was deemed as granted. + * + * @param[out] GenerateOnClose + * A boolean flag returned to the caller once audit generation procedure + * finishes. + * + * @return + * Returns STATUS_SUCCESS if all the operations have been completed successfully. + * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not + * hold the required audit privilege to actually begin auditing in the first place. + * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level + * of the client token is not on par with the impersonation level that alllows + * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has + * submitted a bogus set of privileges as such array set exceeds the maximum + * count of privileges that the kernel can accept. A failure NTSTATUS code + * is returned otherwise. + */ __kernel_entry NTSTATUS NTAPI @@ -1227,7 +1930,37 @@ Cleanup: return Status; } - +/** + * @brief + * Raises an alarm audit message when a caller attempts to request + * a privileged service call. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] ServiceName + * A Unicode string that points to a name of the privileged service. + * + * @param[in] ClientTokenHandle + * A handle to a client access token. + * + * @param[in] Privileges + * An array set of privileges. + * + * @param[in] AccessGranted + * Set this to TRUE if the access attempt was deemed as granted. + * + * @return + * Returns STATUS_SUCCESS if all the operations have been completed successfully. + * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not + * hold the required audit privilege to actually begin auditing in the first place. + * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level + * of the client token is not on par with the impersonation level that alllows + * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has + * submitted a bogus set of privileges as such array set exceeds the maximum + * count of privileges that the kernel can accept. A failure NTSTATUS code + * is returned otherwise. + */ __kernel_entry NTSTATUS NTAPI @@ -1387,7 +2120,32 @@ Cleanup: return Status; } - +/** + * @brief + * Raises an alarm audit message when a caller attempts to access a + * privileged object. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID that is used as identification instance for auditing. + * + * @param[in] ClientToken + * A handle to a client access token. + * + * @param[in] DesiredAccess + * A handle to a client access token. + * + * @param[in] Privileges + * An array set of privileges. + * + * @param[in] AccessGranted + * Set this to TRUE if the access attempt was deemed as granted. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, IN PVOID HandleId, @@ -1400,7 +2158,49 @@ NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, return STATUS_NOT_IMPLEMENTED; } - +/** + * @brief + * Raises an alarm audit message when a caller attempts to access an + * object and determine if the access can be made. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID that is used as identification instance for auditing. + * + * @param[in] ObjectTypeName + * The name of the object type. + * + * @param[in] ObjectName + * The object name. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] GenericMapping + * The generic mapping of access mask rights. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[out] GrantedAccess + * Returns the granted access rights. + * + * @param[out] AccessStatus + * Returns a NTSTATUS status code indicating whether access check + * can be granted or not. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @return + * See SepAccessCheckAndAuditAlarm. + */ _Must_inspect_result_ __kernel_entry NTSTATUS @@ -1438,6 +2238,66 @@ NtAccessCheckAndAuditAlarm( FALSE); } +/** + * @brief + * Raises an alarm audit message when a caller attempts to access an + * object and determine if the access can be made by type. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID that is used as identification instance for auditing. + * + * @param[in] ObjectTypeName + * The name of the object type. + * + * @param[in] ObjectName + * The object name. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] AuditType + * Type of audit to start, influencing how the audit should + * be done. + * + * @param[in] Flags + * Flag bitmask, used to check if auditing can be done + * without privileges. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping of access mask rights. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[out] GrantedAccess + * Returns the granted access rights. + * + * @param[out] AccessStatus + * Returns a NTSTATUS status code indicating whether access check + * can be granted or not. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @return + * See SepAccessCheckAndAuditAlarm. + */ _Must_inspect_result_ __kernel_entry NTSTATUS @@ -1480,6 +2340,66 @@ NtAccessCheckByTypeAndAuditAlarm( FALSE); } +/** + * @brief + * Raises an alarm audit message when a caller attempts to access an + * object and determine if the access can be made by given type result. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID that is used as identification instance for auditing. + * + * @param[in] ObjectTypeName + * The name of the object type. + * + * @param[in] ObjectName + * The object name. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] AuditType + * Type of audit to start, influencing how the audit should + * be done. + * + * @param[in] Flags + * Flag bitmask, used to check if auditing can be done + * without privileges. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping of access mask rights. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[out] GrantedAccessList + * Returns the granted access rights. + * + * @param[out] AccessStatusList + * Returns a NTSTATUS status code indicating whether access check + * can be granted or not. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @return + * See SepAccessCheckAndAuditAlarm. + */ _Must_inspect_result_ __kernel_entry NTSTATUS @@ -1522,6 +2442,70 @@ NtAccessCheckByTypeResultListAndAuditAlarm( TRUE); } +/** + * @brief + * Raises an alarm audit message when a caller attempts to access an + * object and determine if the access can be made by given type result + * and a token handle. + * + * @param[in] SubsystemName + * A Unicode string that points to a name of the subsystem. + * + * @param[in] HandleId + * A handle to an ID that is used as identification instance for auditing. + * + * @param[in] ClientToken + * A handle to a client access token. + * + * @param[in] ObjectTypeName + * The name of the object type. + * + * @param[in] ObjectName + * The object name. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[in] PrincipalSelfSid + * A principal self user SID. + * + * @param[in] DesiredAccess + * The desired access rights masks requested by the caller. + * + * @param[in] AuditType + * Type of audit to start, influencing how the audit should + * be done. + * + * @param[in] Flags + * Flag bitmask, used to check if auditing can be done + * without privileges. + * + * @param[in] ObjectTypeList + * A list of object types. + * + * @param[in] ObjectTypeLength + * The length size of the list. + * + * @param[in] GenericMapping + * The generic mapping of access mask rights. + * + * @param[in] ObjectCreation + * Set this to TRUE if the object has just been created. + * + * @param[out] GrantedAccessList + * Returns the granted access rights. + * + * @param[out] AccessStatusList + * Returns a NTSTATUS status code indicating whether access check + * can be granted or not. + * + * @param[out] GenerateOnClose + * Returns TRUE if the function has generated a list of granted access rights and + * status codes on termination, FALSE otherwise. + * + * @return + * See SepAccessCheckAndAuditAlarm. + */ _Must_inspect_result_ __kernel_entry NTSTATUS diff --git a/ntoskrnl/se/priv.c b/ntoskrnl/se/priv.c index 53286f5fc84..42f69c5e84a 100644 --- a/ntoskrnl/se/priv.c +++ b/ntoskrnl/se/priv.c @@ -1,10 +1,10 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/priv.c - * PURPOSE: Security manager - * - * PROGRAMMERS: No programmer listed. + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security privileges support + * COPYRIGHT: Copyright Alex Ionescu + * Copyright Timo Kreuzer + * Copyright Eric Kohl */ /* INCLUDES ******************************************************************/ @@ -54,6 +54,15 @@ const LUID SeCreateSymbolicLinkPrivilege = CONST_LUID(SE_CREATE_SYMBOLIC_LINK_PR /* PRIVATE FUNCTIONS **********************************************************/ +/** + * @brief + * Initializes the privileges during the startup phase of the security + * manager module. This function serves as a placeholder as it currently + * does nothing. + * + * @return + * Nothing. + */ CODE_SEG("INIT") VOID NTAPI @@ -62,7 +71,32 @@ SepInitPrivileges(VOID) } - +/** + * @brief + * Checks the privileges pointed by Privileges array argument if they exist and + * match with the privileges from an access token. + * + * @param[in] Token + * An access token where privileges are to be checked. + * + * @param[in] Privileges + * An array of privileges with attributes used as checking indicator for + * the function. + * + * @param[in] PrivilegeCount + * The total number count of privileges in the array. + * + * @param[in] PrivilegeControl + * Privilege control bit mask to determine if we should check all the + * privileges based on the number count of privileges or not. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if the required privileges exist and that they do match. + * Otherwise the functions returns FALSE. + */ BOOLEAN NTAPI SepPrivilegeCheck(PTOKEN Token, @@ -129,6 +163,25 @@ SepPrivilegeCheck(PTOKEN Token, return FALSE; } +/** + * @brief + * Checks only single privilege based upon the privilege pointed by a LUID and + * if it matches with the one from an access token. + * + * @param[in] PrivilegeValue + * The privilege to be checked. + * + * @param[in] Token + * An access token where its privilege is to be checked against the one + * provided by the caller. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if the required privilege exists and that it matches + * with the one from the access token, FALSE otherwise. + */ NTSTATUS NTAPI SepSinglePrivilegeCheck( @@ -149,6 +202,40 @@ SepSinglePrivilegeCheck( PreviousMode); } +/** + * @brief + * Checks the security policy and returns a set of privileges + * based upon the said security policy context. + * + * @param[in,out] DesiredAccess + * The desired access right mask. + * + * @param[in,out] GrantedAccess + * The granted access rights masks. The rights are granted depending + * on the desired access rights requested by the calling thread. + * + * @param[in] SubjectContext + * Security subject context. If the caller supplies one, the access token + * supplied by the caller will be assigned to one of client or primary tokens + * of the subject context in question. + * + * @param[in] Token + * An access token. + * + * @param[out] OutPrivilegeSet + * An array set of privileges to be reported to the caller, if the actual + * calling thread wants such set of privileges in the first place. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns STATUS_PRIVILEGE_NOT_HELD if the respective operations have succeeded + * without problems. STATUS_PRIVILEGE_NOT_HELD is returned if the access token + * doesn't have SeSecurityPrivilege privilege to warrant ACCESS_SYSTEM_SECURITY + * access right. STATUS_INSUFFICIENT_RESOURCES is returned if we failed + * to allocate block of memory pool for the array set of privileges. + */ NTSTATUS NTAPI SePrivilegePolicyCheck( @@ -248,6 +335,23 @@ SePrivilegePolicyCheck( return STATUS_SUCCESS; } +/** + * @brief + * Checks a single privilege and performs an audit + * against a privileged service based on a security subject + * context. + * + * @param[in] DesiredAccess + * Security subject context used for privileged service + * auditing. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if service auditing and privilege checking + * tests have succeeded, FALSE otherwise. + */ BOOLEAN NTAPI SeCheckAuditPrivilege( @@ -282,6 +386,48 @@ SeCheckAuditPrivilege( return Result; } +/** + * @brief + * Captures a LUID with attributes structure. This function is mainly + * tied in the context of privileges. + * + * @param[in] Src + * Source of a valid LUID with attributes structure. + * + * @param[in] PrivilegeCount + * Count number of privileges to be captured. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @param[in] AllocatedMem + * If specified, the function will use this allocated block memory + * buffer for the captured LUID and attributes structure. Otherwise + * the function will automatically allocate some buffer for it. + * + * @param[in] AllocatedLength + * The length of the buffer, pointed by AllocatedMem. + * + * @param[in] PoolType + * Pool type of the memory allocation. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the capturing is done in the kernel itself. + * FALSE if the capturing is done in a kernel mode driver instead. + * + * @param[out] Dest + * The captured LUID with attributes buffer. + * + * @param[in,out] Length + * The length of the captured privileges count. + * + * @return + * Returns STATUS_SUCCESS if the LUID and attributes array + * has been captured successfully. STATUS_INSUFFICIENT_RESOURCES is returned + * if memory pool allocation for the captured buffer has failed. + * STATUS_BUFFER_TOO_SMALL is returned if the buffer size is less than the + * required size. + */ NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, @@ -378,6 +524,23 @@ SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, return Status; } +/** + * @brief + * Releases a LUID with attributes structure. + * + * @param[in] Privilege + * Array of a LUID and attributes that represents a privilege. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the releasing is done in the kernel itself. + * FALSE if the releasing is done in a kernel mode driver instead. + * + * @return + * Nothing. + */ VOID NTAPI SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, @@ -395,8 +558,21 @@ SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, /* PUBLIC FUNCTIONS ***********************************************************/ -/* - * @implemented +/** + * @brief + * Appends additional privileges. + * + * @param[in] AccessState + * Access request to append. + * + * @param[in] Privileges + * Set of new privileges to append. + * + * @return + * Returns STATUS_SUCCESS if the privileges have been successfully + * appended. Otherwise STATUS_INSUFFICIENT_RESOURCES is returned, + * indicating that pool allocation has failed for the buffer to hold + * the new set of privileges. */ NTSTATUS NTAPI @@ -468,8 +644,15 @@ SeAppendPrivileges(IN OUT PACCESS_STATE AccessState, return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Frees a set of privileges. + * + * @param[in] Privileges + * Set of privileges array to be freed. + * + * @return + * Nothing. */ VOID NTAPI @@ -479,8 +662,25 @@ SeFreePrivileges(IN PPRIVILEGE_SET Privileges) ExFreePoolWithTag(Privileges, TAG_PRIVILEGE_SET); } -/* - * @implemented +/** + * @brief + * Checks if a set of privileges exist and match within a + * security subject context. + * + * @param[in] Privileges + * A set of privileges where the check must be performed + * against the subject context. + * + * @param[in] SubjectContext + * A subject security context. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if all the privileges do exist and match + * with the ones specified by the caller and subject + * context, FALSE otherwise. */ BOOLEAN NTAPI @@ -512,8 +712,20 @@ SePrivilegeCheck(PPRIVILEGE_SET Privileges, PreviousMode); } -/* - * @implemented +/** + * @brief + * Checks if a single privilege is present in the context + * of the calling thread. + * + * @param[in] PrivilegeValue + * The specific privilege to be checked. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if the privilege is present, FALSE + * otherwise. */ BOOLEAN NTAPI @@ -551,6 +763,28 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue, return Result; } +/** + * @brief + * Checks a privileged object if such object has + * the specific privilege submitted by the caller. + * + * @param[in] PrivilegeValue + * A privilege to be checked against the one from + * the object. + * + * @param[in] ObjectHandle + * A handle to any kind of object. + * + * @param[in] DesiredAccess + * Desired access right mask requested by the caller. + * + * @param[in] PreviousMode + * Processor level access mode. + * + * @return + * Returns TRUE if the privilege is present, FALSE + * otherwise. + */ BOOLEAN NTAPI SeCheckPrivilegedObject(IN LUID PrivilegeValue, @@ -591,6 +825,30 @@ SeCheckPrivilegedObject(IN LUID PrivilegeValue, /* SYSTEM CALLS ***************************************************************/ +/** + * @brief + * Checks a client access token if it has the required set of + * privileges. + * + * @param[in] ClientToken + * A handle to an access client token. + * + * @param[in] RequiredPrivileges + * A set of required privileges to be checked against the privileges + * of the access token. + * + * @param[out] Result + * The result, as a boolean value. If TRUE, the token has all the required + * privileges, FALSE otherwise. + * + * @return + * Returns STATUS_SUCCESS if the function has completed successfully. + * STATUS_INVALID_PARAMETER is returned if the set array of required + * privileges has a bogus number of privileges, that is, the array + * has a count of privileges that exceeds the maximum threshold + * (or in other words, an integer overflow). A failure NTSTATUS code + * is returned otherwise. + */ NTSTATUS NTAPI NtPrivilegeCheck(IN HANDLE ClientToken, diff --git a/ntoskrnl/se/sd.c b/ntoskrnl/se/sd.c index 72eff599ce5..fc9369d1808 100644 --- a/ntoskrnl/se/sd.c +++ b/ntoskrnl/se/sd.c @@ -1,10 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/sd.c - * PURPOSE: Security manager - * - * PROGRAMMERS: David Welch + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security descriptors (SDs) implementation support + * COPYRIGHT: Copyright David Welch */ /* INCLUDES *******************************************************************/ @@ -25,6 +23,14 @@ PSECURITY_DESCRIPTOR SeSystemAnonymousLogonSd = NULL; /* PRIVATE FUNCTIONS **********************************************************/ +/** + * @brief + * Initializes the known security descriptors in the system. + * + * @return + * Returns TRUE if all the security descriptors have been initialized, + * FALSE otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -124,6 +130,26 @@ SepInitSDs(VOID) return TRUE; } +/** + * @brief + * Sets a "World" security descriptor. + * + * @param[in] SecurityInformation + * Security information details, alongside with the security + * descriptor to set the World SD. + * + * @param[in] SecurityDescriptor + * A security descriptor buffer. + * + * @param[in] BufferLength + * Length size of the buffer. + * + * @return + * Returns STATUS_SUCCESS if the World security descriptor has been + * set. STATUS_ACCESS_DENIED is returned if the caller hasn't + * provided security information details thus the SD cannot + * be set. + */ NTSTATUS NTAPI SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, @@ -217,6 +243,23 @@ SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, /* PUBLIC FUNCTIONS ***********************************************************/ +/** + * @brief + * Determines the size of a SID. + * + * @param[in] Sid + * A security identifier where its size is to be determined. + * + * @param[in,out] OutSAC + * The returned sub authority count of the security + * identifier. + * + * @param[in] ProcessorMode + * Processor level access mode. + * + * @return + * Returns the size length of a security identifier (SID). + */ static ULONG DetermineSIDSize( @@ -248,6 +291,21 @@ DetermineSIDSize( return Size; } +/** + * @brief + * Determines the size of an ACL. + * + * @param[in] Acl + * An access control list where its size is to be + * determined. + * + * @param[in] ProcessorMode + * Processor level access mode. + * + * @return + * Returns the size length of a an access control + * list (ACL). + */ static ULONG DetermineACLSize( @@ -267,6 +325,37 @@ DetermineACLSize( return Size; } +/** + * @brief + * Captures a security descriptor. + * + * @param[in] _OriginalSecurityDescriptor + * An already existing and valid security descriptor + * to be captured. + * + * @param[in] CurrentMode + * Processor level access mode. + * + * @param[in] PoolType + * Pool type to be used when allocating the captured + * buffer. + * + * @param[in] CaptureIfKernel + * Set this to TRUE if capturing is done within the + * kernel. + * + * @param[out] CapturedSecurityDescriptor + * The captured security descriptor. + * + * @return + * Returns STATUS_SUCCESS if the operations have been + * completed successfully and that the security descriptor + * has been captured. STATUS_UNKNOWN_REVISION is returned + * if the security descriptor has an unknown revision. + * STATUS_INSUFFICIENT_RESOURCES is returned if memory + * pool allocation for the captured buffer has failed. + * A failure NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SeCaptureSecurityDescriptor( @@ -452,8 +541,32 @@ SeCaptureSecurityDescriptor( return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Queries information details about a security + * descriptor. + * + * @param[in] SecurityInformation + * Security information details to be queried + * from a security descriptor. + * + * @param[out] SecurityDescriptor + * The returned security descriptor with security information + * data. + * + * @param[in,out] Length + * The returned length of a security descriptor. + * + * @param[in,out] ObjectsSecurityDescriptor + * The returned object security descriptor. + * + * @return + * Returns STATUS_SUCCESS if the operations have been + * completed successfully and that the specific information + * about the security descriptor has been queried. + * STATUS_BUFFER_TOO_SMALL is returned if the buffer size + * is too small to contain the queried info about the + * security descriptor. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -600,8 +713,22 @@ SeQuerySecurityDescriptorInfo( return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Releases a captured security descriptor buffer. + * + * @param[in] CapturedSecurityDescriptor + * The captured security descriptor to be freed. + * + * @param[in] CurrentMode + * Processor level access mode. + * + * @param[in] CaptureIfKernelMode + * Set this to TRUE if the releasing is to be done within + * the kernel. + * + * @return + * Returns STATUS_SUCCESS. */ NTSTATUS NTAPI @@ -627,8 +754,32 @@ SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Modifies some information data about a security + * descriptor. + * + * @param[in] Object + * If specified, the function will use this arbitrary + * object that points to an object security descriptor. + * + * @param[in] SecurityInformation + * Security information details to be set. + * + * @param[in] SecurityDescriptor + * A security descriptor where its info is to be changed. + * + * @param[in,out] ObjectsSecurityDescriptor + * The returned pointer to security descriptor objects. + * + * @param[in] PoolType + * Pool type for the new security descriptor to allocate. + * + * @param[in] GenericMapping + * The generic mapping of access rights masks. + * + * @return + * See SeSetSecurityDescriptorInfoEx. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -652,8 +803,42 @@ SeSetSecurityDescriptorInfo( GenericMapping); } -/* - * @implemented +/** + * @brief + * An extended function that sets new information data to + * a security descriptor. + * + * @param[in] Object + * If specified, the function will use this arbitrary + * object that points to an object security descriptor. + * + * @param[in] SecurityInformation + * Security information details to be set. + * + * @param[in] SecurityDescriptor + * A security descriptor where its info is to be changed. + * + * @param[in,out] ObjectsSecurityDescriptor + * The returned pointer to security descriptor objects. + * + * @param[in] AutoInheritFlags + * Flags bitmask inheritation, influencing how the security + * descriptor can be inherited and if it can be in the first + * place. + * + * @param[in] PoolType + * Pool type for the new security descriptor to allocate. + * + * @param[in] GenericMapping + * The generic mapping of access rights masks. + * + * @return + * Returns STATUS_SUCCESS if the operations have been + * completed without problems and that new info has been + * set to the security descriptor. STATUS_NO_SECURITY_ON_OBJECT + * is returned if the object does not have a security descriptor. + * STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation + * for the new security descriptor with new info set has failed. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -795,9 +980,22 @@ SeSetSecurityDescriptorInfoEx( return STATUS_SUCCESS; } - -/* - * @implemented +/** + * @brief + * Determines if a security descriptor is valid according + * to the general security requirements and conditions + * set by the kernel. + * + * @param[in] Length + * The length of a security descriptor. + * + * @param[in] _SecurityDescriptor + * A security descriptor where its properties are to be + * checked for validity. + * + * @return + * Returns TRUE if the given security descriptor is valid, + * FALSE otherwise. */ BOOLEAN NTAPI SeValidSecurityDescriptor(IN ULONG Length, @@ -932,8 +1130,15 @@ SeValidSecurityDescriptor(IN ULONG Length, return TRUE; } -/* - * @implemented +/** + * @brief + * Frees a security descriptor. + * + * @param[in] SecurityDescriptor + * A security descriptor to be freed from memory. + * + * @return + * Returns STATUS_SUCCESS. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -952,8 +1157,58 @@ SeDeassignSecurity( return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * An extended function that assigns a security descriptor for a new + * object. + * + * @param[in] _ParentDescriptor + * A security descriptor of the parent object that is being + * created. + * + * @param[in] _ExplicitDescriptor + * An explicit security descriptor that is applied to a new + * object. + * + * @param[out] NewDescriptor + * The new allocated security descriptor. + * + * @param[in] ObjectType + * The type of the new object. + * + * @param[in] IsDirectoryObject + * Set this to TRUE if the newly created object is a directory + * object, otherwise set this to FALSE. + * + * @param[in] AutoInheritFlags + * Automatic inheritance flags that influence how access control + * entries within ACLs from security descriptors are inherited. + * + * @param[in] SubjectContext + * Security subject context of the new object. + * + * @param[in] GenericMapping + * Generic mapping of access mask rights. + * + * @param[in] PoolType + * This parameter is unused. + * + * @return + * Returns STATUS_SUCCESS if the operations have been completed + * successfully and that the security descriptor has been + * assigned to the new object. STATUS_NO_TOKEN is returned + * if the caller hasn't supplied a valid argument to a security + * subject context. STATUS_INVALID_OWNER is returned if the caller + * hasn't supplied a parent descriptor that belongs to the main + * user (owner). STATUS_INVALID_PRIMARY_GROUP is returned + * by the same reason as with the previous NTSTATUS code. + * The two NTSTATUS codes are returned if the calling thread + * stated that the owner and/or group is defaulted to the + * parent descriptor (SEF_DEFAULT_OWNER_FROM_PARENT and/or + * SEF_DEFAULT_GROUP_FROM_PARENT respectively). + * STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation + * for the descriptor buffer has failed. A failure NTSTATUS is returned + * otherwise. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -1244,8 +1499,36 @@ SeAssignSecurityEx( return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Assigns a security descriptor for a new object. + * + * @param[in] ParentDescriptor + * A security descriptor of the parent object that is being + * created. + * + * @param[in] ExplicitDescriptor + * An explicit security descriptor that is applied to a new + * object. + * + * @param[out] NewDescriptor + * The new allocated security descriptor. + * + * @param[in] IsDirectoryObject + * Set this to TRUE if the newly created object is a directory + * object, otherwise set this to FALSE. + * + * @param[in] SubjectContext + * Security subject context of the new object. + * + * @param[in] GenericMapping + * Generic mapping of access mask rights. + * + * @param[in] PoolType + * This parameter is unused. + * + * @return + * See SeAssignSecurityEx. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS @@ -1272,8 +1555,23 @@ SeAssignSecurity( PoolType); } -/* - * @implemented +/** + * @brief + * Computes the quota size of a security descriptor. + * + * @param[in] SecurityDescriptor + * A security descriptor. + * + * @param[out] QuotaInfoSize + * The returned quota size of the given security descriptor to + * the caller. The function may return 0 to this parameter if + * the descriptor doesn't have a group or a discretionary + * access control list (DACL) even. + * + * @return + * Returns STATUS_SUCCESS if the quota size of a security + * descriptor has been computed successfully. STATUS_UNKNOWN_REVISION + * is returned if the security descriptor has an invalid revision. */ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS diff --git a/ntoskrnl/se/semgr.c b/ntoskrnl/se/semgr.c index 4e217c8a982..961177eaa87 100644 --- a/ntoskrnl/se/semgr.c +++ b/ntoskrnl/se/semgr.c @@ -1,10 +1,11 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/semgr.c - * PURPOSE: Security manager - * - * PROGRAMMERS: No programmer listed. + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security manager infrastructure + * COPYRIGHT: Copyright Timo Kreuzer + * Copyright Eric Kohl + * Copyright Aleksey Bragin + * Copyright Alex Ionescu */ /* INCLUDES *******************************************************************/ @@ -26,6 +27,14 @@ extern ERESOURCE SepSubjectContextLock; /* PRIVATE FUNCTIONS **********************************************************/ +/** + * @brief + * Initializes all the security exports upon initialization phase of + * the module. + * + * @return + * Returns TRUE. + */ static CODE_SEG("INIT") BOOLEAN @@ -91,7 +100,15 @@ SepInitExports(VOID) return TRUE; } - +/** + * @brief + * Handles the phase 0 procedure of the SRM initialization. + * + * @return + * Returns TRUE if the phase 0 initialization has succeeded and that + * we can proceed further with next initialization phase, FALSE + * otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -137,6 +154,14 @@ SepInitializationPhase0(VOID) return TRUE; } +/** + * @brief + * Handles the phase 1 procedure of the SRM initialization. + * + * @return + * Returns TRUE if the phase 1 initialization has succeeded, FALSE + * otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -245,6 +270,15 @@ SepInitializationPhase1(VOID) return TRUE; } +/** + * @brief + * Main security manager initialization function. + * + * @return + * Returns a boolean value according to the phase initialization + * routine that handles it. If TRUE, the routine deems the initialization + * phase as complete, FALSE otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -275,6 +309,43 @@ SeInitSystem(VOID) } } +/** + * @brief + * Internal function that is responsible for querying, deleting, assigning and + * setting a security descriptor for an object in the NT kernel. It is the default + * security method for objects regarding the security context of objects. + * + * @param[in] Object + * The object that has the default security method, which the function has been + * called upon. + * + * @param[in] OperationType + * Operation type to perform to that object. + * + * @param[in] SecurityInformation + * Auxiliary security information of the object. + * + * @param[in] SecurityDescriptor + * A security descriptor. This SD is used accordingly to the operation type + * requested by the caller. + * + * @param[in] ReturnLength + * The length size of the queried security descriptor, in bytes. + * + * @param[in] OldSecurityDescriptor + * The old SD that belonged to the object, in case we're either deleting + * or replacing it. + * + * @param[in] PoolType + * Pool type allocation for the security descriptor. + * + * @param[in] GenericMapping + * The generic mapping of access rights masks for the object. + * + * @return + * Returns STATUS_SUCCESS if the specific operation tasked has been + * completed. Otherwise a failure NTSTATUS code is returned. + */ NTSTATUS NTAPI SeDefaultObjectMethod(IN PVOID Object, @@ -336,6 +407,20 @@ SeDefaultObjectMethod(IN PVOID Object, return STATUS_SUCCESS; } +/** + * @brief + * Queries the access mask from a security information context. + * + * @param[in] SecurityInformation + * The security information context where the access mask is to be + * gathered. + * + * @param[out] DesiredAccess + * The queried access mask right. + * + * @return + * Nothing. + */ VOID NTAPI SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, @@ -355,6 +440,19 @@ SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, } } +/** + * @brief + * Sets the access mask for a security information context. + * + * @param[in] SecurityInformation + * The security information context to apply a new access right. + * + * @param[out] DesiredAccess + * The returned access mask right. + * + * @return + * Nothing. + */ VOID NTAPI SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, @@ -378,6 +476,30 @@ SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, } } +/** + * @unimplemented + * @brief + * Report a security event to the security manager. + * + * @param[in] Flags + * Flags that influence how the event should be reported. + * + * @param[in] SourceName + * A Unicode string that represents the source name of the event. + * + * @param[in] UserSid + * The SID that represents a user that initiated the reporting. + * + * @param[in] AuditParameters + * An array of parameters for auditing purposes. This is used + * for reporting the event which the security manager will take + * care subsequently of doing eventual security auditing. + * + * @return + * Returns STATUS_SUCCESS if the security event has been reported. + * STATUS_INVALID_PARAMETER is returned if one of the parameters + * do not satisfy the requirements expected by the function. + */ NTSTATUS NTAPI SeReportSecurityEvent( @@ -447,6 +569,28 @@ SeReportSecurityEvent( return STATUS_SUCCESS; } +/** + * @unimplemented + * @brief + * Sets an array of audit parameters for later security auditing use. + * + * @param[in,out] AuditParameters + * An array of audit parameters to be set. + * + * @param[in] Type + * The type of audit parameters to be set. + * + * @param[in] Index + * Index number that represents an instance of an audit parameters. + * Such index must be within the maximum range of audit parameters. + * + * @param[in] Data + * An arbitrary buffer data that is bounds to what kind of audit parameter + * type must be set. + * + * @return + * To be added... + */ _Const_ NTSTATUS NTAPI diff --git a/ntoskrnl/se/sid.c b/ntoskrnl/se/sid.c index 24a7a9b526e..89fd380648c 100644 --- a/ntoskrnl/se/sid.c +++ b/ntoskrnl/se/sid.c @@ -1,10 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/se/sid.c - * PURPOSE: Security manager - * - * PROGRAMMERS: David Welch + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security Identifier (SID) implementation support and handling + * COPYRIGHT: Copyright David Welch */ /* INCLUDES *******************************************************************/ @@ -54,6 +52,13 @@ PSID SeNetworkServiceSid = NULL; /* FUNCTIONS ******************************************************************/ +/** + * @brief + * Frees all the known initialized SIDs in the system from the memory. + * + * @return + * Nothing. + */ VOID NTAPI FreeInitializedSids(VOID) @@ -88,6 +93,14 @@ FreeInitializedSids(VOID) if (SeAnonymousLogonSid) ExFreePoolWithTag(SeAnonymousLogonSid, TAG_SID); } +/** + * @brief + * Initializes all the SIDs known in the system. + * + * @return + * Returns TRUE if all the SIDs have been initialized, + * FALSE otherwise. + */ CODE_SEG("INIT") BOOLEAN NTAPI @@ -263,6 +276,31 @@ SepInitSecurityIDs(VOID) return TRUE; } +/** + * @brief + * Captures a SID. + * + * @param[in] InputSid + * A valid security identifier to be captured. + * + * @param[in] AccessMode + * Processor level access mode. + * + * @param[in] PoolType + * Pool memory type for the captured SID to assign upon + * allocation. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the capturing is done within the kernel. + * Otherwise the capturing is done in a kernel mode driver. + * + * @param[out] CapturedSid + * The captured security identifier, returned to the caller. + * + * @return + * Returns STATUS_SUCCESS if the SID was captured. STATUS_INSUFFICIENT_RESOURCES + * is returned if memory pool allocation for the captured SID has failed. + */ NTSTATUS NTAPI SepCaptureSid(IN PSID InputSid, @@ -331,6 +369,23 @@ SepCaptureSid(IN PSID InputSid, return STATUS_SUCCESS; } +/** + * @brief + * Releases a captured SID. + * + * @param[in] CapturedSid + * The captured SID to be released. + * + * @param[in] AccessMode + * Processor level access mode. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the releasing is done within the kernel. + * Otherwise the releasing is done in a kernel mode driver. + * + * @return + * Nothing. + */ VOID NTAPI SepReleaseSid(IN PSID CapturedSid, @@ -347,6 +402,52 @@ SepReleaseSid(IN PSID CapturedSid, } } +/** + * @brief + * Captures a SID with attributes. + * + * @param[in] SrcSidAndAttributes + * Source of the SID with attributes to be captured. + * + * @param[in] AttributeCount + * The number count of attributes, in total. + * + * @param[in] PreviousMode + * Processor access level mode. + * + * @param[in] AllocatedMem + * The allocated memory buffer for the captured SID. If the caller + * supplies no allocated block of memory then the function will + * allocate some buffer block of memory for the captured SID + * automatically. + * + * @param[in] AllocatedLength + * The length of the buffer that points to the allocated memory, + * in bytes. + * + * @param[in] PoolType + * The pool type for the captured SID and attributes to assign. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the capturing is done within the kernel. + * Otherwise the capturing is done in a kernel mode driver. + * + * @param[out] CapturedSidAndAttributes + * The captured SID and attributes. + * + * @param[out] ResultLength + * The length of the captured SID and attributes, in bytes. + * + * @return + * Returns STATUS_SUCCESS if SID and attributes capturing + * has been completed successfully. STATUS_INVALID_PARAMETER + * is returned if the count of attributes exceeds the maximum + * threshold that the kernel can permit. STATUS_INSUFFICIENT_RESOURCES + * is returned if memory pool allocation for the captured SID has failed. + * STATUS_BUFFER_TOO_SMALL is returned if the length of the allocated + * buffer is less than the required size. A failure NTSTATUS code is + * returned otherwise. + */ NTSTATUS NTAPI SeCaptureSidAndAttributesArray( @@ -548,6 +649,23 @@ SeCaptureSidAndAttributesArray( return Status; } +/** + * @brief + * Releases a captured SID with attributes. + * + * @param[in] CapturedSidAndAttributes + * The captured SID with attributes to be released. + * + * @param[in] AccessMode + * Processor access level mode. + * + * @param[in] CaptureIfKernel + * If set to TRUE, the releasing is done within the kernel. + * Otherwise the releasing is done in a kernel mode driver. + * + * @return + * Nothing. + */ VOID NTAPI SeReleaseSidAndAttributesArray( @@ -564,5 +682,4 @@ SeReleaseSidAndAttributesArray( } } - /* EOF */ diff --git a/ntoskrnl/se/srm.c b/ntoskrnl/se/srm.c index 90809a907e1..abdb7ee2fb7 100644 --- a/ntoskrnl/se/srm.c +++ b/ntoskrnl/se/srm.c @@ -13,9 +13,6 @@ #define NDEBUG #include -extern LUID SeSystemAuthenticationId; -extern LUID SeAnonymousAuthenticationId; - /* PRIVATE DEFINITIONS ********************************************************/ typedef struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION @@ -42,6 +39,9 @@ SepRmCreateLogonSession( /* GLOBALS ********************************************************************/ +extern LUID SeSystemAuthenticationId; +extern LUID SeAnonymousAuthenticationId; + HANDLE SeRmCommandPort; HANDLE SeLsaInitEvent; @@ -62,7 +62,6 @@ KGUARDED_MUTEX SepRmDbLock; PSEP_LOGON_SESSION_REFERENCES SepLogonSessions = NULL; PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION SepLogonNotifications = NULL; - /* PRIVATE FUNCTIONS **********************************************************/ /** @@ -163,7 +162,15 @@ Cleanup: return Status; } - +/** + * @brief + * Manages the phase 0 initialization of the security reference + * monitoring module of the kernel. + * + * @return + * Returns TRUE when phase 0 initialization has completed without + * problems, FALSE otherwise. + */ BOOLEAN NTAPI SeRmInitPhase0(VOID) @@ -190,7 +197,15 @@ SeRmInitPhase0(VOID) return TRUE; } - +/** + * @brief + * Manages the phase 1 initialization of the security reference + * monitoring module of the kernel. + * + * @return + * Returns TRUE when phase 1 initialization has completed without + * problems, FALSE otherwise. + */ BOOLEAN NTAPI SeRmInitPhase1(VOID) @@ -247,6 +262,13 @@ SeRmInitPhase1(VOID) return TRUE; } +/** + * @brief + * Initializes the local security authority audit bounds. + * + * @return + * Nothing. + */ static VOID SepAdtInitializeBounds(VOID) @@ -285,7 +307,18 @@ SepAdtInitializeBounds(VOID) SepAdtMaxListLength = ListBounds.MaxLength; } - +/** + * @brief + * Sets an audit event for future security auditing monitoring. + * + * @param[in,out] Message + * The reference monitoring API message. It is used to determine + * if the right API message number is provided, RmAuditSetCommand + * in this case. + * + * @return + * Returns STATUS_SUCCESS. + */ static NTSTATUS SepRmSetAuditEvent( @@ -456,6 +489,24 @@ SepRmRemoveLogonSessionFromToken( return STATUS_SUCCESS; } +/** + * @brief + * Creates a logon session. The security reference monitoring (SRM) + * module of Executive uses this as an internal kernel data for + * respective logon sessions management within the kernel, + * as in form of a SEP_LOGON_SESSION_REFERENCES data structure. + * + * @param[in,out] LogonLuid + * A logon ID represented as a LUID. This LUID is used to create + * our logon session and add it to the sessions database. + * + * @return + * Returns STATUS_SUCCESS if the logon has been created successfully. + * STATUS_LOGON_SESSION_EXISTS is returned if a logon session with + * the pointed logon ID in the call already exists. + * STATUS_INSUFFICIENT_RESOURCES is returned if logon session allocation + * has failed because of lack of memory pool resources. + */ static NTSTATUS SepRmCreateLogonSession( @@ -627,7 +678,19 @@ Leave: return Status; } - +/** + * @brief + * References a logon session. + * + * @param[in,out] LogonLuid + * A valid LUID that points to the logon session in the database that + * we're going to reference it. + * + * @return + * Returns STATUS_SUCCESS if the logon has been referenced. + * STATUS_NO_SUCH_LOGON_SESSION is returned if the session couldn't be + * found otherwise. + */ NTSTATUS SepRmReferenceLogonSession( PLUID LogonLuid) @@ -667,6 +730,22 @@ SepRmReferenceLogonSession( return STATUS_NO_SUCH_LOGON_SESSION; } +/** + * @brief + * Cleans the DOS device map directory of a logon + * session. + * + * @param[in] LogonLuid + * A logon session ID where its DOS device map directory + * is to be cleaned. + * + * @return + * Returns STATUS_SUCCESS if the device map directory has been + * successfully cleaned from the logon session. STATUS_INVALID_PARAMETER + * is returned if the caller hasn't submitted any logon ID. STATUS_NO_MEMORY + * is returned if buffer allocation for links has failed. A failure + * NTSTATUS code is returned otherwise. + */ static NTSTATUS SepCleanupLUIDDeviceMapDirectory( @@ -910,7 +989,21 @@ AllocateLinksAgain: return Status; } - +/** + * @brief + * De-references a logon session. If the session has a reference + * count of 0 by the time the function has de-referenced the logon, + * that means the session is no longer used and can be safely deleted + * from the logon sessions database. + * + * @param[in,out] LogonLuid + * A logon session ID to de-reference. + * + * @return + * Returns STATUS_SUCCESS if the logon session has been de-referenced + * without issues. STATUS_NO_SUCH_LOGON_SESSION is returned if no + * such logon exists otherwise. + */ NTSTATUS SepRmDereferenceLogonSession( PLUID LogonLuid) @@ -965,7 +1058,18 @@ SepRmDereferenceLogonSession( return STATUS_NO_SUCH_LOGON_SESSION; } - +/** + * @brief + * Main SRM server thread initialization function. It deals + * with security manager and LSASS port connection, thus + * thereby allowing communication between the kernel side + * (the SRM) and user mode side (the LSASS) of the security + * world of the operating system. + * + * @return + * Returns TRUE if command server connection between SRM + * and LSASS has succeeded, FALSE otherwise. + */ BOOLEAN NTAPI SepRmCommandServerThreadInit(VOID) @@ -1108,6 +1212,15 @@ Cleanup: return Result; } +/** + * @brief + * Manages the SRM server API commands, that is, receiving such API + * command messages from the user mode side of the security standpoint, + * the LSASS. + * + * @return + * Nothing. + */ VOID NTAPI SepRmCommandServerThread( @@ -1211,8 +1324,23 @@ SepRmCommandServerThread( /* PUBLIC FUNCTIONS ***********************************************************/ -/* - * @unimplemented +/** + * @brief + * Retrieves the DOS device map from a logon session. + * + * @param[in] LogonId + * A valid logon session ID. + * + * @param[out] DeviceMap + * The returned device map buffer from the logon session. + * + * @return + * Returns STATUS_SUCCESS if the device map could be gathered + * from the logon session. STATUS_INVALID_PARAMETER is returned if + * one of the parameters aren't initialized (that is, the caller has + * submitted a NULL pointer variable). STATUS_NO_SUCH_LOGON_SESSION is + * returned if no such session could be found. A failure NTSTATUS code + * is returned otherwise. */ NTSTATUS NTAPI @@ -1425,9 +1553,20 @@ SeMarkLogonSessionForTerminationNotification( return STATUS_SUCCESS; } - -/* - * @implemented +/** + * @brief + * Registers a callback that will be called once a logon session + * terminates. + * + * @param[in] CallbackRoutine + * Callback routine address. + * + * @return + * Returns STATUS_SUCCESS if the callback routine was registered + * successfully. STATUS_INVALID_PARAMETER is returned if the caller + * did not provide a callback routine. STATUS_INSUFFICIENT_RESOURCES + * is returned if the callback notification data couldn't be allocated + * because of lack of memory pool resources. */ NTSTATUS NTAPI @@ -1464,9 +1603,19 @@ SeRegisterLogonSessionTerminatedRoutine( return STATUS_SUCCESS; } - -/* - * @implemented +/** + * @brief + * Un-registers a callback routine, previously registered by + * SeRegisterLogonSessionTerminatedRoutine function. + * + * @param[in] CallbackRoutine + * Callback routine address to un-register. + * + * @return + * Returns STATUS_SUCCESS if the callback routine was un-registered + * successfully. STATUS_INVALID_PARAMETER is returned if the caller + * did not provide a callback routine. STATUS_NOT_FOUND is returned + * if the callback notification item couldn't be found. */ NTSTATUS NTAPI @@ -1520,3 +1669,5 @@ SeUnregisterLogonSessionTerminatedRoutine( return Status; } + +/* EOF */ diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c index 46dbb725a89..3dd0cb0fd6e 100644 --- a/ntoskrnl/se/token.c +++ b/ntoskrnl/se/token.c @@ -467,6 +467,22 @@ SepImpersonateAnonymousToken( return Status; } +/** + * @brief + * Updates the token's flags based upon the privilege that the token + * has been granted. The flag can either be taken out or given to the token + * if the attributes of the specified privilege is enabled or not. + * + * @param[in,out] Token + * The token where the flags are to be changed. + * + * @param[in] Index + * The index count which represents the total sum of privileges. The count in question + * MUST NOT exceed the expected privileges count of the token. + * + * @return + * Nothing. + */ static VOID SepUpdateSinglePrivilegeFlagToken( @@ -518,6 +534,18 @@ SepUpdateSinglePrivilegeFlagToken( } } +/** + * @brief + * Updates the token's flags based upon the privilege that the token + * has been granted. The function uses the private helper, SepUpdateSinglePrivilegeFlagToken, + * in order to update the flags of a token. + * + * @param[in,out] Token + * The token where the flags are to be changed. + * + * @return + * Nothing. + */ static VOID SepUpdatePrivilegeFlagsToken( @@ -528,11 +556,25 @@ SepUpdatePrivilegeFlagsToken( /* Loop all privileges */ for (i = 0; i < Token->PrivilegeCount; i++) { - /* Updates the flags dor this privilege */ + /* Updates the flags for this privilege */ SepUpdateSinglePrivilegeFlagToken(Token, i); } } +/** + * @brief + * Removes a privilege from the token. + * + * @param[in,out] Token + * The token where the privilege is to be removed. + * + * @param[in] Index + * The index count which represents the number position of the privilege + * we want to remove. + * + * @return + * Nothing. + */ static VOID SepRemovePrivilegeToken( @@ -556,6 +598,17 @@ SepRemovePrivilegeToken( Token->PrivilegeCount--; } +/** + * @unimplemented + * @brief + * Frees (de-allocates) the proxy data memory block of a token. + * + * @param[in,out] ProxyData + * The proxy data to be freed. + * + * @return + * Nothing. + */ VOID NTAPI SepFreeProxyData(PVOID ProxyData) @@ -563,6 +616,20 @@ SepFreeProxyData(PVOID ProxyData) UNIMPLEMENTED; } +/** + * @unimplemented + * @brief + * Copies the proxy data from the source into the destination of a token. + * + * @param[out] Dest + * The destination path where the proxy data is to be copied to. + * + * @param[out] Src + * The source path where the proxy data is be copied from. + * + * @return + * To be added... + */ NTSTATUS NTAPI SepCopyProxyData(PVOID* Dest, @@ -572,6 +639,27 @@ SepCopyProxyData(PVOID* Dest, return STATUS_NOT_IMPLEMENTED; } +/** + * @brief + * Replaces the old access token of a process (pointed by the EPROCESS kernel structure) with a + * new access token. The new access token must be a primary token for use. + * + * @param[in] Process + * The process instance where its access token is about to be replaced. + * + * @param[in] NewAccessToken + * The new token that it's going to replace the old one. + * + * @param[out] OldAccessToken + * The returned old token that's been replaced, which the caller can do anything. + * + * @return + * Returns STATUS_SUCCESS if the exchange operation between tokens has completed successfully. + * STATUS_BAD_TOKEN_TYPE is returned if the new token is not a primary one so that we cannot + * exchange it with the old one from the process. STATUS_TOKEN_ALREADY_IN_USE is returned if + * both tokens aren't equal which means one of them has different properties (groups, privileges, etc.) + * and as such one of them is currently in use. A failure NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SeExchangePrimaryToken( @@ -652,6 +740,16 @@ SeExchangePrimaryToken( return STATUS_SUCCESS; } +/** + * @brief + * Removes the primary token of a process. + * + * @param[in, out] Process + * The process instance with the access token to be removed. + * + * @return + * Nothing. + */ VOID NTAPI SeDeassignPrimaryToken(PEPROCESS Process) @@ -668,6 +766,19 @@ SeDeassignPrimaryToken(PEPROCESS Process) ObDereferenceObject(OldToken); } +/** + * @brief + * Computes the length size of a SID. + * + * @param[in] Count + * Total count of entries that have SIDs in them (that being PSID_AND_ATTRIBUTES in this context). + * + * @param[in] Src + * Source that points to the attributes and SID entry structure. + * + * @return + * Returns the total length of a SID size. + */ static ULONG RtlLengthSidAndAttributes(ULONG Count, PSID_AND_ATTRIBUTES Src) @@ -684,7 +795,35 @@ RtlLengthSidAndAttributes(ULONG Count, return uLength; } - +/** + * @brief + * Finds the primary group and default owner entity based on the submitted primary group instance + * and an access token. + * + * @param[in] Token + * Access token to begin the search query of primary group and default owner. + * + * @param[in] PrimaryGroup + * A primary group SID to be used for search query, determining if user & groups of a token + * and the submitted primary group do match. + * + * @param[in] DefaultOwner + * The default owner. If specified, it's used to determine if the token belongs to the actual user, + * that is, being the owner himself. + * + * @param[out] PrimaryGroupIndex + * Returns the primary group index. + * + * @param[out] DefaultOwnerIndex + * Returns the default owner index. + * + * @return + * Returns STATUS_SUCCESS if the find query operation has completed successfully and that at least one + * search result is requested by the caller. STATUS_INVALID_PARAMETER is returned if the caller hasn't requested + * any search result. STATUS_INVALID_OWNER is returned if the specified default user owner does not match with the other + * user from the token. STATUS_INVALID_PRIMARY_GROUP is returned if the specified default primary group does not match with the + * other group from the token. + */ static NTSTATUS SepFindPrimaryGroupAndDefaultOwner( _In_ PTOKEN Token, @@ -779,7 +918,37 @@ SepFindPrimaryGroupAndDefaultOwner( return STATUS_SUCCESS; } - +/** + * @brief + * Duplicates an access token, from an existing valid token. + * + * @param[in] Token + * Access token to duplicate. + * + * @param[in] ObjectAttributes + * Object attributes for the new token. + * + * @param[in] EffectiveOnly + * If set to TRUE, the function removes all the disabled privileges and groups of the token + * to duplicate. + * + * @param[in] TokenType + * Type of token. + * + * @param[in] Level + * Security impersonation level of a token. + * + * @param[in] PreviousMode + * The processor request level mode. + * + * @param[out] NewAccessToken + * The duplicated token. + * + * @return + * Returns STATUS_SUCCESS if the token has been duplicated. STATUS_INSUFFICIENT_RESOURCES is returned + * if memory pool allocation of the dynamic part of the token for duplication has failed due to the lack + * of memory resources. A failure NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SepDuplicateToken( @@ -1024,6 +1193,27 @@ Quit: return Status; } +/** + * @brief + * Subtracts a token in exchange of duplicating a new one. + * + * @param[in] ParentToken + * The parent access token for duplication. + * + * @param[out] Token + * The new duplicated token. + * + * @param[in] InUse + * Set this to TRUE if the token is about to be used immediately after the call execution + * of this function, FALSE otherwise. + * + * @param[in] SessionId + * Session ID for the token to be assigned. + * + * @return + * Returns STATUS_SUCCESS if token subtracting and duplication have completed successfully. + * A failure NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SeSubProcessToken(IN PTOKEN ParentToken, @@ -1068,6 +1258,21 @@ SeSubProcessToken(IN PTOKEN ParentToken, return Status; } +/** + * @brief + * Checks if the token is a child of the other token + * of the current process that the calling thread is invoking this function. + * + * @param[in] Token + * An access token to determine if it's a child or not. + * + * @param[out] IsChild + * The returned boolean result. + * + * @return + * Returns STATUS_SUCCESS when the function finishes its operation. STATUS_UNSUCCESSFUL is + * returned if primary token of the current calling process couldn't be referenced otherwise. + */ NTSTATUS NTAPI SeIsTokenChild(IN PTOKEN Token, @@ -1101,6 +1306,21 @@ SeIsTokenChild(IN PTOKEN Token, return STATUS_SUCCESS; } +/** + * @brief + * Checks if the token is a sibling of the other token of + * the current process that the calling thread is invoking this function. + * + * @param[in] Token + * An access token to determine if it's a sibling or not. + * + * @param[out] IsSibling + * The returned boolean result. + * + * @return + * Returns STATUS_SUCCESS when the function finishes its operation. STATUS_UNSUCCESSFUL is + * returned if primary token of the current calling process couldn't be referenced otherwise. + */ NTSTATUS NTAPI SeIsTokenSibling(IN PTOKEN Token, @@ -1140,6 +1360,26 @@ SeIsTokenSibling(IN PTOKEN Token, return STATUS_SUCCESS; } +/** + * @brief + * Copies an existing access token (technically duplicating a new one). + * + * @param[in] Token + * Token to copy. + * + * @param[in] Level + * Impersonation security level to assign to the newly copied token. + * + * @param[in] PreviousMode + * Processor request level mode. + * + * @param[out] NewToken + * The newly copied token. + * + * @return + * Returns STATUS_SUCCESS when token copying has finished successfully. A failure + * NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SeCopyClientToken(IN PACCESS_TOKEN Token, @@ -1169,6 +1409,18 @@ SeCopyClientToken(IN PACCESS_TOKEN Token, return Status; } +/** + * @brief + * Internal function that deals with access token object destruction and deletion. + * The function is used solely by the object manager mechanism that handles the life + * management of a token object. + * + * @param[in] ObjectBody + * The object body that represents an access token object. + * + * @return + * Nothing. + */ VOID NTAPI SepDeleteToken(PVOID ObjectBody) @@ -1203,7 +1455,14 @@ SepDeleteToken(PVOID ObjectBody) ExFreePoolWithTag(AccessToken->DynamicPart, TAG_TOKEN_DYNAMIC); } - +/** + * @brief + * Internal function that initializes critical kernel data for access + * token implementation in SRM. + * + * @return + * Nothing. + */ CODE_SEG("INIT") VOID NTAPI @@ -1229,6 +1488,19 @@ SepInitializeTokenImplementation(VOID) ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType); } +/** + * @brief + * Assigns a primary access token to a given process. + * + * @param[in] Process + * Process where the token is about to be assigned. + * + * @param[in] Token + * The token to be assigned. + * + * @return + * Nothing. + */ VOID NTAPI SeAssignPrimaryToken(IN PEPROCESS Process, @@ -1249,6 +1521,80 @@ SeAssignPrimaryToken(IN PEPROCESS Process, ObInitializeFastReference(&Process->Token, Token); } +/** + * @brief + * Internal function responsible for access token object creation in the kernel. + * A fully created token objected is inserted into the token handle, thus the handle + * becoming a valid handle to an access token object and ready for use. + * + * @param[out] TokenHandle + * Valid token handle that's ready for use after token creation and object insertion. + * + * @param[in] PreviousMode + * Processor request level mode. + * + * @param[in] DesiredAccess + * Desired access right for the token object to be granted. This kind of access right + * impacts how the token can be used and who. + * + * @param[in] ObjectAttributes + * Object attributes for the token to be created. + * + * @param[in] TokenType + * Type of token to assign upon creation. + * + * @param[in] ImpersonationLevel + * Security impersonation level of token to assign upon creation. + * + * @param[in] AuthenticationId + * Authentication ID that represents the authentication information of the token. + * + * @param[in] ExpirationTime + * Expiration time of the token to assign. A value of -1 means that the token never + * expires and its life depends upon the amount of references this token object has. + * + * @param[in] User + * User entry to assign to the token. + * + * @param[in] GroupCount + * The total number of groups count for the token. + * + * @param[in] Groups + * The group entries for the token. + * + * @param[in] GroupsLength + * The length size of the groups array, pointed by the Groups parameter. + * + * @param[in] PrivilegeCount + * The total number of priivleges that the newly created token has. + * + * @param[in] Privileges + * The privileges for the token. + * + * @param[in] Owner + * The main user (or also owner) that represents the token that we create. + * + * @param[in] PrimaryGroup + * The main group that represents the token that we create. + * + * @param[in] DefaultDacl + * A discretionary access control list for the token. + * + * @param[in] TokenSource + * Source (or the origin) of the access token that creates it. + * + * @param[in] SystemToken + * If set to TRUE, the newly created token is a system token and only in charge + * by the internal system. The function directly returns a pointer to the + * created token object for system kernel use. Otherwise if set to FALSE, the + * function inserts the object to a handle making it a regular access token. + * + * @return + * Returns STATUS_SUCCESS if token creation has completed successfully. + * STATUS_INSUFFICIENT_RESOURCES is returned if the dynamic area of memory of the + * token hasn't been allocated because of lack of memory resources. A failure + * NTSTATUS code is returned otherwise. + */ NTSTATUS NTAPI SepCreateToken( @@ -1804,8 +2150,33 @@ SepCreateSystemAnonymousLogonTokenNoEveryone(VOID) /* PUBLIC FUNCTIONS ***********************************************************/ -/* +/** * @unimplemented + * @brief + * Filters an access token from an existing token, making it more restricted + * than the previous one. + * + * @param[in] ExistingToken + * An existing token for filtering. + * + * @param[in] Flags + * Privilege flag options. This parameter argument influences how the token + * is filtered. Such parameter can be 0. + * + * @param[in] SidsToDisable + * Array of SIDs to disable. + * + * @param[in] PrivilegesToDelete + * Array of privileges to delete. + * + * @param[in] RestrictedSids + * An array of restricted SIDs for the new filtered token. + * + * @param[out] FilteredToken + * The newly filtered token, returned to the caller. + * + * @return + * To be added... */ NTSTATUS NTAPI @@ -2189,8 +2560,18 @@ SeQueryInformationToken( return Status; } -/* - * @implemented +/** + * @brief + * Queries the session ID of an access token. + * + * @param[in] Token + * A valid access token where the session ID has to be gathered. + * + * @param[out] pSessionId + * The returned pointer to a session ID to the caller. + * + * @return + * Returns STATUS_SUCCESS. */ NTSTATUS NTAPI @@ -2210,8 +2591,18 @@ SeQuerySessionIdToken(IN PACCESS_TOKEN Token, return STATUS_SUCCESS; } -/* - * @implemented +/** + * @brief + * Queries the authentication ID of an access token. + * + * @param[in] Token + * A valid access token where the authentication ID has to be gathered. + * + * @param[out] pSessionId + * The returned pointer to an authentication ID to the caller. + * + * @return + * Returns STATUS_SUCCESS. */ NTSTATUS NTAPI @@ -2225,9 +2616,15 @@ SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, return STATUS_SUCCESS; } - -/* - * @implemented +/** + * @brief + * Gathers the security impersonation level of an access token. + * + * @param[in] Token + * A valid access token where the impersonation level has to be gathered. + * + * @return + * Returns the security impersonation level from a valid token. */ SECURITY_IMPERSONATION_LEVEL NTAPI @@ -2238,9 +2635,16 @@ SeTokenImpersonationLevel(IN PACCESS_TOKEN Token) return ((PTOKEN)Token)->ImpersonationLevel; } - -/* - * @implemented +/** + * @brief + * Gathers the token type of an access token. A token ca be either + * a primary token or impersonation token. + * + * @param[in] Token + * A valid access token where the token type has to be gathered. + * + * @return + * Returns the token type from a valid token. */ TOKEN_TYPE NTAPI SeTokenType(IN PACCESS_TOKEN Token) @@ -2250,9 +2654,18 @@ SeTokenType(IN PACCESS_TOKEN Token) return ((PTOKEN)Token)->TokenType; } - -/* - * @implemented +/** + * @brief + * Determines if a token is either an admin token or not. Such + * condition is checked based upon TOKEN_HAS_ADMIN_GROUP flag, + * which means if the respective access token belongs to an + * administrator group or not. + * + * @param[in] Token + * A valid access token to determine if such token is admin or not. + * + * @return + * Returns TRUE if the token is an admin one, FALSE otherwise. */ BOOLEAN NTAPI @@ -2265,8 +2678,16 @@ SeTokenIsAdmin(IN PACCESS_TOKEN Token) return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0; } -/* - * @implemented +/** + * @brief + * Determines if a token is restricted or not, based upon the token + * flags. + * + * @param[in] Token + * A valid access token to determine if such token is restricted. + * + * @return + * Returns TRUE if the token is restricted, FALSE otherwise. */ BOOLEAN NTAPI @@ -2277,10 +2698,20 @@ SeTokenIsRestricted(IN PACCESS_TOKEN Token) return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0; } -/* - * @implemented - * @note First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2, - * then finally re-introduced in Vista+. +/** + * @brief + * Determines if a token is write restricted, that is, nobody can write anything + * to it. + * + * @param[in] Token + * A valid access token to determine if such token is write restricted. + * + * @return + * Returns TRUE if the token is write restricted, FALSE otherwise. + * + * @remarks + * First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2, + * then finally re-introduced in Vista+. */ BOOLEAN NTAPI @@ -2393,8 +2824,37 @@ Quit: /* SYSTEM CALLS ***************************************************************/ -/* - * @implemented +/** + * @brief + * Queries a specific type of information in regard of an access token based upon + * the information class. The calling thread must have specific access rights in order + * to obtain specific information about the token. + * + * @param[in] TokenHandle + * A handle of a token where information is to be gathered. + * + * @param[in] TokenInformationClass + * Token information class. + * + * @param[out] TokenInformation + * A returned output buffer with token information, which information is arbitrarily upon + * the information class chosen. + * + * @param[in] TokenInformationLength + * Length of the token information buffer, in bytes. + * + * @param[out] ReturnLength + * If specified in the call, the function returns the total length size of the token + * information buffer.. + * + * @return + * Returns STATUS_SUCCESS if information querying has completed successfully. + * STATUS_BUFFER_TOO_SMALL is returned if the information length that represents + * the token information buffer is not greater than the required length. + * STATUS_INVALID_HANDLE is returned if the token handle is not a valid one. + * STATUS_INVALID_INFO_CLASS is returned if the information class is not a valid + * one (that is, the class doesn't belong to TOKEN_INFORMATION_CLASS). A failure + * NTSTATUS code is returned otherwise. */ _Must_inspect_result_ __kernel_entry @@ -2966,11 +3426,37 @@ NtQueryInformationToken( return Status; } - -/* - * NtSetTokenInformation: Partly implemented. - * Unimplemented: - * TokenOrigin, TokenDefaultDacl +/** + * @unimplemented + * @brief + * Sets (modifies) some specific information in regard of an access token. The + * calling thread must have specific access rights in order to modify token's + * information data. + * + * @param[in] TokenHandle + * A handle of a token where information is to be modified. + * + * @param[in] TokenInformationClass + * Token information class. + * + * @param[in] TokenInformation + * An arbitrary pointer to a buffer with token information to set. Such + * arbitrary buffer depends on the information class chosen that the caller + * wants to modify such information data of a token. + * + * @param[in] TokenInformationLength + * Length of the token information buffer, in bytes. + * + * @return + * Returns STATUS_SUCCESS if information setting has completed successfully. + * STATUS_INFO_LENGTH_MISMATCH is returned if the information length of the + * buffer is less than the required length. STATUS_INSUFFICIENT_RESOURCES is + * returned if memory pool allocation has failed. STATUS_PRIVILEGE_NOT_HELD + * is returned if the calling thread hasn't the required privileges to perform + * the operation in question. A failure NTSTATUS code is returned otherwise. + * + * @remarks + * The function is partly implemented, mainly TokenOrigin and TokenDefaultDacl. */ _Must_inspect_result_ __kernel_entry @@ -3494,11 +3980,37 @@ Cleanup: return Status; } - -/* - * @implemented +/** + * @brief + * Duplicates a token. + * + * @param[in] ExistingTokenHandle + * An existing token to duplicate. + * + * @param[in] DesiredAccess + * The desired access rights for the new duplicated token. + * + * @param[in] ObjectAttributes + * Object attributes for the new duplicated token. + * + * @param[in] EffectiveOnly + * If set to TRUE, the function removes all the disabled privileges and groups + * of the token to duplicate. + * + * @param[in] TokenType + * Type of token to assign to the duplicated token. + * + * @param[out] NewTokenHandle + * The returned duplicated token handle. * - * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K + * @return + * STATUS_SUCCESS is returned if token duplication has completed successfully. + * STATUS_BAD_IMPERSONATION_LEVEL is returned if the caller erroneously wants + * to raise the impersonation level even though the conditions do not permit + * it. A failure NTSTATUS code is returned otherwise. + * + * @remarks + * Some sources claim 4th param is ImpersonationLevel, but on W2K * this is certainly NOT true, although I can't say for sure that EffectiveOnly * is correct either. -Gunnar * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI @@ -3650,6 +4162,36 @@ NtDuplicateToken( return Status; } +/** + * @brief + * Changes the groups list of SIDs of a token. + * + * @param[in] TokenHandle + * Token handle where the list of groups SIDs are to be adjusted. + * + * @param[in] ResetToDefault + * If set to TRUE, the function resets the list of groups SIDs to default. + * All the rest of parameters are ignored. + * + * @param[in] NewState + * A new list of groups SIDs that the function will use it accordingly to + * modify the current list of groups SIDs of a token. + * + * @param[in] BufferLength + * The length size of the buffer that is pointed by the NewState parameter + * argument, in bytes. + * + * @param[out] PreviousState + * If specified, the function will return to the caller the old list of groups + * SIDs. + * + * @param[out] ReturnLength + * If specified, the function will return the total size length of the old list + * of groups SIDs, in bytes. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtAdjustGroupsToken(IN HANDLE TokenHandle, IN BOOLEAN ResetToDefault, @@ -3662,7 +4204,43 @@ NtAdjustGroupsToken(IN HANDLE TokenHandle, return STATUS_NOT_IMPLEMENTED; } - +/** + * @brief + * Removes a certain amount of privileges of a token based upon the request + * by the caller. + * + * @param[in,out] Token + * Token handle where the privileges are about to be modified. + * + * @param[in] DisableAllPrivileges + * If set to TRUE, the function disables all the privileges. + * + * @param[in] NewState + * A new list of privileges that the function will use it accordingly to + * either disable or enable the said privileges and change them. + * + * @param[in] NewStateCount + * The new total number count of privileges. + * + * @param[out] PreviousState + * If specified, the function will return the previous state list of privileges. + * + * @param[in] ApplyChanges + * If set to TRUE, the function will immediatelly apply the changes onto the + * token's privileges. + * + * @param[out] ChangedPrivileges + * The returned count number of changed privileges. + * + * @param[out] ChangesMade + * If TRUE, the function has made changes to the token's privileges. FALSE + * otherwise. + * + * @return + * Returns STATUS_SUCCESS if the function has successfully changed the list + * of privileges. STATUS_NOT_ALL_ASSIGNED is returned if not every privilege + * has been changed. + */ static NTSTATUS SepAdjustPrivileges( @@ -3779,9 +4357,42 @@ SepAdjustPrivileges( return STATUS_SUCCESS; } - -/* - * @implemented +/** + * @brief + * Removes a certain amount of privileges of a token based upon the request + * by the caller. + * + * @param[in,out] Token + * Token handle where the privileges are about to be modified. + * + * @param[in] DisableAllPrivileges + * If set to TRUE, the function disables all the privileges. + * + * @param[in] NewState + * A new list of privileges that the function will use it accordingly to + * either disable or enable the said privileges and change them. + * + * @param[in] NewStateCount + * The new total number count of privileges. + * + * @param[out] PreviousState + * If specified, the function will return the previous state list of privileges. + * + * @param[in] ApplyChanges + * If set to TRUE, the function will immediatelly apply the changes onto the + * token's privileges. + * + * @param[out] ChangedPrivileges + * The returned count number of changed privileges. + * + * @param[out] ChangesMade + * If TRUE, the function has made changes to the token's privileges. FALSE + * otherwise. + * + * @return + * Returns STATUS_SUCCESS if the function has successfully changed the list + * of privileges. STATUS_NOT_ALL_ASSIGNED is returned if not every privilege + * has been changed. */ _Must_inspect_result_ __kernel_entry @@ -3985,6 +4596,54 @@ Cleanup: return Status; } +/** + * @brief + * Creates an access token. + * + * @param[out] TokenHandle + * The returned created token handle to the caller. + * + * @param[in] DesiredAccess + * The desired access rights for the token that we're creating. + * + * @param[in] ObjectAttributes + * The object attributes for the token object that we're creating. + * + * @param[in] TokenType + * The type of token to assign for the newly created token. + * + * @param[in] AuthenticationId + * Authentication ID that represents the token's identity. + * + * @param[in] ExpirationTime + * Expiration time for the token. If set to -1, the token never expires. + * + * @param[in] TokenUser + * The main user entity for the token to assign. + * + * @param[in] TokenGroups + * Group list of SIDs for the token to assign. + * + * @param[in] TokenPrivileges + * Privileges for the token. + * + * @param[in] TokenOwner + * The main user that owns the newly created token. + * + * @param[in] TokenPrimaryGroup + * The primary group that represents as the main group of the token. + * + * @param[in] TokenDefaultDacl + * Discretionary access control list for the token. This limits on how + * the token can be used, accessed and used by whom. + * + * @param[in] TokenSource + * The source origin of the token who creates it. + * + * @return + * Returns STATUS_SUCCESS if the function has successfully created the token. + * A failure NTSTATUS code is returned otherwise. + */ __kernel_entry NTSTATUS NTAPI @@ -4258,8 +4917,32 @@ Cleanup: return Status; } -/* - * @implemented +/** + * @brief + * Opens a token that is tied to a thread handle. + * + * @param[out] ThreadHandle + * Thread handle where the token is about to be opened. + * + * @param[in] DesiredAccess + * The request access right for the token. + * + * @param[in] OpenAsSelf + * If set to TRUE, the access check will be made with the security context + * of the process of the calling thread (opening as self). Otherwise the access + * check will be made with the security context of the calling thread instead. + * + * @param[in] HandleAttributes + * Handle attributes for the opened thread token handle. + * + * @param[out] TokenHandle + * The opened token handle returned to the caller for use. + * + * @return + * Returns STATUS_SUCCESS if the function has successfully opened the thread + * token. STATUS_CANT_OPEN_ANONYMOUS is returned if a token has SecurityAnonymous + * as impersonation level and we cannot open it. A failure NTSTATUS code is returned + * otherwise. */ NTSTATUS NTAPI @@ -4441,8 +5124,26 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle, return Status; } -/* - * @implemented +/** + * @brief + * Opens a token that is tied to a thread handle. + * + * @param[out] ThreadHandle + * Thread handle where the token is about to be opened. + * + * @param[in] DesiredAccess + * The request access right for the token. + * + * @param[in] OpenAsSelf + * If set to TRUE, the access check will be made with the security context + * of the process of the calling thread (opening as self). Otherwise the access + * check will be made with the security context of the calling thread instead. + * + * @param[out] TokenHandle + * The opened token handle returned to the caller for use. + * + * @return + * See NtOpenThreadTokenEx. */ NTSTATUS NTAPI NtOpenThreadToken(IN HANDLE ThreadHandle, @@ -4556,6 +5257,33 @@ NtCompareTokens( return Status; } +/** + * @unimplemented + * @brief + * Opens a token that is tied to a thread handle. + * + * @param[in] ExistingTokenHandle + * An existing token for filtering. + * + * @param[in] Flags + * Privilege flag options. This parameter argument influences how the token + * is filtered. Such parameter can be 0. + * + * @param[in] SidsToDisable + * Array of SIDs to disable. + * + * @param[in] PrivilegesToDelete + * Array of privileges to delete. + * + * @param[in] RestrictedSids + * An array of restricted SIDs for the new filtered token. + * + * @param[out] NewTokenHandle + * The newly filtered token, returned to the caller. + * + * @return + * To be added... + */ NTSTATUS NTAPI NtFilterToken(IN HANDLE ExistingTokenHandle,