Сущность технологии СОМ. Библиотека программиста
Сущность технологии СОМ. Библиотека программиста читать книгу онлайн
В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
В идеале серверные процессы конфигурируются для запуска как отдельные принципалы защиты. Управлять этим можно, помещая именованную величину RunAs в имя учетной записи в AppID:
[HKCRAppID{27EE6A4D-DF65-11d0-8C5F-0080C73925BA}]
RunAs="DomainXUserY"
Если эта именованная величина присутствует, SCM будет использовать указанное имя учетной записи для создания нового регистрационного маркера (login token) и присвоит этот маркер серверному процессу. Для правильной работы этой схемы требуются два условия. Во-первых, соответствующий пароль должен быть записан в определенном месте реестра в качестве ключа локальных средств защиты (LSA – Local Security Authority). Во-вторых, указанная учетная запись пользователя должна иметь полномочия «Вход в систему как пакетное задание» («Logon as a batch job»). При установке значения RunAs утилита DCOMCNFG.EXE обеспечивает выполнение обоих этих условий [2].
Для предотвращения спуфинга (spoofing, получение доступа путем обмана) классов злонамеренными программами CoRegisterClassObject проверяет, зарегистрирован ли AppID данного класса. Если AppID имеет установку RunAs, то COM гарантирует, что принципал вызывающей программы совпадает с именем принципала, записанным в реестре. Если же вызывающая программа не имеет указанной учетной записи RunAs для AppID класса, то вызов метода CoRegisterСlassObject будет отклонен и возвратится известный HRESULT CO_E_WRONG_SERVER_IDENTITY. Поскольку конфигурационные установки COM записаны в защищенной части реестра, только привилегированные пользователи могут изменять список соответствия классов и пользователей.
Важно отметить, что когда в AppID имеется явная учетная запись пользователя RunAs, то SCM всегда будет запускать серверный процесс в его собственной отдельной window-станции (window station) [3]. Это означает, что серверный процесс не может с легкостью ни создавать окна, видимые для интерактивного пользователя на данной машине, ни принимать информацию с клавиатуры, от мыши или из буфера (clipboard). Вообще говоря, такая защита полезна, поскольку не дает простым (naive) серверам COM влиять на деятельность пользователя, работающего на машине [4]. К сожалению, иногда серверному процессу бывает необходимо связаться с авторизовавшимся (logged on) в данный момент пользователем. Одним из способов достижения этого является использование для управления window-станциями и рабочими столами (desktop) явных API-функций COM, что дает потоку возможность временно выполняться на интерактивном рабочем столе. При выполнении на интерактивном рабочем столе любые окна, которые создает поток, будут видимы интерактивному пользователю, и, кроме того, поток может получать аппаратные сообщения (hardware messages) от клавиатуры и мыши. Если же все, что нужно, – это получить от пользователя ответ типа да/нет, то на этот случай в API-функции Win32 MessageBox имеется флаг MB_SERVICE_NOTIFICATION, при выставлении которого, без какого-либо добавочного кода, на интерактивном рабочем столе появится окно сообщения.
Если требуется расширенное взаимодействие с интерактивным пользователем, то использование Win32 API window-станции может стать весьма громоздким. Лучшим подходом могло бы стать выделение компонентов пользовательского интерфейса во второй внепроцессный сервер, который сможет работать на window-станции, отличной от той, на который запущена основная иерархия объектов. Чтобы заставить серверный процесс, содержащий компоненты пользовательского интерфейса, работать при интерактивной пользовательской window-станции, COM распознает характерное значение RunAs «Interactive User» («Интерактивный пользователь»):
[HKCRAppID{27EE6A4D-DF65-11d0-8C5F-0080C73925BA}]
RunAs="Interactive User"
При использовании этого значения COM запускает новый серверный процесс в window-станции, соответствующей подсоединенному в текущий момент пользователю. Для запроса полномочий для нового серверного процесса COM при создании этого нового серверного процесса просто копирует маркер текущего интерактивного сеанса. Это означает, что в реестр не требуется записывать никаких паролей. К сожалению, и этот режим активации не обходится без ловушек. Во-первых, если активационный запрос поступает в момент, когда на хост-машине не зарегистрировано ни одного пользователя, то активационный запрос даст сбой с результатом E_ACCESSDENIED. Кроме того, если интерактивный пользователь выйдет из сети в тот момент, когда у серверного процесса еще есть подключенные клиенты, то серверный процесс будет преждевременно прерван, что приведет к грубому отсоединению всех существующих в тот момент заместителей. И наконец, часто невозможно предсказать, какой пользователь будет подсоединен во время активации, что усложняет обеспечение достаточных прав и привилегий доступа ко всем необходимым ресурсам для данного объекта. Эти ограничения сводят применимость такого режима активации к простым компонентам пользовательского интерфейса [5].
Одна интересная разновидность управления маркером и window-станцией серверного процесса относится к службам NT. Напомним, что наличие именованной величины LocalService заставляет SCM использовать для запуска серверного процесса NT Service Control Manager вместо CreateProcess или CreateProcessAsUser. При запуске серверных процессов как сервисов NT COM не контролирует, с каким принципалом запускается этот процесс просто потому, что это жестко запрограммировано в конфигурации соответствующей запущенной службы NT. В этом случае COM игнорирует именованную величину RunAs, чтобы убедиться, что случайные процессы не могут имитировать вызовы CoRegisterClassObject. Наличие именованной величины LocalService требует, чтобы вызывающая программа выполнялась как сервис NT. Если сам этот сервис сконфигурирован на запуск как встроенная учетная запись SYSTEM, то серверный процесс либо запустит интерактивную window– станцию, либо будет запущена заранее определенная window-станция, совместно используемая всеми сервисами NT в качестве SYSTEM (это зависит от того, как именно сконфигурирован сервис NT). Если вместо этого сервис NT сконфигурирован для выполнения как отдельная учетная запись пользователя, то NT Service Control Manager будет всегда запускать сервис NT под новой window– станцией, специфической для данного серверного процесса.
Одно общее соображение в пользу реализации сервера COM как сервиса NT заключается в том, что только сервисы NT способны выполняться со встроенной учетной записью SYSTEM. Эта учетная запись обыкновенно имеет больший доступ к таким локальным ресурсам, как файлы и ключи реестра. Кроме того, эта учетная запись часто является единственной, которая может выступать как часть доверительной компьютерной базы (trusted computing base) и использовать низкоуровневые службы защиты, доступ к которым был бы опасен из обычных пользовательских учетных записей. К сожалению, хотя учетная запись SYSTEM воистину всемогуща в локальной системе, она полностью бессильна для доступа к защищенным удаленным ресурсам, в том числе к удаленным файловым системам и к удаленным объектам COM. Это обстоятельство делает учетную запись SYSTEM отчасти менее полезной для построения распределенных систем, чем можно было бы ожидать. Вне зависимости от того, используется ли сервер как сервис NT или в качестве традиционного процесса Win32, принято создавать отдельную учетную запись пользователя для каждого приложения COM, которое имеет полные полномочия для доступа в сеть.
Где мы находимся?
В данной главе рассматривались вопросы, относящиеся к выделению классов в отдельные серверные процессы. COM поддерживает запуск серверных процессов на основе запросов на активацию. Эти серверные процессы должны саморегистрироваться с помощью библиотеки COM, используя CoRegisterClassObject для того, чтобы обеспечить доступ к объектам своего класса со стороны внешних клиентов. Архитектура системы безопасности COM тесно связана с собственной моделью безопасности операционной системы и основывается на трех различных понятиях. Целостность и аутентичность сообщений ORPC, которыми обмениваются клиент и объект, обеспечивается аутентификацией. Контроль доступа выявляет, какие принципалы защиты могут иметь доступ к объектам, экспортированным из данного процесса. Управление маркерами отслеживает, какие полномочия используются для запуска серверных процессов и выполнения методов объекта.