nim_duilib/base/win32/security_util.cpp
jiajia_deng 4933d1f2bc Remove dependency on shared
Signed-off-by: jiajia_deng <2894220@gmail.com>
2019-09-20 16:27:58 +08:00

169 lines
4.1 KiB
C++

// Copyright (c) 2012, NetEase Inc. All rights reserved.
//
// wrt(guangguang)
// 2012/5/31
//
// utilities for security associated operations
#include "base/win32/security_util.h"
#if defined(OS_WIN)
#include <aclapi.h> // ConvertStringSecurityDescriptorToSecurityDescriptorW
#include <sddl.h> // SetSecurityInfo
#include "base/win32/win_util.h"
#include "base/win32/scoped_win_handle.h"
namespace nbase
{
namespace win32
{
static const wchar_t kLowIntegeritySddlSaclW[] = L"S:(ML;;NW;;;LW)";
bool SetObjectToLowIntegrity(HANDLE hObject, SE_OBJECT_TYPE type /*= SE_KERNEL_OBJECT*/)
{
if(!IsRunningOnVistaOrHigher())
return true;
bool bRet = false;
DWORD dwErr = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL;
BOOL fSaclPresent = FALSE;
BOOL fSaclDefaulted = FALSE;
if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(kLowIntegeritySddlSaclW, SDDL_REVISION_1, &pSD, NULL))
{
if (::GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted))
{
dwErr = SetSecurityInfo(hObject, type, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl);
bRet = (ERROR_SUCCESS == dwErr);
}
::LocalFree(pSD);
}
return bRet;
}
bool IsUserAdmin()
{
SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
PSID administrators_group = NULL;
BOOL result = ::AllocateAndInitializeSid(&nt_authority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&administrators_group);
if (result)
{
if (!::CheckTokenMembership(NULL, administrators_group, &result))
result = false;
::FreeSid(administrators_group);
}
return !!result;
}
bool IsUserNonElevatedAdmin()
{
// If pre-Vista return false;
if (!IsRunningOnVistaOrHigher())
return false;
bool non_elevated_admin = false;
ScopedWinHandle token;
if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_READ, &token))
{
TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
DWORD infoLen = 0;
if (::GetTokenInformation(token.Get(),
TokenElevationType,
reinterpret_cast<void*>(&elevation_type),
sizeof(elevation_type),
&infoLen))
{
if (elevation_type == TokenElevationTypeLimited)
non_elevated_admin = true;
}
}
return non_elevated_admin;
}
HRESULT GetSidIntegrityLevel(PSID sid, MANDATORY_LEVEL* level)
{
static SID_IDENTIFIER_AUTHORITY mandatory_label_auth =
SECURITY_MANDATORY_LABEL_AUTHORITY;
if (!IsValidSid(sid))
return E_FAIL;
SID_IDENTIFIER_AUTHORITY* authority = ::GetSidIdentifierAuthority(sid);
if (!authority)
return E_FAIL;
if (memcmp(authority, &mandatory_label_auth, sizeof(SID_IDENTIFIER_AUTHORITY)))
return E_FAIL;
PUCHAR count = ::GetSidSubAuthorityCount(sid);
if (!count || *count != 1)
return E_FAIL;
DWORD* rid = ::GetSidSubAuthority(sid, 0);
if (!rid)
return E_FAIL;
if ((*rid & 0xFFF) != 0 || *rid > SECURITY_MANDATORY_PROTECTED_PROCESS_RID)
return E_FAIL;
*level = static_cast<MANDATORY_LEVEL>(*rid >> 12);
return S_OK;
}
HRESULT GetProcessIntegrityLevel(DWORD process_id, MANDATORY_LEVEL* level)
{
if (!IsRunningOnVistaOrHigher())
return E_NOTIMPL;
if (process_id == 0)
process_id = ::GetCurrentProcessId();
HRESULT result = E_FAIL;
HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
if (process != NULL)
{
HANDLE current_token;
if (::OpenProcessToken(process,
TOKEN_QUERY | TOKEN_QUERY_SOURCE,
&current_token))
{
DWORD label_size = 0;
TOKEN_MANDATORY_LABEL* label;
::GetTokenInformation(current_token,
TokenIntegrityLevel,
NULL,
0,
&label_size);
if (label_size && (label = reinterpret_cast<TOKEN_MANDATORY_LABEL*>
(::LocalAlloc(LPTR, label_size))) != NULL)
{
if (::GetTokenInformation(current_token,
TokenIntegrityLevel,
label,
label_size,
&label_size))
{
result = GetSidIntegrityLevel(label->Label.Sid, level);
}
::LocalFree(label);
}
::CloseHandle(current_token);
}
::CloseHandle(process);
}
return result;
}
} // namespace win32
} // namespace nbase
#endif // OS_WIN