2011-02-02 2 views
2

При установке SQL Server 2008, если эта привилегия не включена для пользователя, выполняющего установку, установка завершится неудачно. Поэтому в моем приложении перед установкой SQL Server (с использованием его бесшумной установки) я хотел бы определить, есть ли у текущего текущего пользователя привилегия «Отладка программ» (например, SeDebugPrivilege, SE_DEBUG_NAME ...)Как определить, установлена ​​ли опция «Отладка программ»?

Я не хочу знать, установлен ли текущий процесс (потому что, по-видимому, в большинстве случаев это не так, даже если привилегия включена в системе). Первоначально я думал, что API «PrivilegeCheck» будет работать, но это не так. Если вы запустите этот код под отладчиком VS, он сообщает вам, что привилегия включена. Если вы запустите его из командной строки, он сообщает вам, что привилегия отключена. Как мне исправить эту программу, чтобы действительно проверить, доступна ли эта привилегия?


HANDLE hToken;

// Get the calling thread's access token. 
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) 
{ 
    if (GetLastError() != ERROR_NO_TOKEN) 
    { 
     printf("CAN'T GET THREAD TOKEN!!!\n"); 
     return -1; 
    } 

    // Retry against process token if no thread token exists. 
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 
    { 
     printf("CAN'T GET PROCESS TOKEN!!!\n"); 
     return -1; 
    } 
} 

//Find the LUID for the debug privilege token 
LUID luidDebugPrivilege; 
if (!LookupPrivilegeValue( 
    NULL,   // lookup privilege on local system 
    "SeDebugPrivilege", // privilege to lookup 
    &luidDebugPrivilege))  // receives LUID of privilege 
{ 
    printf("LookupPrivilegeValue error: %u\n", GetLastError()); 
    return -1; 
} 

PRIVILEGE_SET privs; 
privs.PrivilegeCount = 1; 
privs.Control = PRIVILEGE_SET_ALL_NECESSARY; 

privs.Privilege[0].Luid = luidDebugPrivilege; 
privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 

BOOL bResult; 
::PrivilegeCheck(hToken, &privs, &bResult); 

if(bResult) 
{ 
    printf("DEBUG ENABLED!\n"); 
} 
else 
{ 
    printf("DEBUG NOT ENABLED!\n"); 
} 

ответ

1

Если я вас понимаю правильно, вы можете использовать LsaEnumerateAccountRights, чтобы получить список привилегий, которые имеет пользователь.

+0

Существует вещь, называемая запретная маркер, так что процесс работает как пользователь X может на самом деле имеют меньше привилегий, чем то, что обычно имеет пользователь (Большой пример UAC с раздельным маркеров модели, но Безопаснее API, добавленный в XP, тоже делает это, а IIRC - фактическое ограничение токена api было добавлено в 2000) – Anders

2

Функция GetTokenInformation может использоваться для получения списка привилегий для процесса. PrivilegeCheck проверяет, включена ли привилегия или отключена, а привилегии, не удерживаемые пользователем, всегда будут отключены. Привилегии, которые могут быть заблокированы пользователем (некоторые из них по умолчанию отключены)

С вашего вопроса, я думаю, что вы действительно хотите проверить, является ли пользователь администратором.

+1

У пользователя-администратора может быть или не быть этого набора привилегий. Мы столкнулись с несколькими примерами, когда наш клиент установил очень «жесткие» элементы управления в своих системах, и даже у администратора нет привилегий «отладочные программы». Я действительно нашел решение - мы пытаемся установить привилегию в этом процессе, и если мы МОЖЕТЕ установить его, то это означает, что пользователь имеет эту привилегию. Если мы не можем установить его, то у них нет привилегии. –

2

OK, мы выяснили это после размещения оригинального вопроса. Нам действительно нужно попытаться установить привилегии «отладочные программы» для текущего процесса. Если мы сможем включить эту привилегию, то это означает, что текущий пользователь, включенный в систему, имеет эту привилегию для них в локальном редакторе политики безопасности (gpedit.msc на XP ...)

См. Ниже пример кода, в случае кому-то еще нужно решить эту проблему! Важными частями являются:

  • Используйте LookupPrivilegeValue(), чтобы найти LUID для SeDebugPrivilege. (Для всех API-интерфейсов для этого требуется LUID ...)
  • Используйте GetTokenInformation(), чтобы узнать, какие привилегии включены в этот процесс уже. Если процесс имеет уже включенную привилегию, это означает, что процесс, скорее всего, выполняется под отладчиком и что текущий вход в систему пользователя имеет привилегию.
  • Если процесс не имеет набора привилегий, используйте функцию AdjustTokenPrivileges(), чтобы попытаться установить привилегию. Это наш метод AttemptToAddDebugPrivilegeToProcess() ниже; мы возвращаем true, если привилегия может быть установлена ​​(что означает, что у текущего пользователя, имеющего вход в систему, есть привилегия «отладочные программы») или false, если это невозможно.

#include "stdafx.h" 
#include <strsafe.h> 

void ShowLastError(LPTSTR lpszFunction) { 
    // Retrieve the system error message for the last-error code 

    LPVOID lpMsgBuf; 
    LPVOID lpDisplayBuf; 
    DWORD dw = GetLastError(); 

    FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_IGNORE_INSERTS, 
     NULL, 
     dw, 
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
     (LPTSTR) &lpMsgBuf, 
     0, NULL); 

    // Display the error message and exit the process 

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
     (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
     LocalSize(lpDisplayBuf)/sizeof(TCHAR), 
     TEXT("%s failed with error %d: %s"), 
     lpszFunction, dw, lpMsgBuf); 
    printf((LPTSTR)lpDisplayBuf); 

    LocalFree(lpMsgBuf); 
    LocalFree(lpDisplayBuf); 
} 



bool LuidsMatch(LUID l1, LUID l2) 
{ 
    return l1.LowPart == l2.LowPart && l1.HighPart == l2.HighPart; } 

bool AttemptToAddDebugPrivilegeToProcess(HANDLE hToken) { 
    //Find the LUID for the debug privilege token 
    LUID luidDebugPrivilege; 
    if (!LookupPrivilegeValue( 
     NULL,   // lookup privilege on local system 
     "SeDebugPrivilege", // privilege to lookup 
     &luidDebugPrivilege))  // receives LUID of privilege 
    { 
     printf("LookupPrivilegeValue error: %u\n", GetLastError()); 
     return false; 
    } 

    TOKEN_PRIVILEGES newState; 
    newState.PrivilegeCount = 1; 
    newState.Privileges[0].Luid = luidDebugPrivilege; 
    newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    if(AdjustTokenPrivileges(
     hToken, 
     FALSE, 
     &newState, 
     sizeof(newState), 
     NULL, //&previousState, 
     0)) 
    { 
     if(GetLastError() == ERROR_NOT_ALL_ASSIGNED) 
     { 
      printf("Couldn't set debug!!!"); 
      return false; 
     } 

     //************************************************************* 
     //IF YOU MADE IT HERE, THE USER HAS THE DEBUG PROGRAMS PRIVILEGE 
     //************************************************************* 
     printf("DEBUG OK!!!"); 
     return true; 
    } 

    printf("AdjustTokenPrivileges returned false!!!"); 
    ShowLastError("AdjustTokenPrivileges"); 
    return false; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HANDLE hToken; 

    // Get the calling thread's access token. 
    if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, TRUE, &hToken)) 
    { 
     if (GetLastError() != ERROR_NO_TOKEN) 
     { 
      printf("CAN'T GET THREAD TOKEN!!!\n"); 
      return -1; 
     } 

     // Retry against process token if no thread token exists. 
     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken)) 
     { 
      printf("CAN'T GET PROCESS TOKEN!!!\n"); 
      return -1; 
     } 
    } 

    //Find the LUID for the debug privilege token 
    LUID luidDebugPrivilege; 
    if (!LookupPrivilegeValue( 
     NULL,   // lookup privilege on local system 
     "SeDebugPrivilege", // privilege to lookup 
     &luidDebugPrivilege))  // receives LUID of privilege 
    { 
     printf("LookupPrivilegeValue error: %u\n", GetLastError()); 
     return -1; 
    } 


    //Find if the "debug programs" privilege is already assigned to this process 
    DWORD dwReturnedDataSize; 
    GetTokenInformation(
     hToken, 
     TokenPrivileges, 
     NULL, 
     0, 
     &dwReturnedDataSize); 

    BYTE* pData = new BYTE[dwReturnedDataSize]; 
    GetTokenInformation(
     hToken, 
     TokenPrivileges, 
     pData, 
     dwReturnedDataSize, 
     &dwReturnedDataSize); 

    TOKEN_PRIVILEGES* pPrivileges = (TOKEN_PRIVILEGES*)pData; 

    bool bFound = false; 

    for(unsigned int count = 0; count PrivilegeCount; count++) 
    { 
     LUID_AND_ATTRIBUTES& luidAndAttrs = pPrivileges->Privileges[count]; 

     if(LuidsMatch(luidAndAttrs.Luid, luidDebugPrivilege)) 
     { 
      bFound = true; 
      if((luidAndAttrs.Attributes & SE_PRIVILEGE_ENABLED) == SE_PRIVILEGE_ENABLED) 
      { 
       //************************************************************** 
       //IF YOU MADE IT HERE, THE USER HAS THE DEBUG PROGRAMS PRIVILEGE 
       //************************************************************** 
      } 
      else 
      { 
       printf("THIS PROCESS DOES NOT HAVE THE DEBUG PROGRAMS PRIVILEGE ENABLED\n");        AttemptToAddDebugPrivilegeToProcess(hToken); 
      } 
     } 
    } 

    if(!bFound) 
    { 
     printf("THIS PROCESS DOES NOT HAVE THE DEBUG PROGRAMS PRIVILEGE ENABLED\n"); 
     AttemptToAddDebugPrivilegeToProcess(hToken); 
    } 

    return 0; 
} 
Смежные вопросы