Системное программирование в среде Windows
Шрифт:
Защита объектов ядра и приватных объектов
Многие объекты, такие как процессы, потоки или мьютексы, являются объектами ядра (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 требуется для выполнения функций ожидания завершения процесса.
Чтобы проиллюстрировать эти идеи, на основе программы JobShell, рассмотренной в главе 6, была разработана программа JobShellSecure.c, которая разрешает доступ к управляемому процессу только его владельцу (или администратору). Эта программа находится на Web-сайте книги.
Обзор дополнительных возможностей защиты объектов
О средствах безопасности Windows можно было сказать намного больше, но настоящая глава является лишь введением в эту тему, показывая, как организовать защиту объектов Windows, используя API системы безопасности. В последующих разделах кратко рассмотрены дополнительные вопросы, относящиеся к этой тематике.
Удаление элементов АСЕ
Функция DeleteAce удаляет АСЕ, определяемый с помощью индекса аналогично тому, как это делается в случае функции GetAce.
Абсолютные и самоопределяющиеся относительные дескрипторы безопасности
Программа 15.5, позволяющая изменять ACL, удобна тем, что просто заменяет один дескриптор безопасности (SD) другим. В то же время, при замене существующих SD следует проявлять осторожность, поскольку они бывают двух типов: абсолютные (absolute) и самоопределяющиеся относительные (self-relative). Внутреннее устройство этих структур данных для наших целей не имеет значения, однако вы должны понимать, в чем состоит различие между ними, и как переходить от одного из них к другому.
• В процессе создания SD они являются абсолютными, и входящие в них указатели указывают на различные структуры, находящиеся в памяти. По сути, функция InitializeSecurityDescriptor создает абсолютный SD.
• При связывании SD с постоянно существующим объектом, например файлом, ОС объединяет все данные, относящиеся к SD, в одну компактную самоопределяющуюся структуру. В то же время, изменение SD (например, изменение ACL) порождает трудности при управлении пространством в пределах структуры абсолютного SD.