blob: cf1067393dab48af66bc390127bda7ca8b1178c0 [file] [log] [blame]
// Copyright 2004-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
#include "omaha/common/user_rights.h"
#include <lm.h>
#include <wtsapi32.h>
#include "base/scoped_ptr.h"
#include "omaha/common/debug.h"
#include "omaha/common/error.h"
#include "omaha/common/logging.h"
#include "omaha/common/reg_key.h"
#include "omaha/common/scope_guard.h"
#include "omaha/common/scoped_any.h"
#include "omaha/common/system_info.h"
#include "omaha/common/vistautil.h"
namespace omaha {
bool UserRights::TokenIsAdmin(HANDLE token) {
return BelongsToGroup(token, DOMAIN_ALIAS_RID_ADMINS);
}
bool UserRights::UserIsAdmin() {
return BelongsToGroup(NULL, DOMAIN_ALIAS_RID_ADMINS);
}
bool UserRights::UserIsUser() {
return BelongsToGroup(NULL, DOMAIN_ALIAS_RID_USERS);
}
bool UserRights::UserIsPowerUser() {
return BelongsToGroup(NULL, DOMAIN_ALIAS_RID_POWER_USERS);
}
bool UserRights::UserIsGuest() {
return BelongsToGroup(NULL, DOMAIN_ALIAS_RID_GUESTS);
}
bool UserRights::BelongsToGroup(HANDLE token, int group_id) {
SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
PSID group = NULL;
BOOL check = ::AllocateAndInitializeSid(&nt_authority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
group_id,
0,
0,
0,
0,
0,
0,
&group);
if (check) {
if (!::CheckTokenMembership(token, group, &check)) {
check = false;
}
::FreeSid(group);
}
return !!check;
}
bool UserRights::UserIsRestricted() {
scoped_handle token;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, address(token))) {
UTIL_LOG(LE, (_T("[UserRights::UserIsRestricted - OpenProcessToken failed]")
_T("[0x%08x]"), HRESULTFromLastError()));
return true;
}
return !!::IsTokenRestricted(get(token));
}
bool UserRights::UserIsLowOrUntrustedIntegrity() {
if (SystemInfo::IsRunningOnVistaOrLater()) {
MANDATORY_LEVEL integrity_level = MandatoryLevelUntrusted;
if (FAILED(vista_util::GetProcessIntegrityLevel(0, &integrity_level)) ||
integrity_level == MandatoryLevelUntrusted ||
integrity_level == MandatoryLevelLow) {
return true;
}
}
return false;
}
HRESULT UserRights::UserIsLoggedOnInteractively(bool* is_logged_on) {
ASSERT1(is_logged_on);
*is_logged_on = false;
HRESULT hr = S_OK;
TCHAR* domain_name = NULL;
DWORD domain_name_len = 0;
if (!::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION,
WTSDomainName,
&domain_name,
&domain_name_len)) {
hr = HRESULTFromLastError();
UTIL_LOG(LE, (_T("[WTSQuerySessionInformation failed][0x%08x]"), hr));
return hr;
}
ON_SCOPE_EXIT(::WTSFreeMemory, domain_name);
TCHAR* user_name = NULL;
DWORD user_name_len = 0;
if (!::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION,
WTSUserName,
&user_name,
&user_name_len)) {
hr = HRESULTFromLastError();
UTIL_LOG(LE, (_T("[WTSQuerySessionInformation failed][0x%08x]"), hr));
return hr;
}
ON_SCOPE_EXIT(::WTSFreeMemory, user_name);
UTIL_LOG(L2, (_T("[ts domain=%s][ts user=%s]"), domain_name, user_name));
// Occasionally, the domain name and user name could not be retrieved when
// the program is started just at logon time.
if (!(domain_name && *domain_name && user_name && *user_name)) {
return E_FAIL;
}
// Get the user associated with the current process.
WKSTA_USER_INFO_1* user_info = NULL;
NET_API_STATUS status = ::NetWkstaUserGetInfo(
NULL,
1,
reinterpret_cast<uint8**>(&user_info));
if (status != NERR_Success || user_info == NULL) {
UTIL_LOG(LE, (_T("[NetWkstaUserGetInfo failed][%u]"), status));
return HRESULT_FROM_WIN32(status);
}
ON_SCOPE_EXIT(::NetApiBufferFree, user_info);
UTIL_LOG(L2, (_T("[wks domain=%s][wks user=%s]"),
user_info->wkui1_logon_domain, user_info->wkui1_username));
*is_logged_on = _tcsicmp(user_info->wkui1_logon_domain, domain_name) == 0 &&
_tcsicmp(user_info->wkui1_username, user_name) == 0;
return S_OK;
}
HRESULT UserRights::GetCallerToken(HANDLE* token) {
ASSERT1(token);
scoped_handle smart_token;
HRESULT hr = ::CoImpersonateClient();
if (FAILED(hr)) {
return hr;
}
hr = ::OpenThreadToken(::GetCurrentThread(),
TOKEN_QUERY,
true,
address(smart_token)) ? S_OK : HRESULTFromLastError();
if (FAILED(hr)) {
return hr;
}
hr = ::CoRevertToSelf();
if (FAILED(hr)) {
return hr;
}
*token = release(smart_token);
return S_OK;
}
bool UserRights::ImpersonateAndVerifyCallerIsAdmin() {
scoped_handle impersonated_token;
if (FAILED(GetCallerToken(address(impersonated_token)))) {
return false;
}
return TokenIsAdmin(get(impersonated_token));
}
} // namespace omaha