// -------------------------------------------------------------------------- // Module Name: TokenInformation.h // // Copyright (c) 1999-2000, Microsoft Corporation // // Class to get information about either the current thread/process token or // a specified token. // // History: 1999-10-05 vtan created // 2000-02-01 vtan moved from Neptune to Whistler // -------------------------------------------------------------------------- #include "StandardHeader.h" #include "TokenInformation.h" // -------------------------------------------------------------------------- // CTokenInformation::CTokenInformation // // Arguments: hToken = Optional user token to get information on. // // Returns: // // Purpose: Duplicates the given token if provided. Otherwise the thread // token is opened or the process token if that doesn't exist. // // History: 1999-10-05 vtan created // -------------------------------------------------------------------------- CTokenInformation::CTokenInformation (HANDLE hToken) : _hToken(hToken), _hTokenToRelease(NULL), _pvGroupBuffer(NULL), _pvPrivilegeBuffer(NULL), _pvUserBuffer(NULL), _pszUserLogonName(NULL), _pszUserDisplayName(NULL) { if (hToken == NULL) { if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &_hToken) == FALSE) { TBOOL(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &_hToken)); } if (_hToken != NULL) { _hTokenToRelease = _hToken; } } } // -------------------------------------------------------------------------- // CTokenInformation::~CTokenInformation // // Arguments: // // Returns: // // Purpose: Releases resources used by the object. // // History: 1999-10-05 vtan created // -------------------------------------------------------------------------- CTokenInformation::~CTokenInformation (void) { ReleaseMemory(_pszUserLogonName); ReleaseMemory(_pszUserDisplayName); ReleaseMemory(_pvUserBuffer); ReleaseMemory(_pvPrivilegeBuffer); ReleaseMemory(_pvGroupBuffer); ReleaseHandle(_hTokenToRelease); } // -------------------------------------------------------------------------- // CTokenInformation::GetLogonSID // // Arguments: // // Returns: PSID // // Purpose: Gets token information for the token groups. Walks the groups // looking for the SID with SE_GROUP_LOGON_ID and returns a // pointer to this SID. This memory is available for the scope // of the object. // // History: 1999-10-05 vtan created // -------------------------------------------------------------------------- PSID CTokenInformation::GetLogonSID (void) { PSID pSID; pSID = NULL; if ((_hToken != NULL) && (_pvGroupBuffer == NULL)) { GetTokenGroups(); } if (_pvGroupBuffer != NULL) { ULONG ulIndex, ulLimit; TOKEN_GROUPS *pTG; pTG = reinterpret_cast(_pvGroupBuffer); ulLimit = pTG->GroupCount; for (ulIndex = 0; (pSID == NULL) && (ulIndex < ulLimit); ++ulIndex) { if ((pTG->Groups[ulIndex].Attributes & SE_GROUP_LOGON_ID) != 0) { pSID = pTG->Groups[ulIndex].Sid; } } } return(pSID); } // -------------------------------------------------------------------------- // CTokenInformation::GetUserSID // // Arguments: // // Returns: PSID // // Purpose: Gets token information for the token user. This returns the // SID for the user of the token. This memory is available for // the scope of the object. // // History: 1999-10-05 vtan created // -------------------------------------------------------------------------- PSID CTokenInformation::GetUserSID (void) { PSID pSID; if ((_pvUserBuffer == NULL) && (_hToken != NULL)) { DWORD dwReturnLength; dwReturnLength = 0; (BOOL)GetTokenInformation(_hToken, TokenUser, NULL, 0, &dwReturnLength); _pvUserBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength); if ((_pvUserBuffer != NULL) && (GetTokenInformation(_hToken, TokenUser, _pvUserBuffer, dwReturnLength, &dwReturnLength) == FALSE)) { ReleaseMemory(_pvUserBuffer); _pvUserBuffer = NULL; } } if (_pvUserBuffer != NULL) { pSID = reinterpret_cast(_pvUserBuffer)->User.Sid; } else { pSID = NULL; } return(pSID); } // -------------------------------------------------------------------------- // CTokenInformation::IsUserTheSystem // // Arguments: // // Returns: bool // // Purpose: Gets token information for the token user. This returns // whether the user is the local system. // // History: 1999-12-13 vtan created // -------------------------------------------------------------------------- bool CTokenInformation::IsUserTheSystem (void) { static const LUID sLUIDSystem = SYSTEM_LUID; ULONG ulReturnLength; TOKEN_STATISTICS tokenStatistics; return((GetTokenInformation(_hToken, TokenStatistics, &tokenStatistics, sizeof(tokenStatistics), &ulReturnLength) != FALSE) && RtlEqualLuid(&tokenStatistics.AuthenticationId, &sLUIDSystem)); } // -------------------------------------------------------------------------- // CTokenInformation::IsUserAnAdministrator // // Arguments: // // Returns: bool // // Purpose: Gets token information for the token user. This returns // whether the user is a member of the local administrator group. // // History: 92-05-06 davidc created // 1999-11-06 vtan stolen // -------------------------------------------------------------------------- bool CTokenInformation::IsUserAnAdministrator (void) { bool fIsAnAdministrator; fIsAnAdministrator = false; if ((_hToken != NULL) && (_pvGroupBuffer == NULL)) { GetTokenGroups(); } if (_pvGroupBuffer != NULL) { PSID pAdministratorSID; static SID_IDENTIFIER_AUTHORITY sSystemSidAuthority = SECURITY_NT_AUTHORITY; if (NT_SUCCESS(RtlAllocateAndInitializeSid(&sSystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorSID))) { ULONG ulIndex, ulLimit; TOKEN_GROUPS *pTG; pTG = reinterpret_cast(_pvGroupBuffer); ulLimit = pTG->GroupCount; for (ulIndex = 0; !fIsAnAdministrator && (ulIndex < ulLimit); ++ulIndex) { fIsAnAdministrator = ((RtlEqualSid(pTG->Groups[ulIndex].Sid, pAdministratorSID) != FALSE) && ((pTG->Groups[ulIndex].Attributes & SE_GROUP_ENABLED) != 0)); } (void*)RtlFreeSid(pAdministratorSID); } } return(fIsAnAdministrator); } // -------------------------------------------------------------------------- // CTokenInformation::UserHasPrivilege // // Arguments: // // Returns: bool // // Purpose: Gets token information for the token user. This returns // whether the user is a member of the local administrator group. // // History: 2000-04-26 vtan created // -------------------------------------------------------------------------- bool CTokenInformation::UserHasPrivilege (DWORD dwPrivilege) { bool fUserHasPrivilege; fUserHasPrivilege = false; if ((_hToken != NULL) && (_pvPrivilegeBuffer == NULL)) { GetTokenPrivileges(); } if (_pvPrivilegeBuffer != NULL) { ULONG ulIndex, ulLimit; TOKEN_PRIVILEGES *pTP; LUID luidPrivilege; luidPrivilege.LowPart = dwPrivilege; luidPrivilege.HighPart = 0; pTP = reinterpret_cast(_pvPrivilegeBuffer); ulLimit = pTP->PrivilegeCount; for (ulIndex = 0; !fUserHasPrivilege && (ulIndex < ulLimit); ++ulIndex) { fUserHasPrivilege = (RtlEqualLuid(&pTP->Privileges[ulIndex].Luid, &luidPrivilege) != FALSE); } } return(fUserHasPrivilege); } // -------------------------------------------------------------------------- // CTokenInformation::GetUserName // // Arguments: // // Returns: WCHAR // // Purpose: Looks up the account name of the implicit token.. // // History: 2000-08-31 vtan created // -------------------------------------------------------------------------- const WCHAR* CTokenInformation::GetUserName (void) { if (_pszUserLogonName == NULL) { DWORD dwUserNameSize, dwReferencedDomainSize; SID_NAME_USE eUse; WCHAR *pszReferencedDomain; dwUserNameSize = dwReferencedDomainSize = 0; (BOOL)LookupAccountSid(NULL, GetUserSID(), NULL, &dwUserNameSize, NULL, &dwReferencedDomainSize, &eUse); pszReferencedDomain = static_cast(LocalAlloc(LMEM_FIXED, dwReferencedDomainSize * sizeof(WCHAR))); if (pszReferencedDomain != NULL) { _pszUserLogonName = static_cast(LocalAlloc(LMEM_FIXED, dwUserNameSize * sizeof(WCHAR))); if (_pszUserLogonName != NULL) { if (LookupAccountSid(NULL, GetUserSID(), _pszUserLogonName, &dwUserNameSize, pszReferencedDomain, &dwReferencedDomainSize, &eUse) == FALSE) { ReleaseMemory(_pszUserLogonName); } } (HLOCAL)LocalFree(pszReferencedDomain); } } return(_pszUserLogonName); } // -------------------------------------------------------------------------- // CTokenInformation::GetUserDisplayName // // Arguments: // // Returns: WCHAR // // Purpose: Returns the display name of the implicit token. // // History: 2000-08-31 vtan created // -------------------------------------------------------------------------- const WCHAR* CTokenInformation::GetUserDisplayName (void) { if (_pszUserDisplayName == NULL) { const WCHAR *pszUserName; pszUserName = GetUserName(); if (pszUserName != NULL) { USER_INFO_2 *pUserInfo; if (NERR_Success == NetUserGetInfo(NULL, pszUserName, 2, reinterpret_cast(&pUserInfo))) { const WCHAR *pszUserDisplayName; if (pUserInfo->usri2_full_name[0] != L'\0') { pszUserDisplayName = pUserInfo->usri2_full_name; } else { pszUserDisplayName = pszUserName; } _pszUserDisplayName = static_cast(LocalAlloc(LMEM_FIXED, (lstrlen(pszUserDisplayName) + sizeof('\0')) * sizeof(WCHAR))); if (_pszUserDisplayName != NULL) { lstrcpy(_pszUserDisplayName, pszUserDisplayName); } TW32(NetApiBufferFree(pUserInfo)); } } } return(_pszUserDisplayName); } // -------------------------------------------------------------------------- // CTokenInformation::LogonUser // // Arguments: See the platform SDK under LogonUser. // // Returns: DWORD // // Purpose: Calls advapi32!LogonUserW with supplied credentials using // interactive logon type. Returns the error code as a DWORD // rather than the standard Win32 API method which allows the // filtering of certain error codes. // // History: 2001-03-28 vtan created // -------------------------------------------------------------------------- DWORD CTokenInformation::LogonUser (const WCHAR *pszUsername, const WCHAR *pszDomain, const WCHAR *pszPassword, HANDLE *phToken) { DWORD dwErrorCode; if (::LogonUserW(const_cast(pszUsername), const_cast(pszDomain), const_cast(pszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, phToken) != FALSE) { dwErrorCode = ERROR_SUCCESS; } else { *phToken = NULL; dwErrorCode = GetLastError(); // Ignore ERROR_PASSWORD_MUST_CHANGE and ERROR_PASSWORD_EXPIRED. if ((dwErrorCode == ERROR_PASSWORD_MUST_CHANGE) || (dwErrorCode == ERROR_PASSWORD_EXPIRED)) { dwErrorCode = ERROR_SUCCESS; } } return(dwErrorCode); } // -------------------------------------------------------------------------- // CTokenInformation::IsSameUser // // Arguments: hToken1 = Token of one user. // hToken2 = Token of other user. // // Returns: bool // // Purpose: Compares the user SID of the tokens for a match. // // History: 2001-03-28 vtan created // -------------------------------------------------------------------------- bool CTokenInformation::IsSameUser (HANDLE hToken1, HANDLE hToken2) { PSID pSID1; PSID pSID2; CTokenInformation tokenInformation1(hToken1); CTokenInformation tokenInformation2(hToken2); pSID1 = tokenInformation1.GetUserSID(); pSID2 = tokenInformation2.GetUserSID(); return((pSID1 != NULL) && (pSID2 != NULL) && (EqualSid(pSID1, pSID2) != FALSE)); } // -------------------------------------------------------------------------- // CTokenInformation::GetTokenGroups // // Arguments: // // Returns: // // Purpose: Gets token information for the token user. This function // allocates the memory for the token groups. This memory is // available for the scope of the object. // // History: 1999-11-06 vtan created // -------------------------------------------------------------------------- void CTokenInformation::GetTokenGroups (void) { DWORD dwReturnLength; dwReturnLength = 0; (BOOL)GetTokenInformation(_hToken, TokenGroups, NULL, 0, &dwReturnLength); _pvGroupBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength); if ((_pvGroupBuffer != NULL) && (GetTokenInformation(_hToken, TokenGroups, _pvGroupBuffer, dwReturnLength, &dwReturnLength) == FALSE)) { ReleaseMemory(_pvGroupBuffer); _pvGroupBuffer = NULL; } } // -------------------------------------------------------------------------- // CTokenInformation::GetTokenPrivileges // // Arguments: // // Returns: // // Purpose: Gets token privileges for the token user. This function // allocates the memory for the token privileges. This memory is // available for the scope of the object. // // History: 2000-04-26 vtan created // -------------------------------------------------------------------------- void CTokenInformation::GetTokenPrivileges (void) { DWORD dwReturnLength; dwReturnLength = 0; (BOOL)GetTokenInformation(_hToken, TokenPrivileges, NULL, 0, &dwReturnLength); _pvPrivilegeBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength); if ((_pvPrivilegeBuffer != NULL) && (GetTokenInformation(_hToken, TokenPrivileges, _pvPrivilegeBuffer, dwReturnLength, &dwReturnLength) == FALSE)) { ReleaseMemory(_pvPrivilegeBuffer); _pvPrivilegeBuffer = NULL; } }