• FILE_GENERIC_READ
• FILE_GENERIC_WRITE
• SYNCHRONIZE (разрешает потоку ожидать освобождения канала)
Если при подключении клиента требуется предоставить все права доступа, можно просто указать уровень доступа STANDARD_RIGHTS_REQUIRED. Для получения полного доступа (дуплексного, входящего, исходящего и так далее) вам также придется воспользоваться маской 0x1FF. В сервере, представленном в программе 15.6, предусмотрена защита экземпляров его именованных каналов с использованием этих прав доступа. Доступ к каналу имеют только клиенты, запущенные на выполнение владельцем канала, хотя предоставление доступа к каналу также членам группы не вызывает никаких сложностей.
Программа 15.6. ServerNP: защита именованного канала
/* Глава 15. ServerNP. Предусмотрена защита именованного канала.
* Многопоточный сервер командной строки. Версия на основе
* именованного канала.
* Использование: Server [ИмяПользователя ИмяГруппы]. */
…
_tmain(int argc, LPTSTR argv[]) {
…
HANDLE hNp, hMonitor, hSrvrThread[MAXCLIENTS];
DWORD iNp, MonitorId, ThreadId;
DWORD AceMasks[] = /* Права доступа к именованному каналу. */
{STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0X1FF, 0, 0 };
LPSECURITY_ATTRIBUTES pNPSA = NULL;
…
if (argc == 4) /* Необязательный параметр защиты канала. */
pNPSA = InitializeAccessOnlySA(0440, argv[1], argv[2], AceMasks, &hSecHeap);
…
/* Создать экземпляр канала для каждого серверного потока. */
…
for (iNp = 0; iNp < MAXCLIENTS; iNp++) {
hNp = CreateNamedPipe(SERVER_PIPE, PIPE_ACCESS_DUPLEX, PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE | PIPE_WAIT, MAXCLIENTS, 0, 0, INFINITE, pNPSA);
if (hNp == INVALID_HANDLE_VALUE) ReportError(_T("Невозможно открыть именованный канал."), 1, TRUE);
}
…
}
Защита объектов ядра и приватных объектов
Многие объекты, такие как процессы, потоки или мьютексы, являются объектами ядра (kernel objects). Для получения и установки дескрипторов безопасности ядра используются функции GetKernelObjectsSecurity и SetKernelObjectsSecurity, аналогичные функциям защиты файлов, описанным в настоящей главе. Однако при этом вы должны знать, какие права доступа соответствуют данному объекту; в следующем разделе показано, как определить эти права.
Существует также возможность связывания дескрипторов безопасности с приватными, сгенерированными программой объектами, такими как объекты Windows Sockets или патентованные базы данных. Соответствующими функциями являются GetPrivateObjectSecurity и SetPrivateObjectSecurity. Ответственность за принудительное введение определенных прав доступа к таким объектам несет программист, который для изменения дескрипторов безопасности должен использовать функции CreatePrivateObjectSecurity и DestroyPrivateObjectSecurity.
Модели "пользователь, группа, прочие", которую реализует функция InitUnixSA в большинстве случаев будет вполне достаточно, хотя с использованием тех же базовых методов могут реализовываться и другие модели.
Вместе с тем, для этого необходимо знать фактические значения маски АСЕ, которые соответствуют тому или иному объекту ядра. Эти значения не всегда достаточно хорошо документированы, но для их нахождения можно воспользоваться несколькими способами.
• Прочитайте документацию с описанием функции открытия интересующего вас объекта. Флаги доступа имеют те же значения, что и флаги, используемые в маске АСЕ. Так, функция OpenMutex использует флаги MUTEX_ALL_ACCESS и SYNCHRONIZE (второй из указанных флагов требуется для любого объекта, который может использоваться с функциями WaitForSingleObject или WaitForMultipleObjects). Другие объекты, например процессы, имеют множество других дополнительных флагов доступа.
• Полезная в этом отношении информация может содержаться также в документации по функциям "создания" объектов.
• Проверьте, не содержатся ли флаги, применимые к интересующему вас объекту, в заголовочных файлах WINNT.H и WINBASE.Н.
Пример: защита процесса и его потоков
В документации по функции OpenProcess представлена подробная градация прав доступа, соответствующих самым разнообразным функциям, выполнение которых требует применения дескриптора процесса.
Так, значение PROCESS_TERMINATE параметра доступа разрешает процессу (а фактически — потока внутри процесса) использовать дескриптор процесса в функции TerminateProcess для завершения процесса.
Доступ на уровне PROCESS_QUERY_INFORMATION разрешает использование дескриптора процесса при вызове функций GetExitCodeProcess или GetPriorityClass, тогда как уровень доступа PROCESS_ALL_ACCESS разрешает любой доступ, а доступ SYNCHRONIZE требуется для выполнения функций ожидания завершения процесса.
Читать дальше