Визуальное программирование и MFC

       

Защита вызовов


После создания объект готов к приему вызовов своих методов от клиентов. Когда последние выполняются на других компьютерах, можно с пользой задействовать ряд сервисов контроля доступа. Вот самые важные:

  • аутентификация позволяет удостовериться, что пользователь именно тот, за кого себя выдает. С помощью аутентификации объект достоверно определяет личность клиента. Если поддерживается взаимная аутентификация, то и клиент может быть уверен в том, что сервер является именно тем за кого себя выдает;
  • авторизация позволяет определить, что клиент имеет npаво делать. Для принятия подобного решения объект может использовать любую схему. Например, в Microsoft Windows NT объект может воспользоваться встроенной поддержкой ACL;
  • целостность данных гарантирует, что принятые по сети данные не были изменены при пересылке. В отсутствие этого сервиса некто мог бы "выловить" пакет из сети, изменить его и послать первоначальному реципиенту, причем последний не заметил бы подмены;
  • секретность данных гарантирует, что пересылаемые и сети данные не будут прочитаны при передаче. Обычно для этого используется шифрование данных, что может существенно снизить производительность.
  • Сервисы защиты могут обеспечиваться различными механизмами. Например, механизмы защиты, включенные в состав Windows NT, поддерживают все 4 упомянутых сервиса. Альтернативой является Kerberos — система защиты, разработанная в Массачусетском технологическом институте (Massachusetts Institute of Technology). Kerberos обеспечивает аутентификацию, целостность и секретность данных, но не решает вопросы авторизации (но Kerberos поддерживает взаимную аутентификацию — средство, отсутствующее в составе механизмов распределенной защиты Windows NT). Другие механизмы защиты предоставляют другие комбинации сервисов защиты.

    В связи с большим количеством механизмов, обеспечивающих защиту вызовов, архитекторы DCOM столкнулись с проблемой: какой из них поддерживать? Было решено не выбирать какой-то один, но определить общие интерфейсы, способные работать со многими из существующих вариантов. Тем не менее первая версия DCOM, выпущенная в 1996 году, поддерживает только механизмы защиты Windows NT.
    В следующих версиях планируется включить поддержку Kerberos.

    Независимо от используемого базового механизма, интерфейсы защиты вызовов DCOM определяют 2 основные возможности: автоматическую и поинтерфейсную защиты. В первом случае клиентский или серверный процесс устанавливает уровень защиты по умолчанию для всех вызовов этого процесса или вызовов, выполняемых им. Во втором — разные установки защиты можно задать для разных интерфейсов одного объекта или для разных объектов. Можно использовать и оба варианта одновременно, установив значения по умолчанию с помощью автоматической защиты и выполнив затем тонкую настройку, используя поинтерфейсную защиту.



    Автоматическая защита



    Будет ли процесс клиентом, выдающим запросы, или объектом, принимающим запросы, или и тем и другим, он может задать значения по умолчанию автоматической защиты вызовом CoInitializeSecurity. Вызов этой функции достаточно сложен, но позволяет процессу быстро и полностью задать свои требования по защите. Вот его наиболее интересные параметры:

  • ACL определяет, кто имеет право вызывать методы любого объекта данного процесса, а также кому это явно запрещено;




  • уровень аутентификации процесса определяет, как часто выполняется аутентификация (один раз при установке соединения, один раз для каждого вызова, или один раз для каждого пакета), а также должны ли использоваться средства обеспечения целостности и секретности данных. Вызовы, выполняемые данным процессом, будут исполняться на заданном уровне защиты, и все вызовы извне, использующие уровень ниже заданного, будут отвергаться;


  • список сервисов аутентификации вызовов извне.


  • Вызвав эту единственную функцию, процесс может установить значения широкого диапазона параметров защиты. Но, решив не прибегать к ней, процесс все равно наследует значения по умолчанию для данной системы. В защищенной зоне системного реестра администратор может задать общемашинные значения по умолчанию, применяемые ко всем процессам, не вызывающим CoInitializeSecurity самостоятельно.


    Эти установки по умолчанию включают уровень аутентификации и ACL, управляющий тем, кто имеет доступ к процессу без собственного ACL.



    Поинтерфейсная защита



    Автоматическая защита — грубый инструмент. Она определяет один набор параметров защиты для всего, что делает процесс, будь он клиентом или сервером. Автоматическая защита, кроме того, проста в использовании, и для многих приложений — это именно то, что нужно. Но не каждый процесс может обойтись одной автоматической защитой. Например, клиент может пожелать использовать разные уровни защиты для вызовов разных объектов или даже разных интерфейсов одного объекта. Серверу, реализующему несколько объектов, может потребоваться применять к каждому из них или к каждому из их интерфейсов особые схемы авторизации. Поинтерфейсная защита обеспечивает поддержку подобных тонких разграничении.



    В отличие от автоматической защиты, когда один вызов устанавливает параметры как серверной, так и клиентской защиты, Поинтерфейсная защита выглядит для клиента и сервера по-разному. Чтобы использовать ее, клиент должен получить указатель на интерфейс IClientSecurity, тогда как серверу понадобится для этого указатель на интерфейс IServerSecurity. Методы этих интерфейсов позволяют клиенту и серверу определить конкретные нужные им сервисы и уровни защиты.

    С точки зрения клиента, каждый объект поддерживает IClientSecurity. Клиент получает указатель на этот интерфейс обычным образом с помощью QueryInterface. На самом деле эта внешне очевидная ситуация не так проста. Фактически интерфейс IClientSecurity реализован самой СОМ в библиотеке, подгружаемой к клиенту. При запросе клиентом IClientSecurity с помощью QueryInterface обращение к объекту никогда не производится. Вместо этого возвращается указатель на локальную реализацию интерфейса.



    С помощью методов полученного указателя IClientSecurity клиент может установить параметры защиты для каждого интерфейса объекта. В действительности, однако, при этом устанавливаются параметры, поддерживаемые заместителем данного интерфейса внутри клиента,
    так что вызовы IClientSecurity не поступают к самому объекту.


    Среди методов IClientSecurity отметим:

  • SetBlanket устанавливает информацию защиты, используемую всеми вызовами через данный заместитель. Задаваемые здесь значения переопределяют те, что были заданы с помощью CoInitializeSecurity. SetBlanket можно использовать для указания сервиса аутентификации, такого как Kerberos (в будущем) или сервис аутентификации Windows NT (сегодня) со специфичным для данного сервиса именем клиента, передаваемым с каждым вызовом. Данный метод позволяет также установить уровень аутентификации, аналогично CoInitializeSecurity;


  • QueryBlanket возвращает текущие значения параметров защиты заместителя.


  • После того как клиент задал параметры защиты заместителя с помощью IClientSecurity::SetBlanket, эти параметры используются при всех вызовах, выполняемых через данный заместитель. Вызовы через другие заместители осуществляются через параметры, заданные для последних. (Если параметры защиты не были заданы явно, используются значения, установленные CoInitializeSecurity либо общемашинные умолчания.) Вспомогательные функции, в которых заключены типичные последовательности вызовов, несколько облегчают установку этих параметров. Вместо того, например, чтобы запрашивать IClientSecurity, вызывать IClientSecurity::SetBlanket и затем освобождать указатель на интерфейс IClientSecurity, клиент может вызвать CoSetProxyBlanket, помещающую все эти вызовы в "удобную упаковку".

    Независимо от используемых параметров защиты каждый вызов, сделанный клиентом, приводит в конце концов к исполнению кода метода, реализованного объектом. Установление личности клиента (аутентификация) выполняется СОМ, а также любое необходимое декодирование и проверка целостности принятых данных. Если какая-то из проверок не удалась, вызов отвергается. А если все в порядке, метод объекта должен сам определить, имеет ли данный клиент право на выполнение того, что запрашивает. Другими словами, объект должен выполнить авторизацию.



    Чтобы определить, что имеет право делать данный клиент, надо знать, кем он является и какие параметры защиты он задал для данного вызова. Для получения этой информации код метода объекта начинает с вызова библиотечной функции CoGetCallContext, возвращающей указатель на IServerSecurity — серверный аналог IClientSecurity. Задействовав методы этого интерфейса, объект может получить информацию о клиенте, сделавшем данный вызов, а затем использовать ее для определения того, что этот клиент имеет право делать.


    Среди методов IServerSecurity отметим следующие:

  • QueryBlanket возвращает информацию, заданную клиентом с помощью IClientSecurity: :SetBlanket. Эта информация, включая имя клиента и запрошенный им уровень аутентификации, позволяет серверу принять решение по авторизации. Сервер может, например, убедиться в использовании клиентом надлежащего уровня аутентификации (чтобы это ни означало для данного объекта). Если проверка успешна, объект может далее сравнить имя клиента с ACL, управляющим доступом к объекту. Или же метод может использовать совершенно иную схему для принятия подобного решения — строго определенных правил здесь нет;


  • ImpersonateClient позволяет объекту или потоку управления внутри объекта "надеть" личину клиента. Возможны различные уровни имперсонации (управляются клиентом): от использования ее только для проверок ACL до способности объекта выполнять запросы к другим удаленным объектам под именем клиента — так называемого делегирования (delegation). (Впрочем, делегирование не поддерживается в первой версии DCOM);


  • RevertToSelf возвращает объекту или потоку внутри него первоначальную личность после вызова IServerSecurity::ImpersonateClient.


  • Как и в случае IClientSecurity, есть несколько вспомогательных функций. Например, объект может вызвать CoQueryClient-Blanket, заключающую в себе вызовы CoGetCallContext, IServerSecurity: :QueryBlanket и IServerSecurity:: Release.


    Содержание раздела