Структура SECURITY_ATTRIBUTES и CreateNamedPipe ()

Мой сценарий следующий: процесс, который создает объект именованного канала сCreateNamedPipe() имеет права администратора, но клиентский процесс «подключается» к нему сCreateFile() не. ПроходяNULL в качестве последнего аргументаCreateNamedPipe() По умолчанию отображается только для прав администратора.

Как хак, я попытался сделать на стороне сервераImpersonateLoggedOnUser()/RevertToSelf() метод для продолжительности кода, связанного с каналом, но он не работает. Мне кажется, что лучше всего здесь сделатьSECURITY_ATTRIBUTES структура до последнего параметраCreateNamedPipe(), но у меня проблемы с выяснением, как это сделать.

Пример MSDN Есть пример, относящийся к манипулированию ключами реестра, но мне не хватает опыта, чтобы приспособить его к моим целям.

Вот что я пробовал:

if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
    SECURITY_WORLD_RID,
    0, 0, 0, 0, 0, 0, 0,
    &pEveryoneSID))
{
    _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
    ret_val = 0;
    goto Cleanup;
}

// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID;

// there's another ACE for administrators in between, but is of no relevance here

dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);

// Initialize a security descriptor.  
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
    SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
    _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
    ret_val = 0;
    goto Cleanup;
}

if (!InitializeSecurityDescriptor(pSD,
    SECURITY_DESCRIPTOR_REVISION))
{
    _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
        GetLastError());
    ret_val = 0;
    goto Cleanup;
}

// Add the ACL to the security descriptor. 
if (!SetSecurityDescriptorDacl(pSD,
    TRUE,     // bDaclPresent flag   
    pACL,
    FALSE))   // not a default DACL 
{
    _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),
        GetLastError());
    ret_val = 0;
    goto Cleanup;
}

    // Initialize a security attributes structure.
*sa = new SECURITY_ATTRIBUTES;

(*sa)->nLength = sizeof(SECURITY_ATTRIBUTES);
(*sa)->lpSecurityDescriptor = pSD;
(*sa)->bInheritHandle = FALSE;

В результате клиентская сторона получает ошибку0x5 (доступ запрещен) включенCreateFile(), Что здесь не так?

 ehoopz17 июл. 2016 г., 09:51
Да, извини @RbBm, должен был сделать комментарий более заметным или просто оставить его в покое.
 Harry Johnston17 июл. 2016 г., 04:48
@RbMm: если вы читаете комментарии, он просто пропустил этот фрагмент кода. Ehoopz, пожалуйста, постарайся избежать этого, так как это часто вызывает путаницу. Кроме того, вы будете удивлены, как часто настоящая проблема оказывается в куске кода, который вы считаете неуместным. :-)
 RbMm16 июл. 2016 г., 20:43
ваша ошибка в строке SetEntriesInAcl (2, ea, NULL, & pACL); когда нужно SetEntriesInAcl (1, ea, NULL, & pACL); - вы действительно инициируете и используете только 1 запись

Ответы на вопрос(1)

Решение Вопроса

чтобы разрешить кому-либо доступ к каналу:

pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!pSD)
{
    ...
}

if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
    ...
}

if (!SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE))
{
    ...
}

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;

... = CreateNamedPipe(..., &sa);
 ehoopz17 июл. 2016 г., 10:52
Несмотря на то, что в итоге я выбрал другое решение (обмен клиент / сервер, о котором я упоминал в предыдущем комментарии), это отвечает на первоначальный вопрос, поэтому я принял его.
 Remy Lebeau17 июл. 2016 г., 04:02
Это позволяет любому клиентскому процессу подключаться к серверу именованных каналов без отклонения разрешениями безопасности. Он не позволяет клиенту именованного канала перехватывать данные между другим клиентом и сервером или выдавать себя за другого клиента. Кроме того, только сервер может выдать себя за клиента (см.ImpersonateNamedPipeClient()).
 ehoopz17 июл. 2016 г., 10:11
РАБОТАЕТ! Здорово. Тем не менее, предоставление полного разрешения доступа всем кажется экстремальным. Кроме того, я только что понял, что в моем конкретном сценарии роли двух процессов можно довольно легко поменять местами; то есть пусть непривилегированный процесс создает именованный канал, а не наоборот. Я попробую и посмотрю, как это будет.
 Harry Johnston17 июл. 2016 г., 03:55
В зависимости от того, для чего используется труба, это может быть небезопасно. Это позволило бы любому процессу в системе создать новый экземпляр именованного канала, потенциально перехватывая данные, предназначенные для сервера именованного канала, или (в некоторых случаях) даже выдавая себя за клиента.
 Harry Johnston17 июл. 2016 г., 04:35
Теоретически, по крайней мере, он позволяет любому процессу стать сервером для того же именованного канала, поскольку он предоставляет FILE_CREATE_PIPE_INSTANCE. Другие механизмы могут вступить в игру, хотя, мне придется экспериментировать. Даже если это так, я лично предпочел бы использовать ACL, который явно требует прав администратора для создания другого экземпляра, на всякий случай.

Ваш ответ на вопрос