Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получение группы пользователя-владельца файла 
V
    Опции темы
Sheff
Дата 17.11.2007, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 503
Регистрация: 25.3.2002
Где: Зеленоград

Репутация: нет
Всего: 3



Всем доброго времени суток! 
Ситуация следующая, есть файл, нужно получить его владельца, но не само имя пользователся, а нужно выяснить является ли он администратором компьютера или нет. 
Пробую через GetSecurityInfo/LookupAccountSid, но не получается, Group SID, который выдаёт GetSecurityInfo и близко не похож на админский, хотя юзер входит в группу админов. 
Пытался также сделать: 
Код

PSID pSID = NULL; 
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; 
... 
AllocateAndInitializeSid( &SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID);


а потом: 

Код

EqualSid(pSID, myGroupSID);


Возвращает FALSE, и это естественно, если учесть что для BUILTIN/Administrators SID = S-1-5-32-544, а для моей группы = S-1-5-21-746137067-1604221776-725345543-513 

У кого какие предложения ? Как определить является юзер админом или нет ?


--------------------
--------------------------
Шеф всегда прав :)
PM MAIL WWW ICQ   Вверх
Pulse69
Дата 18.11.2007, 03:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Насколько я знаю, имея SID пользователя никак невозможно узнать, является ли он членом какой-либо группы.
Если бы у Вас был токен безопасности (например, полученный в результате олицетворения контекста безопасности или вызова функции LogonUser), Вы бы могли вызвать функцию CheckTokenMembership и проверить, находится ли SID группы администраторов в этом токене.
Можно было бы воспользоваться функциями LogonUser и ImpersonateLoggedOnUser для получения токена безопасности, однако тут есть несколько трудностей. Во-первых, нет пароля пользователя, во-вторых, на Windows 2000 понадобится специальная привелегия.
Единственая возможность проверить, является ли пользователь членом группы - получить все группы, в которые он входит, получить SIDы этих групп и с помощью EqualSid сравнить с SIDом группы администраторов.

Для получения списка групп пользователя можно воспользоваться функциями 
NetUserGetGroups и NetUserGetLocalGroups (они принимают имя пользователя, а не SID). Потом всё ясно - LookupAccountSid и EqualSid.


Это сообщение отредактировал(а) Pulse69 - 18.11.2007, 03:50
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
Sheff
Дата 18.11.2007, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 503
Регистрация: 25.3.2002
Где: Зеленоград

Репутация: нет
Всего: 3



Pulse69, да, у меня была идея юзать NetUserGetGroups и NetUserGetLocalGroups, но пугает префикс - Net. У меня с сетью ничего не связано, как-то не правильно юзать сетевые функции для этого и линковаться с Netapi32. Более того, они принимают строку имени пользователя, а мне почему-то кажется что строка не уникально идентифицирует юзера, имя юзера я конечно могу взять с помощью LookupAccountSid, а потом скормить его NetUserGetLocalGroups, но вот вопрос, будут ли эти группы группами именно того юзера, какого мне нужно ?


--------------------
--------------------------
Шеф всегда прав :)
PM MAIL WWW ICQ   Вверх
Pulse69
Дата 18.11.2007, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Насчёт сетевых функций.
NetUser* являются ещё одним способом работать с Active Directory (можно ещё использовать интерфейсы IADsUser и IADsComputer), которая хранит информацию о пользователях. Интерфейс AD для получения информации об учётных записях - сетевой, даже не смотря на то, что действия выполняются на локальном компьютере. Так почему бы не воспользоваться этими функциями.

Второе. Почему ИМЯ пользователя не идентифицирует его уникально?
Конечно, локальный пользователь и пользователь в домене может иметь одинаковое имя. Однако, пользователь DOMAIN\UserName (т.е. пользователь в домене) уникален.
После завершения вызова LookupAccountSID получается как домен, где был найден SID, так и имя пользователя. 

Дальше начинается самое интересное. Если пользователь был найден в локальной системе, домен будет равняться "BUILTIN" или имени компьютера.
Цитата

Windows XP, Windows 2000 Professional, and Windows NT Workstation:  The domain name returned for most accounts in the security database of the local computer is the name of the computer as of the last start of the system (backslashes are excluded). If the name of the computer changes, the old name continues to be returned as the domain name until the system is restarted. Some accounts are predefined by the system. The domain name returned for these accounts is BUILTIN. 

В этом случае, в NetUserGet(Local)Groups в качестве сервера следует передать NULL, функция решит, что пользователь находится на локальном компьютере и сделает своё дело.
Иначе, необходимо выполнить дополнительные действия:
Если пользователь с указанным SID найден в домене, функции семейства NetUser* должны выполняться на компьютере, являющимся первичным контроллером для этого домена, т.е. PDC. Получить контроллер домена по его имени можно с помощью функции NetGetDCName.
Да, естественно, что вызовы Net* на PDC завершаться неудачно, если у вызывающего приложения нет права на получение информации из домена. (А это, скорее всего, будет так, если приложение запускается из-под учётной записи, не входящей в группу Domain Administrators). 
Как видите, если предусмотреть все варианты, в программе появляется довольно-таки тесная связь с сетью=)
Так что в Вашем случае, NetUser* ещё не самое плохое решение;)

ЗЫЖ
Надеюсь, довольно понятно объяснил. С длинными скучными описаниями у меня всегда проблемы=)



Это сообщение отредактировал(а) Pulse69 - 18.11.2007, 14:28
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
Sheff
Дата 18.11.2007, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 503
Регистрация: 25.3.2002
Где: Зеленоград

Репутация: нет
Всего: 3



Pulse69, спасибо, очень доходчиво объяснили, но вот в чём проблема, получив группы при помощи NetUserGetLocalGroups я получаю лишь строки, ну вот допустим получил я строку Administrators, а как мне выяснить, это группа администраторов или же она просто так называется ? По строке ж нельзя судить о типе группы, более того, если у меня винда какая-нибудь испанская, но там группа админов может вообще по другому называться. Хотелось бы железобетонный способ определения админ юзер или нет...


--------------------
--------------------------
Шеф всегда прав :)
PM MAIL WWW ICQ   Вверх
Sheff
Дата 18.11.2007, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 503
Регистрация: 25.3.2002
Где: Зеленоград

Репутация: нет
Всего: 3



А, всё, понял, NetGroupGetInfo. Пока сделаю так. 
Pulse69, спасибо ещё раз.


--------------------
--------------------------
Шеф всегда прав :)
PM MAIL WWW ICQ   Вверх
Pulse69
Дата 18.11.2007, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Цитата(Sheff @  19.11.2007,  00:54 Найти цитируемый пост)
А, всё, понял, NetGroupGetInfo. Пока сделаю так. 

В принципе, можно и так, но лучше снова LookupAccountName для имени группы, а потом EqualSid.
Тогда у Вас будет SID группы, в которую входит пользователь и  SID группы, с котрой нужно провести сравнение.

--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
Sheff
Дата 22.11.2007, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 503
Регистрация: 25.3.2002
Где: Зеленоград

Репутация: нет
Всего: 3



Pulse69, да, как вы говорите действительно лучше, я так и сделал:
Код

BOOL IsGroupAdministrative(TCHAR* group) 
{ 
        BOOL result = FALSE; 
        BOOL bReturn; 
        DWORD dwSidSize = 0; 
        DWORD dwDomainSize = 0;         
        SID_NAME_USE nameUse = SidTypeGroup; 
        PSID pSid = NULL;         
        LPTSTR DomainName = NULL; 

        LookupAccountName(NULL, group, NULL, &dwSidSize, NULL, &dwDomainSize, &nameUse); 

        pSid = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwSidSize); 
         
        if (pSid == NULL) 
        { 
                goto ErrorLevel1; 
        } 

        DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwDomainSize + 1)*sizeof(TCHAR)); 
         
        if (DomainName == NULL) 
        { 
                goto ErrorLevel2; 
        } 

        bReturn = LookupAccountName(NULL, group, pSid, &dwSidSize, DomainName, &dwDomainSize, &nameUse); 
         
        if (!bReturn) 
        { 
                goto ErrorLevel3; 
        }                                 

        result = IsWellKnownSid(pSid, WinBuiltinAdministratorsSid); 

ErrorLevel3: 
        GlobalFree(DomainName); 
ErrorLevel2: 
        GlobalFree(pSid); 
ErrorLevel1: 

        return result; 
} 

BOOL IsFileOwnerAdministrator(TCHAR* path) 
{         
        BOOL result = FALSE; 
        DWORD dwReturn; 
        BOOL bReturn; 
        HANDLE hFile;         
        PSID pSidOwner = NULL; 
        PSECURITY_DESCRIPTOR pSD = NULL; 
        LPTSTR AccountName = NULL;         
        LPTSTR DomainName = NULL; 
        DWORD dwAccountName = 0; 
        DWORD dwDomainName = 0; 
        SID_NAME_USE nameUse = SidTypeGroup; 
        LPWSTR FullAccountNameW = NULL; 
        DWORD dwFlags = LG_INCLUDE_INDIRECT; 
        DWORD dwLevel = 0; 
        LPLOCALGROUP_USERS_INFO_0 pGroupInfo = NULL; 
        LPLOCALGROUP_USERS_INFO_0 pCurrentGroupInfo = NULL; 
        DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; 
        DWORD dwEntriesRead = 0; 
        DWORD dwTotalEntries = 0; 
#ifndef UNICODE 
        LPWSTR AccountNameW = NULL; 
        LPTSTR GroupNameA = NULL; 
#endif 

        hFile = CreateFile(        path,                                                 
                                                GENERIC_READ, 
                                                FILE_SHARE_READ, 
                                                NULL, 
                                                OPEN_EXISTING, 
                                                FILE_ATTRIBUTE_NORMAL, 
                                                NULL); 
         
        if (hFile == INVALID_HANDLE_VALUE) 
        { 
                goto ErrorLevel1; 
        }         
                         
        dwReturn = GetSecurityInfo(        hFile, 
                                                                SE_FILE_OBJECT, 
                                                                OWNER_SECURITY_INFORMATION, 
                                                                &pSidOwner, 
                                                                NULL, 
                                                                NULL, 
                                                                NULL, 
                                                                &pSD ); 
         
        if (dwReturn != ERROR_SUCCESS) 
        { 
                goto ErrorLevel2; 
        }                 

        bReturn = LookupAccountSid(        NULL, 
                                                                pSidOwner, 
                                                                AccountName, 
                                                                (LPDWORD)&dwAccountName, 
                                                                DomainName, 
                                                                (LPDWORD)&dwDomainName, 
                                                                &nameUse ); 
         
        AccountName = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwAccountName + 1)*sizeof(TCHAR)); 
         
        if (AccountName == NULL) 
        { 
                goto ErrorLevel3; 
        } 

        DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwDomainName + 1)*sizeof(TCHAR)); 
         
        if (DomainName == NULL) 
        { 
                goto ErrorLevel4; 
        } 

        FullAccountNameW = (LPWSTR)GlobalAlloc(GMEM_FIXED, (dwAccountName + dwDomainName + 2)*2); 
         
        if (FullAccountNameW == NULL) 
        { 
                goto ErrorLevel5; 
        }         

        bReturn = LookupAccountSid(        NULL, 
                                                                pSidOwner, 
                                                                AccountName, 
                                                                (LPDWORD)&dwAccountName, 
                                                                DomainName, 
                                                                (LPDWORD)&dwDomainName, 
                                                                &nameUse ); 
         
        if (bReturn == FALSE) 
        { 
                goto ErrorLevel6; 
        }         

        if (        (_tcscmp(DomainName, TEXT("BUILTIN")) == 0) && 
                        IsGroupAdministrative(AccountName) ) 
        { 
                result = TRUE; 
                goto ErrorLevel6; 
        }         
#ifdef UNICODE 
        wcscpy(FullAccountNameW, DomainName); 
        wcscat(FullAccountNameW, TEXT("\\")); 
        wcscat(FullAccountNameW, AccountName); 
#else 
        AccountNameW = (LPWSTR)GlobalAlloc(GMEM_FIXED, (dwAccountName + 1)*sizeof(WCHAR)); 
         
        if (AccountNameW == NULL) 
        { 
                goto ErrorLevel6; 
        } 

        mbstowcs(AccountNameW, AccountName, dwAccountName + 1); 
        mbstowcs(FullAccountNameW, DomainName, dwDomainName + 1); 
        wcscat(FullAccountNameW, L"\\"); 
        wcscat(FullAccountNameW, AccountNameW); 

        GlobalFree(AccountNameW); 
#endif                 
         
        dwReturn = NetUserGetLocalGroups(        NULL, 
                                                                                FullAccountNameW, 
                                                                                dwLevel, 
                                                                                dwFlags, 
                                                                                (LPBYTE*) &pGroupInfo, 
                                                                                dwPrefMaxLen, 
                                                                                &dwEntriesRead, 
                                                                                &dwTotalEntries ); 

        if (dwReturn != NERR_Success) 
        { 
                goto ErrorLevel6; 
        }         
                           
        if ( (pCurrentGroupInfo = pGroupInfo) != NULL ) 
        { 
                for (DWORD i=0; i<dwEntriesRead; ++i) 
                { 
                        if (pCurrentGroupInfo == NULL) 
                        {                                 
                                break; 
                        } 

#ifndef UNICODE 
                        GroupNameA = (LPSTR)GlobalAlloc(GMEM_FIXED, wcslen(pCurrentGroupInfo->lgrui0_name) + 1); 
                         
                        if (GroupNameA == NULL) 
                        { 
                                break; 
                        } 

                        wcstombs(GroupNameA, pCurrentGroupInfo->lgrui0_name, wcslen(pCurrentGroupInfo->lgrui0_name) + 1); 

                        if (IsGroupAdministrative(GroupNameA)) 
                        { 
                                GlobalFree(GroupNameA); 

                                result = TRUE;                                 
                                break; 
                        } 

                        GlobalFree(GroupNameA); 
#else 
                        if (IsGroupAdministrative(pCurrentGroupInfo->lgrui0_name)) 
                        { 
                                result = TRUE; 
                                break; 
                        } 
#endif 

                        ++pCurrentGroupInfo; 
                } 
        } 

        NetApiBufferFree(pGroupInfo); 
ErrorLevel6: 
        GlobalFree(FullAccountNameW); 
ErrorLevel5: 
        GlobalFree(DomainName); 
ErrorLevel4: 
        GlobalFree(AccountName); 
ErrorLevel3:         
        LocalFree(pSD); 
ErrorLevel2:         
        CloseHandle(hFile); 
ErrorLevel1: 

        return result; 
} 



--------------------
--------------------------
Шеф всегда прав :)
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0611 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.