Хотя соответствующая часть кода в листинге программы 11.3 опущена, сервер, полный программный код которого находится на Web-сайте книги, предоставляет возможность защиты его именованных каналов для предотвращения доступа к ним пользователей, не обладающих необходимыми полномочиями. Необязательные параметры командной строки позволяют указать имя пользователя и групповое имя:
Server [ИмяПользователя ИмяГруппы]
Если имена пользователя и группы опущены, используются коды защиты, заданные по умолчанию. Заметьте, что для создания необязательных атрибутов защиты в полной версии программы 11.3 (которая доступна на Web-сайте) и в программе 15.6 используются методы из программы 15.3. В то же время, вместо вызова функции InitUnixSA мы теперь вызываем более простую функцию InitializeAccessOnlySA, которая обеспечивает предоставление только доступа, разрешенного элементами АСЕ, и помещает последний АСЕ, запрещающий доступ, в конец списка ACL. В программе 15.6 представлены соответствующие участки кода, которые не были отражены в листинге программы 11.3. В случае именованных каналов важное значение имеют следующие права доступа:
• 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);
}
…
}