ReactOS  0.4.15-dev-5097-g328cc41
tokenlif.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for tokenlif.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define SE_TOKEN_DYNAMIC_SLIM   500
 

Functions

NTSTATUS NTAPI SepCreateToken (_Out_ PHANDLE TokenHandle, _In_ KPROCESSOR_MODE PreviousMode, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PSID_AND_ATTRIBUTES User, _In_ ULONG GroupCount, _In_ PSID_AND_ATTRIBUTES Groups, _In_ ULONG GroupsLength, _In_ ULONG PrivilegeCount, _In_ PLUID_AND_ATTRIBUTES Privileges, _In_opt_ PSID Owner, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl, _In_ PTOKEN_SOURCE TokenSource, _In_ BOOLEAN SystemToken)
 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. More...
 
NTSTATUS NTAPI SepDuplicateToken (_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
 Duplicates an access token, from an existing valid token. More...
 
static NTSTATUS SepPerformTokenFiltering (_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
 Private helper function responsible for creating a restricted access token, that is, a filtered token from privileges and groups and with restricted SIDs added into the token on demand by the caller. More...
 
NTSTATUS NTAPI SeFilterToken (_In_ PACCESS_TOKEN ExistingToken, _In_ ULONG Flags, _In_opt_ PTOKEN_GROUPS SidsToDisable, _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete, _In_opt_ PTOKEN_GROUPS RestrictedSids, _Out_ PACCESS_TOKEN *FilteredToken)
 Filters an access token from an existing token, making it more restricted than the previous one. More...
 
__kernel_entry NTSTATUS NTAPI NtCreateToken (_Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER TokenUser, _In_ PTOKEN_GROUPS TokenGroups, _In_ PTOKEN_PRIVILEGES TokenPrivileges, _In_opt_ PTOKEN_OWNER TokenOwner, _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl, _In_ PTOKEN_SOURCE TokenSource)
 Creates an access token. More...
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken (_In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle)
 Duplicates a token. More...
 
NTSTATUS NTAPI NtFilterToken (_In_ HANDLE ExistingTokenHandle, _In_ ULONG Flags, _In_opt_ PTOKEN_GROUPS SidsToDisable, _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete, _In_opt_ PTOKEN_GROUPS RestrictedSids, _Out_ PHANDLE NewTokenHandle)
 Creates an access token in a restricted form from the original existing token, that is, such action is called filtering. More...
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file tokenlif.c.

◆ SE_TOKEN_DYNAMIC_SLIM

#define SE_TOKEN_DYNAMIC_SLIM   500

Definition at line 17 of file tokenlif.c.

Function Documentation

◆ NtCreateToken()

__kernel_entry NTSTATUS NTAPI NtCreateToken ( _Out_ PHANDLE  TokenHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ TOKEN_TYPE  TokenType,
_In_ PLUID  AuthenticationId,
_In_ PLARGE_INTEGER  ExpirationTime,
_In_ PTOKEN_USER  TokenUser,
_In_ PTOKEN_GROUPS  TokenGroups,
_In_ PTOKEN_PRIVILEGES  TokenPrivileges,
_In_opt_ PTOKEN_OWNER  TokenOwner,
_In_ PTOKEN_PRIMARY_GROUP  TokenPrimaryGroup,
_In_opt_ PTOKEN_DEFAULT_DACL  TokenDefaultDacl,
_In_ PTOKEN_SOURCE  TokenSource 
)

Creates an access token.

Parameters
[out]TokenHandleThe returned created token handle to the caller.
[in]DesiredAccessThe desired access rights for the token that we're creating.
[in]ObjectAttributesThe object attributes for the token object that we're creating.
[in]TokenTypeThe type of token to assign for the newly created token.
[in]AuthenticationIdAuthentication ID that represents the token's identity.
[in]ExpirationTimeExpiration time for the token. If set to -1, the token never expires.
[in]TokenUserThe main user entity for the token to assign.
[in]TokenGroupsGroup list of SIDs for the token to assign.
[in]TokenPrivilegesPrivileges for the token.
[in]TokenOwnerThe main user that owns the newly created token.
[in]TokenPrimaryGroupThe primary group that represents as the main group of the token.
[in]TokenDefaultDaclDiscretionary access control list for the token. This limits on how the token can be used, accessed and used by whom.
[in]TokenSourceThe source origin of the token who creates it.
Returns
Returns STATUS_SUCCESS if the function has successfully created the token. A failure NTSTATUS code is returned otherwise.

Definition at line 1554 of file tokenlif.c.

1568 {
1569  HANDLE hToken;
1571  ULONG PrivilegeCount, GroupCount;
1572  PSID OwnerSid, PrimaryGroupSid;
1573  PACL DefaultDacl;
1574  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
1575  LUID LocalAuthenticationId;
1576  TOKEN_SOURCE LocalTokenSource;
1577  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
1578  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
1579  PSID_AND_ATTRIBUTES CapturedUser = NULL;
1580  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
1581  PSID CapturedOwnerSid = NULL;
1582  PSID CapturedPrimaryGroupSid = NULL;
1583  PACL CapturedDefaultDacl = NULL;
1584  ULONG PrivilegesLength, UserLength, GroupsLength;
1585  NTSTATUS Status;
1586 
1587  PAGED_CODE();
1588 
1590 
1591  if (PreviousMode != KernelMode)
1592  {
1593  _SEH2_TRY
1594  {
1596 
1597  if (ObjectAttributes != NULL)
1598  {
1600  sizeof(OBJECT_ATTRIBUTES),
1601  sizeof(ULONG));
1602  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
1603  }
1604 
1605  ProbeForRead(AuthenticationId,
1606  sizeof(LUID),
1607  sizeof(ULONG));
1608  LocalAuthenticationId = *AuthenticationId;
1609 
1610  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
1611 
1613  sizeof(TOKEN_USER),
1614  sizeof(ULONG));
1615 
1617  sizeof(TOKEN_GROUPS),
1618  sizeof(ULONG));
1619  GroupCount = TokenGroups->GroupCount;
1620 
1622  sizeof(TOKEN_PRIVILEGES),
1623  sizeof(ULONG));
1624  PrivilegeCount = TokenPrivileges->PrivilegeCount;
1625 
1626  if (TokenOwner != NULL)
1627  {
1629  sizeof(TOKEN_OWNER),
1630  sizeof(ULONG));
1631  OwnerSid = TokenOwner->Owner;
1632  }
1633  else
1634  {
1635  OwnerSid = NULL;
1636  }
1637 
1639  sizeof(TOKEN_PRIMARY_GROUP),
1640  sizeof(ULONG));
1641  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
1642 
1643  if (TokenDefaultDacl != NULL)
1644  {
1646  sizeof(TOKEN_DEFAULT_DACL),
1647  sizeof(ULONG));
1648  DefaultDacl = TokenDefaultDacl->DefaultDacl;
1649  }
1650  else
1651  {
1652  DefaultDacl = NULL;
1653  }
1654 
1656  sizeof(TOKEN_SOURCE),
1657  sizeof(ULONG));
1658  LocalTokenSource = *TokenSource;
1659  }
1661  {
1662  /* Return the exception code */
1664  }
1665  _SEH2_END;
1666  }
1667  else
1668  {
1669  if (ObjectAttributes != NULL)
1670  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
1671  LocalAuthenticationId = *AuthenticationId;
1672  LocalExpirationTime = *ExpirationTime;
1673  GroupCount = TokenGroups->GroupCount;
1674  PrivilegeCount = TokenPrivileges->PrivilegeCount;
1675  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
1676  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
1677  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
1678  LocalTokenSource = *TokenSource;
1679  }
1680 
1681  /* Check token type */
1682  if ((TokenType < TokenPrimary) ||
1684  {
1685  return STATUS_BAD_TOKEN_TYPE;
1686  }
1687 
1688  /* Check for token creation privilege */
1690  {
1692  }
1693 
1694  /* Capture the user SID and attributes */
1696  1,
1697  PreviousMode,
1698  NULL,
1699  0,
1700  PagedPool,
1701  FALSE,
1702  &CapturedUser,
1703  &UserLength);
1704  if (!NT_SUCCESS(Status))
1705  {
1706  goto Cleanup;
1707  }
1708 
1709  /* Capture the groups SID and attributes array */
1711  GroupCount,
1712  PreviousMode,
1713  NULL,
1714  0,
1715  PagedPool,
1716  FALSE,
1717  &CapturedGroups,
1718  &GroupsLength);
1719  if (!NT_SUCCESS(Status))
1720  {
1721  goto Cleanup;
1722  }
1723 
1724  /* Capture privileges */
1726  PrivilegeCount,
1727  PreviousMode,
1728  NULL,
1729  0,
1730  PagedPool,
1731  FALSE,
1732  &CapturedPrivileges,
1733  &PrivilegesLength);
1734  if (!NT_SUCCESS(Status))
1735  {
1736  goto Cleanup;
1737  }
1738 
1739  /* Capture the token owner SID */
1740  if (TokenOwner != NULL)
1741  {
1742  Status = SepCaptureSid(OwnerSid,
1743  PreviousMode,
1744  PagedPool,
1745  FALSE,
1746  &CapturedOwnerSid);
1747  if (!NT_SUCCESS(Status))
1748  {
1749  goto Cleanup;
1750  }
1751  }
1752 
1753  /* Capture the token primary group SID */
1754  Status = SepCaptureSid(PrimaryGroupSid,
1755  PreviousMode,
1756  PagedPool,
1757  FALSE,
1758  &CapturedPrimaryGroupSid);
1759  if (!NT_SUCCESS(Status))
1760  {
1761  goto Cleanup;
1762  }
1763 
1764  /* Capture DefaultDacl */
1765  if (DefaultDacl != NULL)
1766  {
1767  Status = SepCaptureAcl(DefaultDacl,
1768  PreviousMode,
1769  NonPagedPool,
1770  FALSE,
1771  &CapturedDefaultDacl);
1772  if (!NT_SUCCESS(Status))
1773  {
1774  goto Cleanup;
1775  }
1776  }
1777 
1778  /* Call the internal function */
1779  Status = SepCreateToken(&hToken,
1780  PreviousMode,
1781  DesiredAccess,
1783  TokenType,
1784  LocalSecurityQos.ImpersonationLevel,
1785  &LocalAuthenticationId,
1786  &LocalExpirationTime,
1787  CapturedUser,
1788  GroupCount,
1789  CapturedGroups,
1790  GroupsLength,
1791  PrivilegeCount,
1792  CapturedPrivileges,
1793  CapturedOwnerSid,
1794  CapturedPrimaryGroupSid,
1795  CapturedDefaultDacl,
1796  &LocalTokenSource,
1797  FALSE);
1798  if (NT_SUCCESS(Status))
1799  {
1800  _SEH2_TRY
1801  {
1802  *TokenHandle = hToken;
1803  }
1805  {
1807  }
1808  _SEH2_END;
1809  }
1810 
1811 Cleanup:
1812 
1813  /* Release what we captured */
1816  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
1817  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
1818  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
1819  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
1820 
1821  return Status;
1822 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
VOID NTAPI SepReleaseAcl(_In_ PACL CapturedAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) a captured ACL from the memory pool.
Definition: acl.c:464
const LUID SeCreateTokenPrivilege
Definition: priv.c:21
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID with attributes.
Definition: sid.c:979
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Src, _In_ ULONG PrivilegeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_ PLUID_AND_ATTRIBUTES AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PLUID_AND_ATTRIBUTES *Dest, _Inout_ PULONG Length)
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
LONG NTSTATUS
Definition: precomp.h:26
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3062
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
_SEH2_TRY
Definition: create.c:4226
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI SepCaptureAcl(_In_ PACL InputAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PACL *CapturedAcl)
Captures an access control list from an already valid input ACL.
Definition: acl.c:352
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
VOID NTAPI SeReleaseLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Privilege, _In_ KPROCESSOR_MODE PreviousMode, _In_ BOOLEAN CaptureIfKernel)
Releases a LUID with attributes structure.
Definition: priv.c:554
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Captures a SID with attributes.
Definition: sid.c:696
static const WCHAR Cleanup[]
Definition: register.c:80
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI SepCreateToken(_Out_ PHANDLE TokenHandle, _In_ KPROCESSOR_MODE PreviousMode, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PSID_AND_ATTRIBUTES User, _In_ ULONG GroupCount, _In_ PSID_AND_ATTRIBUTES Groups, _In_ ULONG GroupsLength, _In_ ULONG PrivilegeCount, _In_ PLUID_AND_ATTRIBUTES Privileges, _In_opt_ PSID Owner, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl, _In_ PTOKEN_SOURCE TokenSource, _In_ BOOLEAN SystemToken)
Internal function responsible for access token object creation in the kernel. A fully created token o...
Definition: tokenlif.c:97
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define NULL
Definition: types.h:112
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()

Referenced by LsapLogonUser().

◆ NtDuplicateToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken ( _In_ HANDLE  ExistingTokenHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ BOOLEAN  EffectiveOnly,
_In_ TOKEN_TYPE  TokenType,
_Out_ PHANDLE  NewTokenHandle 
)

Duplicates a token.

Parameters
[in]ExistingTokenHandleAn existing token to duplicate.
[in]DesiredAccessThe desired access rights for the new duplicated token.
[in]ObjectAttributesObject attributes for the new duplicated token.
[in]EffectiveOnlyIf set to TRUE, the function removes all the disabled privileges and groups of the token to duplicate.
[in]TokenTypeType of token to assign to the duplicated token.
[out]NewTokenHandleThe returned duplicated token handle.
Returns
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 NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore wrong in that regard, while MSDN documentation is correct.

Definition at line 1865 of file tokenlif.c.

1872 {
1874  HANDLE hToken;
1875  PTOKEN Token;
1876  PTOKEN NewToken;
1877  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
1878  BOOLEAN QoSPresent;
1880  NTSTATUS Status;
1881 
1882  PAGED_CODE();
1883 
1884  if (TokenType != TokenImpersonation &&
1886  {
1887  return STATUS_INVALID_PARAMETER;
1888  }
1889 
1891 
1892  if (PreviousMode != KernelMode)
1893  {
1894  _SEH2_TRY
1895  {
1897  }
1899  {
1900  /* Return the exception code */
1902  }
1903  _SEH2_END;
1904  }
1905 
1907  PreviousMode,
1908  PagedPool,
1909  FALSE,
1910  &CapturedSecurityQualityOfService,
1911  &QoSPresent);
1912  if (!NT_SUCCESS(Status))
1913  {
1914  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
1915  return Status;
1916  }
1917 
1918  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
1921  PreviousMode,
1922  (PVOID*)&Token,
1924  if (!NT_SUCCESS(Status))
1925  {
1926  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
1927  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1928  PreviousMode,
1929  FALSE);
1930  return Status;
1931  }
1932 
1933  /*
1934  * Fail, if the original token is an impersonation token and the caller
1935  * tries to raise the impersonation level of the new token above the
1936  * impersonation level of the original token.
1937  */
1938  if (Token->TokenType == TokenImpersonation)
1939  {
1940  if (QoSPresent &&
1941  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
1942  {
1944  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1945  PreviousMode,
1946  FALSE);
1948  }
1949  }
1950 
1951  /*
1952  * Fail, if a primary token is to be created from an impersonation token
1953  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
1954  */
1955  if (Token->TokenType == TokenImpersonation &&
1956  TokenType == TokenPrimary &&
1957  Token->ImpersonationLevel < SecurityImpersonation)
1958  {
1960  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1961  PreviousMode,
1962  FALSE);
1964  }
1965 
1968  EffectiveOnly,
1969  TokenType,
1970  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
1971  PreviousMode,
1972  &NewToken);
1973 
1975 
1976  if (NT_SUCCESS(Status))
1977  {
1978  Status = ObInsertObject(NewToken,
1979  NULL,
1980  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
1981  0,
1982  NULL,
1983  &hToken);
1984  if (NT_SUCCESS(Status))
1985  {
1986  _SEH2_TRY
1987  {
1988  *NewTokenHandle = hToken;
1989  }
1991  {
1993  }
1994  _SEH2_END;
1995  }
1996  }
1997 
1998  /* Free the captured structure */
1999  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
2000  PreviousMode,
2001  FALSE);
2002 
2003  return Status;
2004 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define KeGetPreviousMode()
Definition: ketypes.h:1108
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE _Out_ PHANDLE NewTokenHandle
Definition: sefuncs.h:401
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_ ACCESS_MASK _In_opt_ POBJECT_TYPE _In_ KPROCESSOR_MODE _Out_ PVOID _Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
Definition: obfuncs.h:40
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define TOKEN_DUPLICATE
Definition: setypes.h:922
VOID NTAPI SepReleaseSecurityQualityOfService(_In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) the captured SQOS data from an object in the memory pool.
Definition: sqos.c:225
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSTATUS NTAPI SepDuplicateToken(_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
Duplicates an access token, from an existing valid token.
Definition: tokenlif.c:471
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
NTSTATUS NTAPI SepCaptureSecurityQualityOfService(_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, _Out_ PBOOLEAN Present)
Captures the security quality of service data given the object attributes from an object.
Definition: sqos.c:52
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:401
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()

Referenced by CreateProcessAsUserCommon(), DuplicateTokenAsEffective(), DuplicateTokenEx(), ImpersonateLoggedOnUser(), and QueryTokenImpersonationTests().

◆ NtFilterToken()

NTSTATUS NTAPI NtFilterToken ( _In_ HANDLE  ExistingTokenHandle,
_In_ ULONG  Flags,
_In_opt_ PTOKEN_GROUPS  SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES  PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS  RestrictedSids,
_Out_ PHANDLE  NewTokenHandle 
)

Creates an access token in a restricted form from the original existing token, that is, such action is called filtering.

Parameters
[in]ExistingTokenHandleA handle to an access token which is to be filtered.
[in]FlagsPrivilege flag options. This parameter argument influences how the token's privileges are filtered. For further details see remarks.
[in]SidsToDisableArray of SIDs to disable. The action of doing so assigns the SE_GROUP_USE_FOR_DENY_ONLY attribute to the respective group SID and takes away SE_GROUP_ENABLED and SE_GROUP_ENABLED_BY_DEFAULT. This parameter can be NULL. This can be a UM pointer.
[in]PrivilegesToDeleteArray of privileges to delete. The function will walk within this array to determine if the specified privileges do exist in the access token. Any missing privileges gets ignored. This parameter can be NULL. This can be a UM pointer.
[in]RestrictedSidsAn array list of restricted groups SID to be added in the access token. A token that is already restricted the newly added restricted SIDs are redundant information in addition to the existing restricted SIDs in the token. This parameter can be NULL. This can be a UM pointer.
[out]NewTokenHandleA new handle to the restricted (filtered) access token. This can be a UM pointer.
Returns
Returns STATUS_SUCCESS if the routine has successfully filtered the access token. STATUS_INVALID_PARAMETER is returned if one or more parameters are not valid (see SepPerformTokenFiltering routine call for more information). A failure NTSTATUS code is returned otherwise.
Remarks
The Flags parameter determines the final outcome of how the privileges in an access token are filtered. This parameter can take these supported values (these can be combined):

0 – Filter the token's privileges in the usual way. The function expects that the caller MUST PROVIDE a valid array list of privileges to be deleted (that is, PrivilegesToDelete MUSTN'T BE NULL).

DISABLE_MAX_PRIVILEGE – Disables (deletes) all the privileges except SeChangeNotifyPrivilege in the new access token. Bear in mind if this flag is specified the routine ignores PrivilegesToDelete.

SANDBOX_INERT – Stores the TOKEN_SANDBOX_INERT token flag within the access token.

LUA_TOKEN – The newly filtered access token is a LUA token. This flag is not supported in Windows Server 2003.

WRITE_RESTRICTED – The newly filtered token has the restricted SIDs that are considered only when evaluating write access onto the token. This value is not supported in Windows Server 2003.

Definition at line 2071 of file tokenlif.c.

2078 {
2079  PTOKEN Token, FilteredToken;
2080  HANDLE FilteredTokenHandle;
2081  NTSTATUS Status;
2083  OBJECT_HANDLE_INFORMATION HandleInfo;
2085  ULONG CapturedSidsCount = 0;
2086  ULONG CapturedPrivilegesCount = 0;
2087  ULONG CapturedRestrictedSidsCount = 0;
2088  ULONG ProbeSize = 0;
2089  PSID_AND_ATTRIBUTES CapturedSids = NULL;
2090  PSID_AND_ATTRIBUTES CapturedRestrictedSids = NULL;
2091  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
2092 
2093  PAGED_CODE();
2094 
2096 
2097  _SEH2_TRY
2098  {
2099  /* Probe SidsToDisable */
2100  if (SidsToDisable != NULL)
2101  {
2102  /* Probe the header */
2103  ProbeForRead(SidsToDisable, sizeof(*SidsToDisable), sizeof(ULONG));
2104 
2105  CapturedSidsCount = SidsToDisable->GroupCount;
2106  ProbeSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedSidsCount]);
2107 
2108  ProbeForRead(SidsToDisable, ProbeSize, sizeof(ULONG));
2109  }
2110 
2111  /* Probe PrivilegesToDelete */
2112  if (PrivilegesToDelete != NULL)
2113  {
2114  /* Probe the header */
2115  ProbeForRead(PrivilegesToDelete, sizeof(*PrivilegesToDelete), sizeof(ULONG));
2116 
2117  CapturedPrivilegesCount = PrivilegesToDelete->PrivilegeCount;
2118  ProbeSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedPrivilegesCount]);
2119 
2120  ProbeForRead(PrivilegesToDelete, ProbeSize, sizeof(ULONG));
2121  }
2122 
2123  /* Probe RestrictedSids */
2124  if (RestrictedSids != NULL)
2125  {
2126  /* Probe the header */
2127  ProbeForRead(RestrictedSids, sizeof(*RestrictedSids), sizeof(ULONG));
2128 
2129  CapturedRestrictedSidsCount = RestrictedSids->GroupCount;
2130  ProbeSize = FIELD_OFFSET(TOKEN_GROUPS, Groups[CapturedRestrictedSidsCount]);
2131 
2132  ProbeForRead(RestrictedSids, ProbeSize, sizeof(ULONG));
2133  }
2134 
2135  /* Probe the handle */
2137  }
2139  {
2140  /* Return the exception code */
2142  }
2143  _SEH2_END;
2144 
2145  /* Reference the token */
2146  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
2149  PreviousMode,
2150  (PVOID*)&Token,
2151  &HandleInfo);
2152  if (!NT_SUCCESS(Status))
2153  {
2154  DPRINT1("NtFilterToken(): Failed to reference the token (Status 0x%lx)\n", Status);
2155  return Status;
2156  }
2157 
2158  /* Capture the group SIDs */
2159  if (SidsToDisable != NULL)
2160  {
2161  Status = SeCaptureSidAndAttributesArray(SidsToDisable->Groups,
2162  CapturedSidsCount,
2163  PreviousMode,
2164  NULL,
2165  0,
2166  PagedPool,
2167  TRUE,
2168  &CapturedSids,
2169  &ResultLength);
2170  if (!NT_SUCCESS(Status))
2171  {
2172  DPRINT1("NtFilterToken(): Failed to capture the SIDs (Status 0x%lx)\n", Status);
2173  goto Quit;
2174  }
2175  }
2176 
2177  /* Capture the privileges */
2178  if (PrivilegesToDelete != NULL)
2179  {
2180  Status = SeCaptureLuidAndAttributesArray(PrivilegesToDelete->Privileges,
2181  CapturedPrivilegesCount,
2182  PreviousMode,
2183  NULL,
2184  0,
2185  PagedPool,
2186  TRUE,
2187  &CapturedPrivileges,
2188  &ResultLength);
2189  if (!NT_SUCCESS(Status))
2190  {
2191  DPRINT1("NtFilterToken(): Failed to capture the privileges (Status 0x%lx)\n", Status);
2192  goto Quit;
2193  }
2194  }
2195 
2196  /* Capture the restricted SIDs */
2197  if (RestrictedSids != NULL)
2198  {
2199  Status = SeCaptureSidAndAttributesArray(RestrictedSids->Groups,
2200  CapturedRestrictedSidsCount,
2201  PreviousMode,
2202  NULL,
2203  0,
2204  PagedPool,
2205  TRUE,
2206  &CapturedRestrictedSids,
2207  &ResultLength);
2208  if (!NT_SUCCESS(Status))
2209  {
2210  DPRINT1("NtFilterToken(): Failed to capture the restricted SIDs (Status 0x%lx)\n", Status);
2211  goto Quit;
2212  }
2213  }
2214 
2215  /* Call the internal API */
2217  CapturedPrivileges,
2218  CapturedSids,
2219  CapturedRestrictedSids,
2220  CapturedPrivilegesCount,
2221  CapturedSidsCount,
2222  CapturedRestrictedSidsCount,
2223  Flags,
2224  PreviousMode,
2225  &FilteredToken);
2226  if (!NT_SUCCESS(Status))
2227  {
2228  DPRINT1("NtFilterToken(): Failed to filter the token (Status 0x%lx)\n", Status);
2229  goto Quit;
2230  }
2231 
2232  /* Insert the filtered token and retrieve a handle to it */
2233  Status = ObInsertObject(FilteredToken,
2234  NULL,
2235  HandleInfo.GrantedAccess,
2236  0,
2237  NULL,
2238  &FilteredTokenHandle);
2239  if (!NT_SUCCESS(Status))
2240  {
2241  DPRINT1("NtFilterToken(): Failed to insert the filtered token (Status 0x%lx)\n", Status);
2242  goto Quit;
2243  }
2244 
2245  /* And return it to the caller once we're done */
2246  _SEH2_TRY
2247  {
2248  *NewTokenHandle = FilteredTokenHandle;
2249  }
2251  {
2253  _SEH2_YIELD(goto Quit);
2254  }
2255  _SEH2_END;
2256 
2257 Quit:
2258  /* Dereference the token */
2260 
2261  /* Release all the captured data */
2262  if (CapturedSids != NULL)
2263  {
2264  SeReleaseSidAndAttributesArray(CapturedSids,
2265  PreviousMode,
2266  TRUE);
2267  }
2268 
2269  if (CapturedPrivileges != NULL)
2270  {
2271  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
2272  PreviousMode,
2273  TRUE);
2274  }
2275 
2276  if (CapturedRestrictedSids != NULL)
2277  {
2278  SeReleaseSidAndAttributesArray(CapturedRestrictedSids,
2279  PreviousMode,
2280  TRUE);
2281  }
2282 
2283  return Status;
2284 }
static NTSTATUS SepPerformTokenFiltering(_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
Private helper function responsible for creating a restricted access token, that is,...
Definition: tokenlif.c:855
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID with attributes.
Definition: sid.c:979
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Src, _In_ ULONG PrivilegeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_ PLUID_AND_ATTRIBUTES AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PLUID_AND_ATTRIBUTES *Dest, _Inout_ PULONG Length)
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3062
TOpcodeData Groups[17][8]
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE _Out_ PHANDLE NewTokenHandle
Definition: sefuncs.h:401
ACCESS_MASK GrantedAccess
Definition: iotypes.h:181
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
VOID NTAPI SeReleaseLuidAndAttributesArray(_In_ PLUID_AND_ATTRIBUTES Privilege, _In_ KPROCESSOR_MODE PreviousMode, _In_ BOOLEAN CaptureIfKernel)
Releases a LUID with attributes structure.
Definition: priv.c:554
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:13
#define TOKEN_DUPLICATE
Definition: setypes.h:922
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Captures a SID with attributes.
Definition: sid.c:696
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define PAGED_CODE()

Referenced by CreateRestrictedToken(), QueryTokenIsSandboxInert(), QueryTokenPrivilegesAndGroupsTests(), QueryTokenRestrictedSidsTest(), and START_TEST().

◆ SeFilterToken()

NTSTATUS NTAPI SeFilterToken ( _In_ PACCESS_TOKEN  ExistingToken,
_In_ ULONG  Flags,
_In_opt_ PTOKEN_GROUPS  SidsToDisable,
_In_opt_ PTOKEN_PRIVILEGES  PrivilegesToDelete,
_In_opt_ PTOKEN_GROUPS  RestrictedSids,
_Out_ PACCESS_TOKEN FilteredToken 
)

Filters an access token from an existing token, making it more restricted than the previous one.

Parameters
[in]ExistingTokenAn existing token for filtering.
[in]FlagsPrivilege flag options. This parameter argument influences how the token is filtered. Such parameter can be 0. See NtFilterToken syscall for more information.
[in]SidsToDisableArray of SIDs to disable. Such parameter can be NULL.
[in]PrivilegesToDeleteArray of privileges to delete. If DISABLE_MAX_PRIVILEGE flag is specified in the Flags parameter, PrivilegesToDelete is ignored.
[in]RestrictedSidsAn array of restricted SIDs for the new filtered token. Such parameter can be NULL.
[out]FilteredTokenThe newly filtered token, returned to the caller.
Returns
Returns STATUS_SUCCESS if the function has successfully completed its operations and that the access token has been filtered. STATUS_INVALID_PARAMETER is returned if one or more of the parameter are not valid. A failure NTSTATUS code is returned otherwise.

Definition at line 1434 of file tokenlif.c.

1441 {
1442  NTSTATUS Status;
1443  PTOKEN AccessToken;
1444  ULONG PrivilegesCount = 0;
1445  ULONG SidsCount = 0;
1446  ULONG RestrictedSidsCount = 0;
1447 
1448  PAGED_CODE();
1449 
1450  /* Begin copying the counters */
1451  if (SidsToDisable != NULL)
1452  {
1453  SidsCount = SidsToDisable->GroupCount;
1454  }
1455 
1456  if (PrivilegesToDelete != NULL)
1457  {
1458  PrivilegesCount = PrivilegesToDelete->PrivilegeCount;
1459  }
1460 
1461  if (RestrictedSids != NULL)
1462  {
1463  RestrictedSidsCount = RestrictedSids->GroupCount;
1464  }
1465 
1466  /* Call the internal API */
1467  Status = SepPerformTokenFiltering(ExistingToken,
1468  PrivilegesToDelete->Privileges,
1469  SidsToDisable->Groups,
1470  RestrictedSids->Groups,
1471  PrivilegesCount,
1472  SidsCount,
1473  RestrictedSidsCount,
1474  Flags,
1475  KernelMode,
1476  &AccessToken);
1477  if (!NT_SUCCESS(Status))
1478  {
1479  DPRINT1("SeFilterToken(): Failed to filter the token (Status 0x%lx)\n", Status);
1480  return Status;
1481  }
1482 
1483  /* Insert the filtered token */
1484  Status = ObInsertObject(AccessToken,
1485  NULL,
1486  0,
1487  0,
1488  NULL,
1489  NULL);
1490  if (!NT_SUCCESS(Status))
1491  {
1492  DPRINT1("SeFilterToken(): Failed to insert the filtered token (Status 0x%lx)\n", Status);
1493  return Status;
1494  }
1495 
1496  /* Return it to the caller */
1497  *FilteredToken = AccessToken;
1498  return Status;
1499 }
static NTSTATUS SepPerformTokenFiltering(_In_ PTOKEN Token, _In_opt_ PLUID_AND_ATTRIBUTES PrivilegesToBeDeleted, _In_opt_ PSID_AND_ATTRIBUTES SidsToBeDisabled, _In_opt_ PSID_AND_ATTRIBUTES RestrictedSidsIntoToken, _When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG PrivilegesCount, _When_(SidsToBeDisabled !=NULL, _In_) ULONG RegularGroupsSidCount, _When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG RestrictedSidsCount, _In_ ULONG PrivilegeFlags, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *FilteredToken)
Private helper function responsible for creating a restricted access token, that is,...
Definition: tokenlif.c:855
LONG NTSTATUS
Definition: precomp.h:26
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define PAGED_CODE()

Referenced by FatCreateRestrictEveryoneToken(), and FilterToken().

◆ SepCreateToken()

NTSTATUS NTAPI SepCreateToken ( _Out_ PHANDLE  TokenHandle,
_In_ KPROCESSOR_MODE  PreviousMode,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ TOKEN_TYPE  TokenType,
_In_ SECURITY_IMPERSONATION_LEVEL  ImpersonationLevel,
_In_ PLUID  AuthenticationId,
_In_ PLARGE_INTEGER  ExpirationTime,
_In_ PSID_AND_ATTRIBUTES  User,
_In_ ULONG  GroupCount,
_In_ PSID_AND_ATTRIBUTES  Groups,
_In_ ULONG  GroupsLength,
_In_ ULONG  PrivilegeCount,
_In_ PLUID_AND_ATTRIBUTES  Privileges,
_In_opt_ PSID  Owner,
_In_ PSID  PrimaryGroup,
_In_opt_ PACL  DefaultDacl,
_In_ PTOKEN_SOURCE  TokenSource,
_In_ BOOLEAN  SystemToken 
)

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.

Parameters
[out]TokenHandleValid token handle that's ready for use after token creation and object insertion.
[in]PreviousModeProcessor request level mode.
[in]DesiredAccessDesired access right for the token object to be granted. This kind of access right impacts how the token can be used and who.
[in]ObjectAttributesObject attributes for the token to be created.
[in]TokenTypeType of token to assign upon creation.
[in]ImpersonationLevelSecurity impersonation level of token to assign upon creation.
[in]AuthenticationIdAuthentication ID that represents the authentication information of the token.
[in]ExpirationTimeExpiration 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.
[in]UserUser entry to assign to the token.
[in]GroupCountThe total number of groups count for the token.
[in]GroupsThe group entries for the token.
[in]GroupsLengthThe length size of the groups array, pointed by the Groups parameter.
[in]PrivilegeCountThe total number of priivleges that the newly created token has.
[in]PrivilegesThe privileges for the token.
[in]OwnerThe main user (or also owner) that represents the token that we create.
[in]PrimaryGroupThe main group that represents the token that we create.
[in]DefaultDaclA discretionary access control list for the token.
[in]TokenSourceSource (or the origin) of the access token that creates it.
[in]SystemTokenIf 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.
Returns
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.

Definition at line 97 of file tokenlif.c.

117 {
119  PTOKEN AccessToken;
120  ULONG TokenFlags = 0;
121  ULONG PrimaryGroupIndex, DefaultOwnerIndex;
122  LUID TokenId;
123  LUID ModifiedId;
124  PVOID EndMem;
125  ULONG PrivilegesLength;
126  ULONG UserGroupsLength;
127  ULONG VariableLength;
128  ULONG DynamicPartSize, TotalSize;
129  ULONG TokenPagedCharges;
130  ULONG i;
131 
132  PAGED_CODE();
133 
134  /* Loop all groups */
135  for (i = 0; i < GroupCount; i++)
136  {
137  /* Check for mandatory groups */
139  {
140  /* Force them to be enabled */
142  }
143 
144  /* Check of the group is an admin group */
146  {
147  /* Remember this so we can optimize queries later */
148  TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
149  }
150  }
151 
152  /* Allocate unique IDs for the token */
153  ExAllocateLocallyUniqueId(&TokenId);
154  ExAllocateLocallyUniqueId(&ModifiedId);
155 
156  /* Compute how much size we need to allocate for the token */
157 
158  /* Privileges size */
159  PrivilegesLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
160  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
161 
162  /* User and groups size */
163  UserGroupsLength = (1 + GroupCount) * sizeof(SID_AND_ATTRIBUTES);
164  UserGroupsLength += RtlLengthSid(User->Sid);
165  for (i = 0; i < GroupCount; i++)
166  {
167  UserGroupsLength += RtlLengthSid(Groups[i].Sid);
168  }
169  UserGroupsLength = ALIGN_UP_BY(UserGroupsLength, sizeof(PVOID));
170 
171  /* Add the additional groups array length */
172  UserGroupsLength += ALIGN_UP_BY(GroupsLength, sizeof(PVOID));
173 
174  VariableLength = PrivilegesLength + UserGroupsLength;
175  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
176 
177  /*
178  * A token is considered slim if it has the default dynamic
179  * contents, or in other words, the primary group and ACL.
180  * We judge if such contents are default by checking their
181  * total size if it's over the range. On Windows this range
182  * is 0x1F4 (aka 500). If the size of the whole dynamic contents
183  * is over that range then the token is considered fat and
184  * the token will be charged the whole of its token body length
185  * plus the dynamic size.
186  */
187  DynamicPartSize = DefaultDacl ? DefaultDacl->AclSize : 0;
188  DynamicPartSize += RtlLengthSid(PrimaryGroup);
189  if (DynamicPartSize > SE_TOKEN_DYNAMIC_SLIM)
190  {
191  TokenPagedCharges = DynamicPartSize + TotalSize;
192  }
193  else
194  {
195  TokenPagedCharges = SE_TOKEN_DYNAMIC_SLIM + TotalSize;
196  }
197 
201  PreviousMode,
202  NULL,
203  TotalSize,
204  TokenPagedCharges,
205  0,
206  (PVOID*)&AccessToken);
207  if (!NT_SUCCESS(Status))
208  {
209  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
210  return Status;
211  }
212 
213  /* Zero out the buffer and initialize the token */
214  RtlZeroMemory(AccessToken, TotalSize);
215 
216  AccessToken->TokenId = TokenId;
217  AccessToken->TokenType = TokenType;
218  AccessToken->ImpersonationLevel = ImpersonationLevel;
219 
220  /* Initialise the lock for the access token */
221  Status = SepCreateTokenLock(AccessToken);
222  if (!NT_SUCCESS(Status))
223  goto Quit;
224 
225  AccessToken->TokenSource.SourceIdentifier = TokenSource->SourceIdentifier;
226  RtlCopyMemory(AccessToken->TokenSource.SourceName,
227  TokenSource->SourceName,
228  sizeof(TokenSource->SourceName));
229 
230  AccessToken->ExpirationTime = *ExpirationTime;
231  AccessToken->ModifiedId = ModifiedId;
232  AccessToken->DynamicCharged = TokenPagedCharges - TotalSize;
233 
234  AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
235 
236  /* Copy and reference the logon session */
237  AccessToken->AuthenticationId = *AuthenticationId;
239  if (!NT_SUCCESS(Status))
240  {
241  /* No logon session could be found, bail out */
242  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
243  /* Set the flag for proper cleanup by the delete procedure */
245  goto Quit;
246  }
247 
248  /* Insert the referenced logon session into the token */
250  if (!NT_SUCCESS(Status))
251  {
252  /* Failed to insert the logon session into the token, bail out */
253  DPRINT1("SepRmInsertLogonSessionIntoToken() failed (Status 0x%lx)\n", Status);
254  goto Quit;
255  }
256 
257  /* Fill in token debug information */
258 #if DBG
259  /*
260  * We must determine ourselves that the current
261  * process is not the initial CPU one. The initial
262  * process is not a "real" process, that is, the
263  * Process Manager has not yet been initialized and
264  * as a matter of fact we are creating a token before
265  * any process gets created by Ps. If it turns out
266  * that the current process is the initial CPU process
267  * where token creation execution takes place, don't
268  * do anything.
269  */
271  {
272  RtlCopyMemory(AccessToken->ImageFileName,
273  PsGetCurrentProcess()->ImageFileName,
274  min(sizeof(AccessToken->ImageFileName), sizeof(PsGetCurrentProcess()->ImageFileName)));
275 
276  AccessToken->ProcessCid = PsGetCurrentProcessId();
277  AccessToken->ThreadCid = PsGetCurrentThreadId();
278  }
279 
280  AccessToken->CreateMethod = TOKEN_CREATE_METHOD;
281 #endif
282 
283  /* Assign the data that reside in the token's variable information area */
284  AccessToken->VariableLength = VariableLength;
285  EndMem = (PVOID)&AccessToken->VariablePart;
286 
287  /* Copy the privileges */
288  AccessToken->PrivilegeCount = PrivilegeCount;
289  AccessToken->Privileges = NULL;
290  if (PrivilegeCount > 0)
291  {
292  AccessToken->Privileges = EndMem;
293  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
294  VariableLength -= PrivilegesLength;
295 
296  if (PreviousMode != KernelMode)
297  {
298  _SEH2_TRY
299  {
300  RtlCopyMemory(AccessToken->Privileges,
301  Privileges,
302  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
303  }
305  {
307  }
308  _SEH2_END;
309  }
310  else
311  {
312  RtlCopyMemory(AccessToken->Privileges,
313  Privileges,
314  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
315  }
316 
317  if (!NT_SUCCESS(Status))
318  goto Quit;
319  }
320 
321  /* Update the privilege flags */
322  SepUpdatePrivilegeFlagsToken(AccessToken);
323 
324  /* Copy the user and groups */
325  AccessToken->UserAndGroupCount = 1 + GroupCount;
326  AccessToken->UserAndGroups = EndMem;
327  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
328  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
329 
331  User,
332  VariableLength,
333  &AccessToken->UserAndGroups[0],
334  EndMem,
335  &EndMem,
336  &VariableLength);
337  if (!NT_SUCCESS(Status))
338  goto Quit;
339 
341  Groups,
342  VariableLength,
343  &AccessToken->UserAndGroups[1],
344  EndMem,
345  &EndMem,
346  &VariableLength);
347  if (!NT_SUCCESS(Status))
348  goto Quit;
349 
350  /* Find the token primary group and default owner */
352  PrimaryGroup,
353  Owner,
354  &PrimaryGroupIndex,
355  &DefaultOwnerIndex);
356  if (!NT_SUCCESS(Status))
357  {
358  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
359  goto Quit;
360  }
361 
362  /*
363  * Now allocate the token's dynamic information area
364  * and set the data. The dynamic part consists of two
365  * contents, the primary group SID and the default DACL
366  * of the token, in this strict order.
367  */
369  DynamicPartSize,
371  if (AccessToken->DynamicPart == NULL)
372  {
374  goto Quit;
375  }
376 
377  /* Unused memory in the dynamic area */
378  AccessToken->DynamicAvailable = 0;
379 
380  /*
381  * Assign the primary group to the token
382  * and put it in the dynamic part as well.
383  */
384  EndMem = (PVOID)AccessToken->DynamicPart;
385  AccessToken->PrimaryGroup = EndMem;
386  RtlCopySid(RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid),
387  EndMem,
388  AccessToken->UserAndGroups[PrimaryGroupIndex].Sid);
389  AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
390  EndMem = (PVOID)((ULONG_PTR)EndMem + RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid));
391 
392  /*
393  * We have assigned a primary group and put it in the
394  * dynamic part, now it's time to copy the provided
395  * default DACL (if it's provided to begin with) into
396  * the DACL field of the token and put it at the end
397  * tail of the dynamic part too.
398  */
399  if (DefaultDacl != NULL)
400  {
401  AccessToken->DefaultDacl = EndMem;
402 
403  RtlCopyMemory(EndMem,
404  DefaultDacl,
405  DefaultDacl->AclSize);
406  }
407 
408  /* Insert the token only if it's not the system token, otherwise return it directly */
409  if (!SystemToken)
410  {
411  Status = ObInsertObject(AccessToken,
412  NULL,
414  0,
415  NULL,
416  TokenHandle);
417  if (!NT_SUCCESS(Status))
418  {
419  DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status);
420  }
421  }
422  else
423  {
424  /* Return pointer instead of handle */
425  *TokenHandle = (HANDLE)AccessToken;
426  }
427 
428 Quit:
429  if (!NT_SUCCESS(Status))
430  {
431  /* Dereference the token, the delete procedure will clean it up */
432  ObDereferenceObject(AccessToken);
433  }
434 
435  return Status;
436 }
TOKEN_TYPE TokenType
Definition: setypes.h:239
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI SepRmInsertLogonSessionIntoToken(_Inout_ PTOKEN Token)
Inserts a logon session into an access token specified by the caller.
Definition: srm.c:368
ULONG DynamicCharged
Definition: setypes.h:230
#define SE_TOKEN_DYNAMIC_SLIM
Definition: tokenlif.c:17
LUID AuthenticationId
Definition: setypes.h:219
ULONG VariablePart
Definition: setypes.h:253
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
LONG NTSTATUS
Definition: precomp.h:26
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
ULONG PrivilegeCount
Definition: setypes.h:228
#define TOKEN_CREATE_METHOD
Definition: se.h:70
NTSTATUS SepCreateTokenLock(_Inout_ PTOKEN Token)
Creates a lock for the token.
Definition: token.c:45
if(dx==0 &&dy==0)
Definition: linetemp.h:174
TOpcodeData Groups[17][8]
PLUID_AND_ATTRIBUTES Privileges
Definition: setypes.h:236
LUID ModifiedId
Definition: setypes.h:224
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG TokenFlags
Definition: setypes.h:241
LUID SourceIdentifier
Definition: imports.h:279
ULONG DynamicAvailable
Definition: setypes.h:231
VOID SepUpdatePrivilegeFlagsToken(_Inout_ PTOKEN Token)
Updates the token's flags based upon the privilege that the token has been granted....
Definition: token.c:554
PACL DefaultDacl
Definition: setypes.h:238
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTSTATUS SepRmReferenceLogonSession(_Inout_ PLUID LogonLuid)
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1130
ULONG DefaultOwnerIndex
Definition: setypes.h:232
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
ULONG VariableLength
Definition: setypes.h:229
void * PVOID
Definition: retypes.h:9
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:951
PULONG DynamicPart
Definition: setypes.h:237
Status
Definition: gdiplustypes.h:24
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID _Inout_ PULONG _Out_writes_bytes_to_opt_ PrimaryGroupSize PSID PrimaryGroup
Definition: rtlfuncs.h:1585
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
PSID PrimaryGroup
Definition: setypes.h:235
LARGE_INTEGER ExpirationTime
Definition: setypes.h:221
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SE_GROUP_ENABLED
Definition: setypes.h:92
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_Out_ PBOOLEAN _Out_ PBOOLEAN _Out_ PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: psfuncs.h:154
#define ObDereferenceObject
Definition: obfuncs.h:203
PVOID HANDLE
Definition: typedefs.h:73
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PSID SeAliasAdminsSid
Definition: sid.c:41
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:155
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
CCHAR SourceName[TOKEN_SOURCE_LENGTH]
Definition: imports.h:278
EPROCESS KiInitialProcess
Definition: krnlinit.c:45
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
#define TOKEN_HAS_ADMIN_GROUP
Definition: setypes.h:1178
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG UserAndGroupCount
Definition: setypes.h:226
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
LUID TokenId
Definition: setypes.h:218
#define min(a, b)
Definition: monoChain.cc:55
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1583
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:240
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
PSID_AND_ATTRIBUTES UserAndGroups
Definition: setypes.h:233
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
TOKEN_SOURCE TokenSource
Definition: setypes.h:217
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1180
NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Finds the primary group and default owner entity based on the submitted primary group instance and an...
Definition: token.c:1011
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes

Referenced by NtCreateToken(), SepCreateSystemAnonymousLogonToken(), SepCreateSystemAnonymousLogonTokenNoEveryone(), and SepCreateSystemProcessToken().

◆ SepDuplicateToken()

NTSTATUS NTAPI SepDuplicateToken ( _In_ PTOKEN  Token,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes,
_In_ BOOLEAN  EffectiveOnly,
_In_ TOKEN_TYPE  TokenType,
_In_ SECURITY_IMPERSONATION_LEVEL  Level,
_In_ KPROCESSOR_MODE  PreviousMode,
_Out_ PTOKEN NewAccessToken 
)

Duplicates an access token, from an existing valid token.

Parameters
[in]TokenAccess token to duplicate.
[in]ObjectAttributesObject attributes for the new token.
[in]EffectiveOnlyIf set to TRUE, the function removes all the disabled privileges and groups of the token to duplicate.
[in]TokenTypeType of token.
[in]LevelSecurity impersonation level of a token.
[in]PreviousModeThe processor request level mode.
[out]NewAccessTokenThe duplicated token.
Returns
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.

Definition at line 471 of file tokenlif.c.

479 {
481  PTOKEN AccessToken;
482  PVOID EndMem;
483  ULONG PrimaryGroupIndex;
484  ULONG VariableLength;
485  ULONG DynamicPartSize, TotalSize;
486  ULONG PrivilegesIndex, GroupsIndex;
487 
488  PAGED_CODE();
489 
490  /* Compute how much size we need to allocate for the token */
491  VariableLength = Token->VariableLength;
492  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
493 
494  /*
495  * Compute how much size we need to allocate
496  * the dynamic part of the newly duplicated
497  * token.
498  */
499  DynamicPartSize = Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0;
500  DynamicPartSize += RtlLengthSid(Token->PrimaryGroup);
501 
505  PreviousMode,
506  NULL,
507  TotalSize,
508  Token->DynamicCharged,
509  TotalSize,
510  (PVOID*)&AccessToken);
511  if (!NT_SUCCESS(Status))
512  {
513  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
514  return Status;
515  }
516 
517  /* Zero out the buffer and initialize the token */
518  RtlZeroMemory(AccessToken, TotalSize);
519 
520  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
521 
522  AccessToken->TokenType = TokenType;
523  AccessToken->ImpersonationLevel = Level;
524 
525  /* Initialise the lock for the access token */
526  Status = SepCreateTokenLock(AccessToken);
527  if (!NT_SUCCESS(Status))
528  {
529  ObDereferenceObject(AccessToken);
530  return Status;
531  }
532 
533  /* Copy the immutable fields */
534  AccessToken->TokenSource.SourceIdentifier = Token->TokenSource.SourceIdentifier;
535  RtlCopyMemory(AccessToken->TokenSource.SourceName,
536  Token->TokenSource.SourceName,
537  sizeof(Token->TokenSource.SourceName));
538 
539  AccessToken->AuthenticationId = Token->AuthenticationId;
540  AccessToken->ParentTokenId = Token->ParentTokenId;
541  AccessToken->ExpirationTime = Token->ExpirationTime;
542  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
543  AccessToken->DynamicCharged = Token->DynamicCharged;
544 
545  /* Lock the source token and copy the mutable fields */
547 
548  AccessToken->SessionId = Token->SessionId;
549  AccessToken->ModifiedId = Token->ModifiedId;
550 
551  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
552 
553  /* Reference the logon session */
555  if (!NT_SUCCESS(Status))
556  {
557  /* No logon session could be found, bail out */
558  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
559  /* Set the flag for proper cleanup by the delete procedure */
561  goto Quit;
562  }
563 
564  /* Insert the referenced logon session into the token */
566  if (!NT_SUCCESS(Status))
567  {
568  /* Failed to insert the logon session into the token, bail out */
569  DPRINT1("SepRmInsertLogonSessionIntoToken() failed (Status 0x%lx)\n", Status);
570  goto Quit;
571  }
572 
573  /* Fill in token debug information */
574 #if DBG
575  RtlCopyMemory(AccessToken->ImageFileName,
576  PsGetCurrentProcess()->ImageFileName,
577  min(sizeof(AccessToken->ImageFileName), sizeof(PsGetCurrentProcess()->ImageFileName)));
578 
579  AccessToken->ProcessCid = PsGetCurrentProcessId();
580  AccessToken->ThreadCid = PsGetCurrentThreadId();
581  AccessToken->CreateMethod = TOKEN_DUPLICATE_METHOD;
582 #endif
583 
584  /* Assign the data that reside in the token's variable information area */
585  AccessToken->VariableLength = VariableLength;
586  EndMem = (PVOID)&AccessToken->VariablePart;
587 
588  /* Copy the privileges */
589  AccessToken->PrivilegeCount = 0;
590  AccessToken->Privileges = NULL;
591  if (Token->Privileges && (Token->PrivilegeCount > 0))
592  {
593  ULONG PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
594  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
595 
596  ASSERT(VariableLength >= PrivilegesLength);
597 
598  AccessToken->PrivilegeCount = Token->PrivilegeCount;
599  AccessToken->Privileges = EndMem;
600  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
601  VariableLength -= PrivilegesLength;
602 
603  RtlCopyMemory(AccessToken->Privileges,
604  Token->Privileges,
605  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
606  }
607 
608  /* Copy the user and groups */
609  AccessToken->UserAndGroupCount = 0;
610  AccessToken->UserAndGroups = NULL;
611  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
612  {
613  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
614  AccessToken->UserAndGroups = EndMem;
615  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
616  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
617 
619  Token->UserAndGroups,
620  VariableLength,
621  AccessToken->UserAndGroups,
622  EndMem,
623  &EndMem,
624  &VariableLength);
625  if (!NT_SUCCESS(Status))
626  {
627  DPRINT1("RtlCopySidAndAttributesArray(UserAndGroups) failed (Status 0x%lx)\n", Status);
628  goto Quit;
629  }
630  }
631 
632  /* Find the token primary group */
634  Token->PrimaryGroup,
635  NULL,
636  &PrimaryGroupIndex,
637  NULL);
638  if (!NT_SUCCESS(Status))
639  {
640  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
641  goto Quit;
642  }
643 
644  /* Copy the restricted SIDs */
645  AccessToken->RestrictedSidCount = 0;
646  AccessToken->RestrictedSids = NULL;
647  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
648  {
649  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
650  AccessToken->RestrictedSids = EndMem;
651  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
652  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
653 
655  Token->RestrictedSids,
656  VariableLength,
657  AccessToken->RestrictedSids,
658  EndMem,
659  &EndMem,
660  &VariableLength);
661  if (!NT_SUCCESS(Status))
662  {
663  DPRINT1("RtlCopySidAndAttributesArray(RestrictedSids) failed (Status 0x%lx)\n", Status);
664  goto Quit;
665  }
666  }
667 
668  /*
669  * Filter the token by removing the disabled privileges
670  * and groups if the caller wants to duplicate an access
671  * token as effective only.
672  */
673  if (EffectiveOnly)
674  {
675  /* Begin querying the groups and search for disabled ones */
676  for (GroupsIndex = 0; GroupsIndex < AccessToken->UserAndGroupCount; GroupsIndex++)
677  {
678  /*
679  * A group or user is considered disabled if its attributes is either
680  * 0 or SE_GROUP_ENABLED is not included in the attributes flags list.
681  * That is because a certain user and/or group can have several attributes
682  * that bear no influence on whether a user/group is enabled or not
683  * (SE_GROUP_ENABLED_BY_DEFAULT for example which is a mere indicator
684  * that the group has just been enabled by default). A mandatory
685  * group (that is, the group has SE_GROUP_MANDATORY attribute)
686  * by standards it's always enabled and no one can disable it.
687  */
688  if (AccessToken->UserAndGroups[GroupsIndex].Attributes == 0 ||
689  (AccessToken->UserAndGroups[GroupsIndex].Attributes & SE_GROUP_ENABLED) == 0)
690  {
691  /*
692  * If this group is an administrators group
693  * and the token belongs to such group,
694  * we've to take away TOKEN_HAS_ADMIN_GROUP
695  * for the fact that's not enabled and as
696  * such the token no longer belongs to
697  * this group.
698  */
700  &AccessToken->UserAndGroups[GroupsIndex].Sid))
701  {
702  AccessToken->TokenFlags &= ~TOKEN_HAS_ADMIN_GROUP;
703  }
704 
705  /*
706  * A group is not enabled, it's time to remove
707  * from the token and update the groups index
708  * accordingly and continue with the next group.
709  */
710  SepRemoveUserGroupToken(AccessToken, GroupsIndex);
711  GroupsIndex--;
712  }
713  }
714 
715  /* Begin querying the privileges and search for disabled ones */
716  for (PrivilegesIndex = 0; PrivilegesIndex < AccessToken->PrivilegeCount; PrivilegesIndex++)
717  {
718  /*
719  * A privilege is considered disabled if its attributes is either
720  * 0 or SE_PRIVILEGE_ENABLED is not included in the attributes flags list.
721  * That is because a certain privilege can have several attributes
722  * that bear no influence on whether a privilege is enabled or not
723  * (SE_PRIVILEGE_ENABLED_BY_DEFAULT for example which is a mere indicator
724  * that the privilege has just been enabled by default).
725  */
726  if (AccessToken->Privileges[PrivilegesIndex].Attributes == 0 ||
727  (AccessToken->Privileges[PrivilegesIndex].Attributes & SE_PRIVILEGE_ENABLED) == 0)
728  {
729  /*
730  * A privilege is not enabled, therefor it's time
731  * to strip it from the token and continue with the next
732  * privilege. Of course we must also want to update the
733  * privileges index accordingly.
734  */
735  SepRemovePrivilegeToken(AccessToken, PrivilegesIndex);
736  PrivilegesIndex--;
737  }
738  }
739  }
740 
741  /* Now allocate the token's dynamic information area and set the data */
743  DynamicPartSize,
745  if (AccessToken->DynamicPart == NULL)
746  {
748  goto Quit;
749  }
750 
751  /* Unused memory in the dynamic area */
752  AccessToken->DynamicAvailable = 0;
753 
754  /*
755  * Assign the primary group to the token
756  * and put it in the dynamic part as well.
757  */
758  EndMem = (PVOID)AccessToken->DynamicPart;
759  AccessToken->PrimaryGroup = EndMem;
760  RtlCopySid(RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid),
761  EndMem,
762  AccessToken->UserAndGroups[PrimaryGroupIndex].Sid);
763  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
764  EndMem = (PVOID)((ULONG_PTR)EndMem + RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid));
765 
766  /*
767  * The existing token has a default DACL only
768  * if it has an allocated dynamic part.
769  */
770  if (Token->DynamicPart && Token->DefaultDacl)
771  {
772  AccessToken->DefaultDacl = EndMem;
773 
774  RtlCopyMemory(EndMem,
775  Token->DefaultDacl,
776  Token->DefaultDacl->AclSize);
777  }
778 
779  /* Return the token to the caller */
780  *NewAccessToken = AccessToken;
782 
783 Quit:
784  if (!NT_SUCCESS(Status))
785  {
786  /* Dereference the token, the delete procedure will clean it up */
787  ObDereferenceObject(AccessToken);
788  }
789 
790  /* Unlock the source token */
792 
793  return Status;
794 }
TOKEN_TYPE TokenType
Definition: setypes.h:239
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI SepRmInsertLogonSessionIntoToken(_Inout_ PTOKEN Token)
Inserts a logon session into an access token specified by the caller.
Definition: srm.c:368
ULONG DynamicCharged
Definition: setypes.h:230
LUID AuthenticationId
Definition: setypes.h:219
ULONG VariablePart
Definition: setypes.h:253
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
ULONG PrivilegeCount
Definition: setypes.h:228
NTSTATUS SepCreateTokenLock(_Inout_ PTOKEN Token)
Creates a lock for the token.
Definition: token.c:45
if(dx==0 &&dy==0)
Definition: linetemp.h:174
VOID SepRemoveUserGroupToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Removes a group from the token.
Definition: token.c:618
PLUID_AND_ATTRIBUTES Privileges
Definition: setypes.h:236
LUID ModifiedId
Definition: setypes.h:224
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG TokenFlags
Definition: setypes.h:241
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
LUID SourceIdentifier
Definition: imports.h:279
ULONG DynamicAvailable
Definition: setypes.h:231
PACL DefaultDacl
Definition: setypes.h:238
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTSTATUS SepRmReferenceLogonSession(_Inout_ PLUID LogonLuid)
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
LUID ParentTokenId
Definition: setypes.h:220
ULONG DefaultOwnerIndex
Definition: setypes.h:232
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
ULONG VariableLength
Definition: setypes.h:229
void * PVOID
Definition: retypes.h:9
ULONG SessionId
Definition: setypes.h:225
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:951
ULONG RestrictedSidCount
Definition: setypes.h:227
PULONG DynamicPart
Definition: setypes.h:237
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
PSID PrimaryGroup
Definition: setypes.h:235
LARGE_INTEGER ExpirationTime
Definition: setypes.h:221
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SE_GROUP_ENABLED
Definition: setypes.h:92
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PSID_AND_ATTRIBUTES RestrictedSids
Definition: setypes.h:234
PSID SeAliasAdminsSid
Definition: sid.c:41
#define SepReleaseTokenLock(Token)
Definition: se.h:286
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:155
VOID SepRemovePrivilegeToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Removes a privilege from the token.
Definition: token.c:582
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
CCHAR SourceName[TOKEN_SOURCE_LENGTH]
Definition: imports.h:278
#define TOKEN_HAS_ADMIN_GROUP
Definition: setypes.h:1178
ULONG UserAndGroupCount
Definition: setypes.h:226
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
LUID TokenId
Definition: setypes.h:218
#define min(a, b)
Definition: monoChain.cc:55
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define NULL
Definition: types.h:112
#define TOKEN_DUPLICATE_METHOD
Definition: se.h:71
#define DPRINT1
Definition: precomp.h:8
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:240
#define SepAcquireTokenLockShared(Token)
Definition: se.h:280
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
PSID_AND_ATTRIBUTES UserAndGroups
Definition: setypes.h:233
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
TOKEN_SOURCE TokenSource
Definition: setypes.h:217
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:401
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1180
NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Finds the primary group and default owner entity based on the submitted primary group instance and an...
Definition: token.c:1011
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:401
#define PAGED_CODE()
LUID OriginatingLogonSession
Definition: setypes.h:246

Referenced by NtDuplicateToken(), NtOpenThreadTokenEx(), SeCopyClientToken(), and SeSubProcessToken().

◆ SepPerformTokenFiltering()

static NTSTATUS SepPerformTokenFiltering ( _In_ PTOKEN  Token,
_In_opt_ PLUID_AND_ATTRIBUTES  PrivilegesToBeDeleted,
_In_opt_ PSID_AND_ATTRIBUTES  SidsToBeDisabled,
_In_opt_ PSID_AND_ATTRIBUTES  RestrictedSidsIntoToken,
_When_(PrivilegesToBeDeleted !=NULL, _In_) ULONG  PrivilegesCount,
_When_(SidsToBeDisabled !=NULL, _In_) ULONG  RegularGroupsSidCount,
_When_(RestrictedSidsIntoToken !=NULL, _In_) ULONG  RestrictedSidsCount,
_In_ ULONG  PrivilegeFlags,
_In_ KPROCESSOR_MODE  PreviousMode,
_Out_ PTOKEN FilteredToken 
)
static

Private helper function responsible for creating a restricted access token, that is, a filtered token from privileges and groups and with restricted SIDs added into the token on demand by the caller.

Parameters
[in]TokenAn existing and valid access token.
[in]PrivilegesToBeDeletedA list of privileges to be deleted within the token that's going to be filtered. This parameter is ignored if the caller wants to disable all the privileges by specifying DISABLE_MAX_PRIVILEGE in the flags parameter.
[in]SidsToBeDisabledA list of group SIDs to be disabled within the token. This parameter can be NULL.
[in]RestrictedSidsIntoTokenA list of restricted SIDs to be added into the token. This parameter can be NULL.
[in]PrivilegesCountThe privilege count of the privileges list.
[in]RegularGroupsSidCountThe SIDs count of the group SIDs list.
[in]RestrictedSidsCountThe restricted SIDs count of restricted SIDs list.
[in]PrivilegeFlagsInfluences how the privileges should be filtered in an access token. See NtFilterToken syscall for more information.
[in]PreviousModeProcessor level access mode.
[out]FilteredTokenThe filtered token, returned to the caller.
Returns
Returns STATUS_SUCCESS if token token filtering has completed successfully. STATUS_INVALID_PARAMETER is returned if one or more of the parameters do not meet the conditions imposed by the function. A failure NTSTATUS code is returned otherwise.
Remarks
The final outcome of privileges and/or SIDs filtering is not always deterministic. That is, any privileges or SIDs that aren't present in the access token are ignored and the function continues with the next privilege or SID to find for filtering. For a fully deterministic outcome the caller is responsible for querying the information details of privileges and SIDs present in the token and then afterwards use such obtained information to do any kind of filtering to the token.

Definition at line 855 of file tokenlif.c.

866 {
868  PTOKEN AccessToken;
869  PVOID EndMem;
870  ULONG DynamicPartSize;
871  ULONG RestrictedSidsLength;
872  ULONG PrivilegesLength;
873  ULONG PrimaryGroupIndex;
874  ULONG RestrictedSidsInList;
875  ULONG RestrictedSidsInToken;
876  ULONG VariableLength, TotalSize;
877  ULONG PrivsInToken, PrivsInList;
878  ULONG GroupsInToken, GroupsInList;
879  BOOLEAN WantPrivilegesDisabled;
880  BOOLEAN FoundPrivilege;
881  BOOLEAN FoundGroup;
882 
883  PAGED_CODE();
884 
885  /* Ensure that the source token is valid, and lock it */
886  ASSERT(Token);
888 
889  /* Assume the caller doesn't want privileges disabled */
890  WantPrivilegesDisabled = FALSE;
891 
892  /* Assume we haven't found anything */
893  FoundPrivilege = FALSE;
894  FoundGroup = FALSE;
895 
896  /*
897  * Take the size that we need for filtered token
898  * allocation based upon the existing access token
899  * we've been given.
900  */
901  VariableLength = Token->VariableLength;
902 
903  if (RestrictedSidsIntoToken != NULL)
904  {
905  /*
906  * If the caller provided a list of restricted SIDs
907  * to be added onto the filtered access token then
908  * we must compute the size which is the total space
909  * of the current token and the length of the restricted
910  * SIDs for the filtered token.
911  */
912  RestrictedSidsLength = RestrictedSidsCount * sizeof(SID_AND_ATTRIBUTES);
913  RestrictedSidsLength += RtlLengthSidAndAttributes(RestrictedSidsCount, RestrictedSidsIntoToken);
914  RestrictedSidsLength = ALIGN_UP_BY(RestrictedSidsLength, sizeof(PVOID));
915 
916  /*
917  * The variable length of the token is not just
918  * the actual space length of the existing token
919  * but also the sum of the restricted SIDs length.
920  */
921  VariableLength += RestrictedSidsLength;
922  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength + RestrictedSidsLength;
923  }
924  else
925  {
926  /* Otherwise the size is of the actual current token */
927  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
928  }
929 
930  /*
931  * Compute how much size we need to allocate
932  * the dynamic part of the newly duplicated
933  * token.
934  */
935  DynamicPartSize = Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0;
936  DynamicPartSize += RtlLengthSid(Token->PrimaryGroup);
937 
938  /* Set up a filtered token object */
941  NULL,
942  PreviousMode,
943  NULL,
944  TotalSize,
945  Token->DynamicCharged,
946  TotalSize,
947  (PVOID*)&AccessToken);
948  if (!NT_SUCCESS(Status))
949  {
950  DPRINT1("SepPerformTokenFiltering(): Failed to create the filtered token object (Status 0x%lx)\n", Status);
951 
952  /* Unlock the source token and bail out */
954  return Status;
955  }
956 
957  /* Initialize the token and begin filling stuff to it */
958  RtlZeroMemory(AccessToken, TotalSize);
959 
960  /* Set up a lock for the new token */
961  Status = SepCreateTokenLock(AccessToken);
962  if (!NT_SUCCESS(Status))
963  goto Quit;
964 
965  /* Allocate new IDs for the token */
966  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
967  ExAllocateLocallyUniqueId(&AccessToken->ModifiedId);
968 
969  /* Copy the type and impersonation level from the token */
970  AccessToken->TokenType = Token->TokenType;
971  AccessToken->ImpersonationLevel = Token->ImpersonationLevel;
972 
973  /* Copy the immutable fields */
974  AccessToken->TokenSource.SourceIdentifier = Token->TokenSource.SourceIdentifier;
975  RtlCopyMemory(AccessToken->TokenSource.SourceName,
976  Token->TokenSource.SourceName,
977  sizeof(Token->TokenSource.SourceName));
978 
979  AccessToken->AuthenticationId = Token->AuthenticationId;
980  AccessToken->ParentTokenId = Token->TokenId;
981  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
982  AccessToken->DynamicCharged = Token->DynamicCharged;
983 
984  AccessToken->ExpirationTime = Token->ExpirationTime;
985 
986  /* Copy the mutable fields */
987  AccessToken->SessionId = Token->SessionId;
988  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
989 
990  /* Reference the logon session */
992  if (!NT_SUCCESS(Status))
993  {
994  /* We failed, bail out*/
995  DPRINT1("SepPerformTokenFiltering(): Failed to reference the logon session (Status 0x%lx)\n", Status);
997  goto Quit;
998  }
999 
1000  /* Insert the referenced logon session into the token */
1002  if (!NT_SUCCESS(Status))
1003  {
1004  /* Failed to insert the logon session into the token, bail out */
1005  DPRINT1("SepPerformTokenFiltering(): Failed to insert the logon session into token (Status 0x%lx)\n", Status);
1006  goto Quit;
1007  }
1008 
1009  /* Fill in token debug information */
1010 #if DBG
1011  RtlCopyMemory(AccessToken->ImageFileName,
1012  PsGetCurrentProcess()->ImageFileName,
1013  min(sizeof(AccessToken->ImageFileName), sizeof(PsGetCurrentProcess()->ImageFileName)));
1014 
1015  AccessToken->ProcessCid = PsGetCurrentProcessId();
1016  AccessToken->ThreadCid = PsGetCurrentThreadId();
1017  AccessToken->CreateMethod = TOKEN_FILTER_METHOD;
1018 #endif
1019 
1020  /* Assign the data that reside in the token's variable information area */
1021  AccessToken->VariableLength = VariableLength;
1022  EndMem = (PVOID)&AccessToken->VariablePart;
1023 
1024  /* Copy the privileges from the existing token */
1025  AccessToken->PrivilegeCount = 0;
1026  AccessToken->Privileges = NULL;
1027  if (Token->Privileges && (Token->PrivilegeCount > 0))
1028  {
1029  PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1030  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
1031 
1032  /*
1033  * Ensure that the token can actually hold all
1034  * the privileges from the existing token.
1035  * Otherwise something's seriously wrong and
1036  * we've to guard ourselves.
1037  */
1038  ASSERT(VariableLength >= PrivilegesLength);
1039 
1040  AccessToken->PrivilegeCount = Token->PrivilegeCount;
1041  AccessToken->Privileges = EndMem;
1042  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
1043  VariableLength -= PrivilegesLength;
1044 
1045  RtlCopyMemory(AccessToken->Privileges,
1046  Token->Privileges,
1047  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1048  }
1049 
1050  /* Copy the user and groups */
1051  AccessToken->UserAndGroupCount = 0;
1052  AccessToken->UserAndGroups = NULL;
1053  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
1054  {
1055  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
1056  AccessToken->UserAndGroups = EndMem;
1057  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1058  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
1059 
1061  Token->UserAndGroups,
1062  VariableLength,
1063  AccessToken->UserAndGroups,
1064  EndMem,
1065  &EndMem,
1066  &VariableLength);
1067  if (!NT_SUCCESS(Status))
1068  {
1069  DPRINT1("SepPerformTokenFiltering(): Failed to copy the groups into token (Status 0x%lx)\n", Status);
1070  goto Quit;
1071  }
1072  }
1073 
1074  /* Copy the restricted SIDs */
1075  AccessToken->RestrictedSidCount = 0;
1076  AccessToken->RestrictedSids = NULL;
1077  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
1078  {
1079  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
1080  AccessToken->RestrictedSids = EndMem;
1081  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
1082  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
1083 
1085  Token->RestrictedSids,
1086  VariableLength,
1087  AccessToken->RestrictedSids,
1088  EndMem,
1089  &EndMem,
1090  &VariableLength);
1091  if (!NT_SUCCESS(Status))
1092  {
1093  DPRINT1("SepPerformTokenFiltering(): Failed to copy the restricted SIDs into token (Status 0x%lx)\n", Status);
1094  goto Quit;
1095  }
1096  }
1097 
1098  /*
1099  * Insert the restricted SIDs into the token on
1100  * the request by the caller.
1101  */
1102  if (RestrictedSidsIntoToken != NULL)
1103  {
1104  for (RestrictedSidsInList = 0; RestrictedSidsInList < RestrictedSidsCount; RestrictedSidsInList++)
1105  {
1106  /* Did the caller assign attributes to the restricted SIDs? */
1107  if (RestrictedSidsIntoToken[RestrictedSidsInList].Attributes != 0)
1108  {
1109  /* There mustn't be any attributes, bail out */
1110  DPRINT1("SepPerformTokenFiltering(): There mustn't be any attributes to restricted SIDs!\n");
1112  goto Quit;
1113  }
1114  }
1115 
1116  /*
1117  * Ensure that the token can hold the restricted SIDs
1118  * (the variable length is calculated at the beginning
1119  * of the routine call).
1120  */
1121  ASSERT(VariableLength >= RestrictedSidsLength);
1122 
1123  /*
1124  * Now let's begin inserting the restricted SIDs into the filtered
1125  * access token from the list the caller gave us.
1126  */
1127  AccessToken->RestrictedSidCount = RestrictedSidsCount;
1128  AccessToken->RestrictedSids = EndMem;
1129  EndMem = (PVOID)((ULONG_PTR)EndMem + RestrictedSidsLength);
1130  VariableLength -= RestrictedSidsLength;
1131 
1132  RtlCopyMemory(AccessToken->RestrictedSids,
1133  RestrictedSidsIntoToken,
1134  AccessToken->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1135 
1136  /*
1137  * As we've copied the restricted SIDs into
1138  * the token, we must assign them the following
1139  * combination of attributes SE_GROUP_ENABLED,
1140  * SE_GROUP_ENABLED_BY_DEFAULT and SE_GROUP_MANDATORY.
1141  * With such attributes we estabilish that restricting
1142  * SIDs into the token are enabled for access checks.
1143  */
1144  for (RestrictedSidsInToken = 0; RestrictedSidsInToken < AccessToken->RestrictedSidCount; RestrictedSidsInToken++)
1145  {
1146  AccessToken->RestrictedSids[RestrictedSidsInToken].Attributes |= (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY);
1147  }
1148 
1149  /*
1150  * As we added restricted SIDs into the token, mark
1151  * it as restricted.
1152  */
1153  AccessToken->TokenFlags |= TOKEN_IS_RESTRICTED;
1154  }
1155 
1156  /* Search for the primary group */
1158  Token->PrimaryGroup,
1159  NULL,
1160  &PrimaryGroupIndex,
1161  NULL);
1162  if (!NT_SUCCESS(Status))
1163  {
1164  DPRINT1("SepPerformTokenFiltering(): Failed searching for the primary group (Status 0x%lx)\n", Status);
1165  goto Quit;
1166  }
1167 
1168  /* Now allocate the token's dynamic information area and set the data */
1170  DynamicPartSize,
1172  if (AccessToken->DynamicPart == NULL)
1173  {
1175  goto Quit;
1176  }
1177 
1178  /* Unused memory in the dynamic area */
1179  AccessToken->DynamicAvailable = 0;
1180 
1181  /*
1182  * Assign the primary group to the token
1183  * and put it in the dynamic part as well.
1184  */
1185  EndMem = (PVOID)AccessToken->DynamicPart;
1186  AccessToken->PrimaryGroup = EndMem;
1187  RtlCopySid(RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid),
1188  EndMem,
1189  AccessToken->UserAndGroups[PrimaryGroupIndex].Sid);
1190  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
1191  EndMem = (PVOID)((ULONG_PTR)EndMem + RtlLengthSid(AccessToken->UserAndGroups[PrimaryGroupIndex].Sid));
1192 
1193  /*
1194  * The existing token has a default DACL only
1195  * if it has an allocated dynamic part.
1196  */
1197  if (Token->DynamicPart && Token->DefaultDacl)
1198  {
1199  AccessToken->DefaultDacl = EndMem;
1200 
1201  RtlCopyMemory(EndMem,
1202  Token->DefaultDacl,
1203  Token->DefaultDacl->AclSize);
1204  }
1205 
1206  /*
1207  * Now figure out what does the caller
1208  * want with the privileges.
1209  */
1210  if (PrivilegeFlags & DISABLE_MAX_PRIVILEGE)
1211  {
1212  /*
1213  * The caller wants them disabled, cache this request
1214  * for later operations.
1215  */
1216  WantPrivilegesDisabled = TRUE;
1217  }
1218 
1219  if (PrivilegeFlags & SANDBOX_INERT)
1220  {
1221  /* The caller wants an inert token, store the TOKEN_SANDBOX_INERT flag now */
1222  AccessToken->TokenFlags |= TOKEN_SANDBOX_INERT;
1223  }
1224 
1225  /*
1226  * Now it's time to filter the token's privileges.
1227  * Loop all the privileges in the token.
1228  */
1229  for (PrivsInToken = 0; PrivsInToken < AccessToken->PrivilegeCount; PrivsInToken++)
1230  {
1231  if (WantPrivilegesDisabled)
1232  {
1233  /*
1234  * We got the acknowledgement that the caller wants
1235  * to disable all the privileges so let's just do it.
1236  * However, as per the general documentation is stated
1237  * that only SE_CHANGE_NOTIFY_PRIVILEGE must be kept
1238  * therefore in that case we must skip this privilege.
1239  */
1240  if (AccessToken->Privileges[PrivsInToken].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
1241  {
1242  continue;
1243  }
1244  else
1245  {
1246  /*
1247  * The act of disabling privileges actually means
1248  * "deleting" them from the access token entirely.
1249  * First we must disable them so that we can update
1250  * token flags accordingly.
1251  */
1252  AccessToken->Privileges[PrivsInToken].Attributes &= ~SE_PRIVILEGE_ENABLED;
1253  SepUpdateSinglePrivilegeFlagToken(AccessToken, PrivsInToken);
1254 
1255  /* Remove the privileges now */
1256  SepRemovePrivilegeToken(AccessToken, PrivsInToken);
1257  PrivsInToken--;
1258  }
1259  }
1260  else
1261  {
1262  if (PrivilegesToBeDeleted != NULL)
1263  {
1264  /* Loop the privileges we've got to delete */
1265  for (PrivsInList = 0; PrivsInList < PrivilegesCount; PrivsInList++)
1266  {
1267  /* Does this privilege exist in the token? */
1268  if (RtlEqualLuid(&AccessToken->Privileges[PrivsInToken].Luid,
1269  &PrivilegesToBeDeleted[PrivsInList].Luid))
1270  {
1271  /* Mark that we found it */
1272  FoundPrivilege = TRUE;
1273  break;
1274  }
1275  }
1276 
1277  /* Did we find the privilege? */
1278  if (PrivsInList == PrivilegesCount)
1279  {
1280  /* We didn't, continue with next one */
1281  continue;
1282  }
1283  }
1284  }
1285 
1286  /*
1287  * If we have found the target privilege in the token
1288  * based on the privileges list given by the caller
1289  * then begin deleting it.
1290  */
1291  if (FoundPrivilege)
1292  {
1293  /* Disable the privilege and update the flags */
1294  AccessToken->Privileges[PrivsInToken].Attributes &= ~SE_PRIVILEGE_ENABLED;
1295  SepUpdateSinglePrivilegeFlagToken(AccessToken, PrivsInToken);
1296 
1297  /* Delete the privilege */
1298  SepRemovePrivilegeToken(AccessToken, PrivsInToken);
1299 
1300  /*
1301  * Adjust the index and reset the FoundPrivilege indicator
1302  * so that we can continue with the next privilege to delete.
1303  */
1304  PrivsInToken--;
1305  FoundPrivilege = FALSE;
1306  continue;
1307  }
1308  }
1309 
1310  /*
1311  * Loop the group SIDs that we want to disable as
1312  * per on the request by the caller.
1313  */
1314  if (SidsToBeDisabled != NULL)
1315  {
1316  for (GroupsInToken = 0; GroupsInToken < AccessToken->UserAndGroupCount; GroupsInToken++)
1317  {
1318  for (GroupsInList = 0; GroupsInList < RegularGroupsSidCount; GroupsInList++)
1319  {
1320  /* Does this group SID exist in the token? */
1321  if (RtlEqualSid(&AccessToken->UserAndGroups[GroupsInToken].Sid,
1322  &SidsToBeDisabled[GroupsInList].Sid))
1323  {
1324  /* Mark that we found it */
1325  FoundGroup = TRUE;
1326  break;
1327  }
1328  }
1329 
1330  /* Did we find the group? */
1331  if (GroupsInList == RegularGroupsSidCount)
1332  {
1333  /* We didn't, continue with next one */
1334  continue;
1335  }
1336 
1337  /* If we have found the group, disable it */
1338  if (FoundGroup)
1339  {
1340  /*
1341  * If the acess token belongs to the administrators
1342  * group and this is the target group, we must take
1343  * away TOKEN_HAS_ADMIN_GROUP flag from the token.
1344  */
1346  &AccessToken->UserAndGroups[GroupsInToken].Sid))
1347  {
1348  AccessToken->TokenFlags &= ~TOKEN_HAS_ADMIN_GROUP;
1349  }
1350 
1351  /*
1352  * If the target group that we have found it is the
1353  * owner then from now on it no longer is but the user.
1354  * Therefore assign the default owner index as the user.
1355  */
1356  if (AccessToken->DefaultOwnerIndex == GroupsInToken)
1357  {
1358  AccessToken->DefaultOwnerIndex = 0;
1359  }
1360 
1361  /*
1362  * The principle of disabling a group SID is by
1363  * taking away SE_GROUP_ENABLED_BY_DEFAULT and
1364  * SE_GROUP_ENABLED attributes and assign
1365  * SE_GROUP_USE_FOR_DENY_ONLY. This renders
1366  * SID a "Deny only" SID.
1367  */
1368  AccessToken->UserAndGroups[GroupsInToken].Attributes &= ~(SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT);
1369  AccessToken->UserAndGroups[GroupsInToken].Attributes |= SE_GROUP_USE_FOR_DENY_ONLY;
1370 
1371  /* Adjust the index and continue with the next group */
1372  GroupsInToken--;
1373  FoundGroup = FALSE;
1374  continue;
1375  }
1376  }
1377  }
1378 
1379  /* We've finally filtered the token, return it to the caller */
1380  *FilteredToken = AccessToken;
1382  DPRINT("SepPerformTokenFiltering(): The token has been filtered!\n");
1383 
1384 Quit:
1385  if (!NT_SUCCESS(Status))
1386  {
1387  /* Dereference the created token */
1388  ObDereferenceObject(AccessToken);
1389  }
1390 
1391  /* Unlock the source token */
1393 
1394  return Status;
1395 }
TOKEN_TYPE TokenType
Definition: setypes.h:239
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define TOKEN_SANDBOX_INERT
Definition: setypes.h:1181
NTSTATUS NTAPI SepRmInsertLogonSessionIntoToken(_Inout_ PTOKEN Token)
Inserts a logon session into an access token specified by the caller.
Definition: srm.c:368
ULONG DynamicCharged
Definition: setypes.h:230
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LUID AuthenticationId
Definition: setypes.h:219
ULONG VariablePart
Definition: setypes.h:253
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
ULONG PrivilegeCount
Definition: setypes.h:228
NTSTATUS SepCreateTokenLock(_Inout_ PTOKEN Token)
Creates a lock for the token.
Definition: token.c:45
if(dx==0 &&dy==0)
Definition: linetemp.h:174
PLUID_AND_ATTRIBUTES Privileges
Definition: setypes.h:236
LUID ModifiedId
Definition: setypes.h:224
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG TokenFlags
Definition: setypes.h:241
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
LUID SourceIdentifier
Definition: imports.h:279
#define FALSE
Definition: types.h:117
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
ULONG DynamicAvailable
Definition: setypes.h:231
PACL DefaultDacl
Definition: setypes.h:238
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTSTATUS SepRmReferenceLogonSession(_Inout_ PLUID LogonLuid)
unsigned char BOOLEAN
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
LUID ParentTokenId
Definition: setypes.h:220
ULONG DefaultOwnerIndex
Definition: setypes.h:232
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
ULONG VariableLength
Definition: setypes.h:229
void * PVOID
Definition: retypes.h:9
ULONG SessionId
Definition: setypes.h:225
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:951
ULONG RestrictedSidCount
Definition: setypes.h:227
PULONG DynamicPart
Definition: setypes.h:237
Status
Definition: gdiplustypes.h:24
#define SE_CHANGE_NOTIFY_PRIVILEGE
Definition: security.c:677
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
PSID PrimaryGroup
Definition: setypes.h:235
LARGE_INTEGER ExpirationTime
Definition: setypes.h:221
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SE_GROUP_ENABLED
Definition: setypes.h:92
DWORD LowPart
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
#define ObDereferenceObject
Definition: obfuncs.h:203
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PSID_AND_ATTRIBUTES RestrictedSids
Definition: setypes.h:234
PSID SeAliasAdminsSid
Definition: sid.c:41
#define SepReleaseTokenLock(Token)
Definition: se.h:286
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:155
#define SE_GROUP_USE_FOR_DENY_ONLY
Definition: setypes.h:94
#define TOKEN_FILTER_METHOD
Definition: se.h:72
VOID SepRemovePrivilegeToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Removes a privilege from the token.
Definition: token.c:582
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
CCHAR SourceName[TOKEN_SOURCE_LENGTH]
Definition: imports.h:278
#define TOKEN_HAS_ADMIN_GROUP
Definition: setypes.h:1178
VOID SepUpdateSinglePrivilegeFlagToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Updates the token's flags based upon the privilege that the token has been granted....
Definition: token.c:442
ULONG UserAndGroupCount
Definition: setypes.h:226
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
ULONG RtlLengthSidAndAttributes(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src)
Computes the length size of a SID.
Definition: token.c:965
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
LUID TokenId
Definition: setypes.h:218
#define min(a, b)
Definition: monoChain.cc:55
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
#define NULL
Definition: types.h:112
#define DISABLE_MAX_PRIVILEGE
Definition: setypes.h:114
#define DPRINT1
Definition: precomp.h:8
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:240
#define SepAcquireTokenLockShared(Token)
Definition: se.h:280
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
PSID_AND_ATTRIBUTES UserAndGroups
Definition: setypes.h:233
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define SANDBOX_INERT
Definition: setypes.h:115
#define STATUS_SUCCESS
Definition: shellext.h:65
TOKEN_SOURCE TokenSource
Definition: setypes.h:217
#define DPRINT
Definition: sndvol32.h:71
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1180
NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Finds the primary group and default owner entity based on the submitted primary group instance and an...
Definition: token.c:1011
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1179
#define PAGED_CODE()
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
LUID OriginatingLogonSession
Definition: setypes.h:246

Referenced by NtFilterToken(), and SeFilterToken().