Немного о безопасностиВадим Годунко <>, 2008 г. Фактически всегда в распределённых информационных системах остро стоит вопрос обеспечения информационной безопасности. Спецификация CORBA так же не обходит стороной эти вопросы и предлагает ряд стандартных механизмов обеспечения информационной безопасности. PolyORB поддерживает то подмножество механизмов, которое не требует специальных дополнительных коммерческих библиотек. Важной особенностью службы безопасности CORBA является её полная прозрачность для приложений. Всё, что требуется со стороны разработчика — подключить библиотеки службы безопасности к программе и соответствующим образом настроить PolyORB. Прежде чем переходить к описанию способов подключения и настроек PolyORB хочется немного объяснить основные принципы работы службы безопасности CORBA. Настройка параметров службы безопасности — политики безопасности — осуществляется отдельно для сервера и клиента. Для сервера задаются минимальные — требуемые — значения политики безопасности, и определяются максимальные — поддерживаемые — значения политики безопасности. Для клиента задаются только минимальные — требуемые — значения политики безопасности. Брокеры объектных запросов клиента и сервера самостоятельно согласуют свои пожелания и возможности таким образом, что бы имеющимися средствами удовлетворить минимальные — требуемые — как клиентом, так и сервером, значения политики безопасности. Оценка требуемых и поддерживаемых значений политики безопасности выполняется по следующим критериям:
Все приведённые критерии поддерживаются PolyORB, однако здесь опущены неподдерживаемые критерии — DelegationByClient (требует библиотек поддержки сертификатор полномочий X.509AC), DetectReplay и DetectMisordering (требует наличия библиотек поддержки специальных протоколов передачи защищаемых данных). Для реализации безопасного взаимодействия возможно использование одного или нескольких механизмов защиты данных. Каждый механизм способен реализовывать свой специфический набор критериев, и зачастую очень специфичным образом. Имеется возможность группировки некоторых механизмов безопасного взаимодействия и одновременного их использования. Это возможно благодаря наличию трёх уровней безопасного взаимодействия: транспортного уровня, уровеня дополнительной аутентификации и уровня атрибутов безопасности. На каждом уровне возможно выбрать максимиум только один из поддерживаемых механизмов. PolyORB предоставляет следующие механизмы безопасного взаимодействия:
Точная и аккуратная настройка всех механизмов безопасности требует детального понимания всего многообразия имеющихся параметров и поэтому выходит за рамки данного описания. В качестве примера мы будем использовать самый простой изх имеющихся механизмов — механизм аутентификации по имени и паролю — GSSUP. Этот механизм выполняет передачу пароля в открытом виде, и, таким образом, его можно безопасно использовать только одновременно с использованием шифрования данных на транспортном уровне. Теперь пришло время доработать клиентскую и серверную программы. Исправления в клиентской программе сводятся к подключению в программу пакета PolyORB.Setup.Secure_Client. Далее приводится полный текст клиента для удобства использования: with Ada.Characters.Conversions; with Ada.Command_Line; with Ada.Integer_Wide_Text_IO; with Ada.Strings.Wide_Unbounded.Wide_Text_IO; with Ada.Wide_Text_IO; with CORBA.ORB; with PolyORB.Setup.Client; -- Конфигурирование PolyORB для работы в режиме клиента. -- with PolyORB.Setup.Secure_Client; with Users.User; with Users.UserFactory; -- .Helper; with Users.UserFinder; -- .Helper; procedure Client is begin -- Инициализация ORB. declare Argv : CORBA.ORB.Arg_List := CORBA.ORB.Command_Line_Arguments; begin CORBA.ORB.Init (CORBA.ORB.To_CORBA_String ("ORB"), Argv); end; if Ada.Command_Line.Argument_Count /= 2 then Ada.Wide_Text_IO.Put_Line ("client <factory_ior> <finder_ior>"); return; end if; declare Factory : Users.UserFactory.Ref; Finder : Users.UserFinder.Ref; Current : Users.User.Ref; procedure Create_New_User is Name : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; Surname : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; begin -- Ввод имени и фамилии пользователя. Ada.Wide_Text_IO.Put ("Name: "); Ada.Wide_Text_IO.Flush; Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (Name); Ada.Wide_Text_IO.Put ("Surname: "); Ada.Wide_Text_IO.Flush; Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (Surname); -- Создание нового объекта. Current := Users.UserFactory.create (Factory, CORBA.To_CORBA_Wide_String (Ada.Strings.Wide_Unbounded.To_Wide_String (Name)), CORBA.To_CORBA_Wide_String (Ada.Strings.Wide_Unbounded.To_Wide_String (Surname))); end Create_New_User; procedure Save_IOR is File_Name : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; File : Ada.Wide_Text_IO.File_Type; begin -- Проверка наличия текущей объектной ссылки. if Users.User.Is_Nil (Current) then Ada.Wide_Text_IO.Put_Line ("ERROR: No IOR in buffer"); end if; -- Ввод имени файла. Ada.Wide_Text_IO.Put ("File name: "); Ada.Wide_Text_IO.Flush; Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (File_Name); -- Создание файла и сохранение в нём объектной ссылки. Ada.Wide_Text_IO.Create (File, Ada.Wide_Text_IO.Out_File, Ada.Characters.Conversions.To_String (Ada.Strings.Wide_Unbounded.To_Wide_String (File_Name))); Ada.Wide_Text_IO.Put_Line (File, Ada.Characters.Conversions.To_Wide_String (CORBA.To_Standard_String (CORBA.ORB.Object_To_String (Current)))); Ada.Wide_Text_IO.Close (File); end Save_IOR; procedure Load_IOR is File_Name : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; File : Ada.Wide_Text_IO.File_Type; Image : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; begin -- Ввод имени файла. Ada.Wide_Text_IO.Put ("File name: "); Ada.Wide_Text_IO.Flush; Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (File_Name); -- Открытие файла и загрузка из него объектной ссылки. Ada.Wide_Text_IO.Open (File, Ada.Wide_Text_IO.In_File, Ada.Characters.Conversions.To_String (Ada.Strings.Wide_Unbounded.To_Wide_String (File_Name))); Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (File, Image); Ada.Wide_Text_IO.Close (File); -- Создание объектной ссылки по её образу. CORBA.ORB.String_To_Object (CORBA.To_CORBA_String (Ada.Characters.Conversions.To_String (Ada.Strings.Wide_Unbounded.To_Wide_String (Image))), Current); end Load_IOR; procedure Show_Attributes is begin -- Проверка наличия текущей объектной ссылки. if Users.User.Is_Nil (Current) then Ada.Wide_Text_IO.Put_Line ("ERROR: No IOR in buffer"); return; end if; -- Получение и отображение значений атрибутов. Ada.Wide_Text_IO.Put_Line ("Name: '" & CORBA.To_Standard_Wide_String (Users.User.Get_name (Current)) & "'"); Ada.Wide_Text_IO.Put_Line ("Surname: '" & CORBA.To_Standard_Wide_String (Users.User.Get_surname (Current)) & "'"); end Show_Attributes; procedure Search_By_Name is Name : Ada.Strings.Wide_Unbounded.Unbounded_Wide_String; Found : Users.UserSequence; Index : Integer; begin Ada.Wide_Text_IO.Put ("Name: "); Ada.Wide_Text_IO.Flush; Ada.Strings.Wide_Unbounded.Wide_Text_IO.Get_Line (Name); Found := Users.UserFinder.by_name (Finder, CORBA.To_CORBA_Wide_String (Ada.Strings.Wide_Unbounded.To_Wide_String (Name))); Ada.Wide_Text_IO.Put_Line ("Found" & Integer'Wide_Image (Users.Length (Found))); for J in 1 .. Users.Length (Found) loop Ada.Wide_Text_IO.Put_Line (Integer'Wide_Image (J) & ": '" & CORBA.To_Standard_Wide_String (Users.User.Get_name (Users.User.Convert_Forward.To_Ref (Users.Get_Element (Found, J)))) & "', '" & CORBA.To_Standard_Wide_String (Users.User.Get_surname (Users.User.Convert_Forward.To_Ref (Users.Get_Element (Found, J)))) & "'"); end loop; Ada.Wide_Text_IO.Put ("Selection (0 - ignore): "); Ada.Wide_Text_IO.Flush; Ada.Integer_Wide_Text_IO.Get (Index); Ada.Wide_Text_IO.Skip_Line; if Index in 1 .. Users.Length (Found) then Current := Users.User.Convert_Forward.To_Ref (Users.Get_Element (Found, Index)); end if; end Search_By_Name; begin -- Преобразование параметров командной строки в объектные ссылки. CORBA.ORB.String_To_Object (CORBA.To_CORBA_String (Ada.Command_Line.Argument (1)), Factory); CORBA.ORB.String_To_Object (CORBA.To_CORBA_String (Ada.Command_Line.Argument (2)), Finder); -- Цикл обработки ввода пользователя. loop declare Choice : Natural; begin Ada.Wide_Text_IO.New_Line; Ada.Wide_Text_IO.Put_Line ("Menu:"); Ada.Wide_Text_IO.Put_Line (" 1: Create new user"); Ada.Wide_Text_IO.Put_Line (" 2: Save IOR"); Ada.Wide_Text_IO.Put_Line (" 3: Load IOR"); Ada.Wide_Text_IO.Put_Line (" 4: Show attributes"); Ada.Wide_Text_IO.Put_Line (" 5: Search by name"); Ada.Wide_Text_IO.New_Line; Ada.Wide_Text_IO.Put_Line (" 0: Exit"); Ada.Wide_Text_IO.New_Line; Ada.Wide_Text_IO.Put ("Choice: "); Ada.Wide_Text_IO.Flush; Ada.Integer_Wide_Text_IO.Get (Choice); Ada.Wide_Text_IO.Skip_Line; case Choice is when 0 => exit; when 1 => Create_New_User; when 2 => Save_IOR; when 3 => Load_IOR; when 4 => Show_Attributes; when 5 => Search_By_Name; when others => null; end case; -- Вывод объектной ссылки нового пользователя. if not Users.User.Is_Nil (Current) then Ada.Wide_Text_IO.Put_Line ("Current user's IOR: '" & Ada.Characters.Conversions.To_Wide_String (CORBA.To_Standard_String (CORBA.ORB.Object_To_String (Current))) & "'"); end if; end; end loop; end; end Client; Для настройки клиента необходимо задать ряд параметров в конфигурационном файле PolyORB. В приведённом ниже конфигурационном файле настраивается возможность использования механизма аутентификации GSSUP и необходимые параметры (имя пользователя, пароль, домен): ## Управление безопасностью клиента. [security_manager] own_credentials=user_credentials [user_credentials] authentication_credentials_type=gssup gssup.username=user gssup.password=pass [email protected] ## Управление точками доступа. [access_points] srp=disable soap=disable iiop=enable iiop.ssliop=disable diop=disable uipmc=disable ## Управление поддерживаемыми протоколами. [modules] binding_data.srp=disable binding_data.soap=disable binding_data.iiop=enable binding_data.iiop.ssliop=disable binding_data.diop=disable binding_data.uipmc=disable Необходимо отметить, что механизм аутентификации клиента GSSUP может быть затребован только сервером, но не может требоваться клиентом. Для включения безопасного взаимодействия на сервере требуется сделать почти тоже самое. Первым делом необходимо подключить пакет PolyORB.Setup.Secure_Server к программе сервера. При использовании механизмов безопасного взаимодействия рекомендуется также использовать одну из конфигураций PolyORB, поддерживающую многозадачную обработку запросов. Текст программы сервера будет выглядеть следующим образом: with Ada.Text_IO; with CORBA.Object; with CORBA.ORB; with CORBA.Policy; with PortableServer.IdAssignmentPolicy; with PortableServer.ImplicitActivationPolicy; with PortableServer.LifespanPolicy; with PortableServer.POA.Helper; with PortableServer.POAManager; with PortableServer.RequestProcessingPolicy; with PortableServer.ServantManager; --with PolyORB.Setup.No_Tasking_Server; with PolyORB.Setup.Thread_Pool_Server; -- Конфигурирование PolyORB для работы в режиме многозадачного -- сервера. Это необходимо при для корректной работы механизмов -- защищенного взаимодействия. with PolyORB.Setup.Secure_Server; -- Конфигурирование PolyORB для работы в режиме защищенного сервера. with Activator.Impl; with Globals; with Users.UserFactory.Impl; with Users.UserFinder.Impl; procedure Server is begin -- Инициализация ORB. declare Argv : CORBA.ORB.Arg_List := CORBA.ORB.Command_Line_Arguments; begin CORBA.ORB.Init (CORBA.ORB.To_CORBA_String ("ORB"), Argv); end; declare Root_POA : PortableServer.POA.Local_Ref; begin -- Получение ссылки на корневой объектный адаптер. Root_POA := PortableServer.POA.Helper.To_Local_Ref (CORBA.ORB.Resolve_Initial_References (CORBA.ORB.To_CORBA_String ("RootPOA"))); -- Активация корневого объектного адаптера. PortableServer.POAManager.Activate (PortableServer.POA.Get_The_POAManager (Root_POA)); -- Создание объектного адаптера для объектов пользователей. declare Policies : CORBA.Policy.PolicyList; Lifespan : PortableServer.LifespanPolicy.Ref := PortableServer.POA.Create_Lifespan_Policy (PortableServer.PERSISTENT); Id_Assignment : PortableServer.IdAssignmentPolicy.Ref := PortableServer.POA.Create_Id_Assignment_Policy (PortableServer.USER_ID); Activation : PortableServer.ImplicitActivationPolicy.Ref := PortableServer.POA.Create_Implicit_Activation_Policy (PortableServer.NO_IMPLICIT_ACTIVATION); Processing : PortableServer.RequestProcessingPolicy.Ref := PortableServer.POA.Create_Request_Processing_Policy (PortableServer.USE_SERVANT_MANAGER); begin CORBA.Policy.IDL_SEQUENCE_Policy.Append (Policies, CORBA.Policy.Ref (Lifespan)); CORBA.Policy.IDL_SEQUENCE_Policy.Append (Policies, CORBA.Policy.Ref (Id_Assignment)); CORBA.Policy.IDL_SEQUENCE_Policy.Append (Policies, CORBA.Policy.Ref (Activation)); CORBA.Policy.IDL_SEQUENCE_Policy.Append (Policies, CORBA.Policy.Ref (Processing)); Globals.User_POA := PortableServer.POA.Local_Ref (PortableServer.POA.Create_POA (Root_POA, CORBA.To_CORBA_String ("UserPOA"), PortableServer.POA.Get_The_POAManager (Root_POA), Policies)); -- Создание активатора и его регистрация в объектном адаптере. declare Ref : Activator.Local_Ref; begin Activator.Set (Ref, new Activator.Impl.Object); PortableServer.POA.Set_Servant_Manager (Globals.User_POA, Ref); end; end; -- Создание объекта-фабрики и объектной ссылки на этот объект. declare Ref : CORBA.Object.Ref; begin Ref := PortableServer.POA.Servant_To_Reference (Root_POA, new Users.UserFactory.Impl.Object); -- Вывод на экран сформированной объектной ссылки. Ada.Text_IO.Put_Line ("'" & CORBA.To_Standard_String (CORBA.Object.Object_To_String (Ref)) & "'"); end; -- Создание объекта-поисковика и объектной ссылки на этот объект. declare Ref : CORBA.Object.Ref; begin Ref := PortableServer.POA.Servant_To_Reference (Root_POA, new Users.UserFinder.Impl.Object); -- Вывод на экран сформированной объектной ссылки. Ada.Text_IO.Put_Line ("'" & CORBA.To_Standard_String (CORBA.Object.Object_To_String (Ref)) & "'"); end; end; -- Передача нити главной подпрограммы в ведение ORB. CORBA.ORB.Run; end Server; Настройка механизмов безопасного взаимодействия осуществляется в конфигурационном файле отдельно для каждого объектного адаптера. В нашем случае включается механизм аутентификации клиента GSSUP и требуется обязательное выполнение аутентификации: ## Управление безопасностью сервера. [UserPOA] authentication_mechanism=user_gssup authentication_required=true [user_gssup] mechanism=gssup [email protected] gssup.passwd_file=passwd.pwd ## Фиксация точки доступа. [iiop] polyorb.protocols.iiop.default_addr=127.0.0.1 polyorb.protocols.iiop.default_port=6543 ## Управление точками доступа. [access_points] srp=disable soap=disable iiop=enable iiop.ssliop=disable diop=disable uipmc=disable ## Управление поддерживаемыми протоколами. [modules] binding_data.srp=disable binding_data.soap=disable binding_data.iiop=enable binding_data.iiop.ssliop=disable binding_data.diop=disable binding_data.uipmc=disable И последнее, что осталось сделать — создать файл пользователей и паролей — passwd.pwd: user:pass Собрав модифицированные версии клиента и сервера, запустив их можно быть уверенным, что никто не сможет пробраться на сервер не аутентифицировав себя. В этом несложно убедиться поигравшись с настройками конфигурационных файлов, например, задав неверную пару пользователь/пароль. Особо пытливые читатели могут проанализировать объектные ссылки объектов‐пользователей. Они смогут увидеть, что в профиле появился новый тэговый компонент, описывающий механизмы защищенного взаимодействия и требования по безопасному взаимодействия со стороны сервера. К сожалению на момент написания поддержка детальной расшифровки тэга конфигурации защищенного взаимодействия ещё не была включена в программу po_catref. |