LCOV - code coverage report
Current view: top level - DCPS/security/framework - SecurityRegistry.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 177 1.7 %
Date: 2023-04-30 01:32:43 Functions: 1 23 4.3 %

          Line data    Source code
       1             :  /*
       2             :  *
       3             :  *
       4             :  * Distributed under the OpenDDS License.
       5             :  * See: http://www.opendds.org/license.html
       6             :  */
       7             : 
       8             : #include "DCPS/DdsDcps_pch.h"
       9             : 
      10             : #include "SecurityRegistry.h"
      11             : 
      12             : #include "SecurityConfig.h"
      13             : 
      14             : #include <dds/DCPS/transport/framework/EntryExit.h>
      15             : #include <dds/DCPS/Util.h>
      16             : #include <dds/DCPS/Service_Participant.h>
      17             : #include <dds/DCPS/EntityImpl.h>
      18             : #include <dds/DCPS/ConfigUtils.h>
      19             : #include <dds/DCPS/SafetyProfileStreams.h>
      20             : #include <dds/DCPS/DomainParticipantImpl.h>
      21             : 
      22             : #include <ace/Singleton.h>
      23             : #include <ace/OS_NS_strings.h>
      24             : #include <ace/Service_Config.h>
      25             : 
      26             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      27             : 
      28             : namespace OpenDDS {
      29             : namespace Security {
      30             : 
      31             : const char* SecurityRegistry::DEFAULT_CONFIG_NAME = "_OPENDDS_DEFAULT_CONFIG";
      32             : const char* SecurityRegistry::BUILTIN_CONFIG_NAME = "_OPENDDS_BUILTIN_CONFIG";
      33             : const char* SecurityRegistry::DEFAULT_INST_PREFIX = "_OPENDDS_";
      34             : const char* SecurityRegistry::DEFAULT_PLUGIN_NAME = "BuiltIn";
      35             : const char* SecurityRegistry::SECURITY_SECTION_NAME = "security";
      36             : const char* SecurityRegistry::ACCESS_CTRL_PLUGIN_NAME = "access_ctrl_plugin";
      37             : const char* SecurityRegistry::AUTHENTICATION_PLUGIN_NAME = "auth_plugin";
      38             : const char* SecurityRegistry::CRYPTO_PLUGIN_NAME = "crypto_plugin";
      39             : 
      40             : 
      41           0 : SecurityRegistry::SecurityConfigEntry::SecurityConfigEntry(const OPENDDS_STRING& entryName)
      42           0 :   : entry_name_(entryName)
      43           0 :   , auth_name_(DEFAULT_PLUGIN_NAME)
      44           0 :   , access_ctrl_name_(DEFAULT_PLUGIN_NAME)
      45           0 :   , crypto_name_(DEFAULT_PLUGIN_NAME)
      46             : {
      47           0 : }
      48             : 
      49           0 : SecurityRegistry::~SecurityRegistry()
      50             : {
      51             :   DBG_ENTRY_LVL("SecurityRegistry", "~SecurityRegistry", 6);
      52           0 :   release();
      53           0 : }
      54             : 
      55           0 : SecurityRegistry::SecurityConfigEntry::~SecurityConfigEntry()
      56             : {
      57           0 : }
      58             : 
      59             : void
      60           0 : SecurityRegistry::SecurityConfigEntry::add_property(const OPENDDS_STRING& name, const OPENDDS_STRING& value)
      61             : {
      62             :   // Move these up
      63             :   //static const char* AUTH_CONFIG_PROP_NAME = "auth_config";
      64             :   //static const char* ACCESS_CTRL_CONFIG_PROP_NAME = "access_ctrl_config";
      65             :   //static const char* CRYPTO_CONFIG_PROP_NAME = "crypto_config";
      66             : 
      67             :   // Config properties can either identity a specific plugin, or
      68             :   // a configuration property for the security plugins
      69             :   // TODO - External plugins are not enable yet
      70             :   //if (0 == name.compare(AUTH_CONFIG_PROP_NAME)) {
      71             :   //      auth_config_name_ = name;
      72             :   //} else if (0 == name.compare(ACCESS_CTRL_CONFIG_PROP_NAME)) {
      73             :   //      access_ctrl_name_ = name;
      74             :   //} else if (0 == name.compare(CRYPTO_CONFIG_PROP_NAME)) {
      75             :   //      crypto_name_ = name;
      76             :   //} else {
      77           0 :   properties_.push_back(std::make_pair(name, value));
      78             :   //}
      79           0 : }
      80             : 
      81             : 
      82             : SecurityRegistry*
      83           0 : SecurityRegistry::instance()
      84             : {
      85           0 :   return ACE_Unmanaged_Singleton<SecurityRegistry, ACE_Recursive_Thread_Mutex>::instance();
      86             : }
      87             : 
      88             : void
      89           9 : SecurityRegistry::close()
      90             : {
      91           9 :   ACE_Unmanaged_Singleton<SecurityRegistry, ACE_Recursive_Thread_Mutex>::close();
      92           9 : }
      93             : 
      94           0 : SecurityRegistry::SecurityRegistry()
      95             : {
      96             :   DBG_ENTRY_LVL("SecurityRegistry", "SecurityRegistry", 6);
      97           0 :   lib_directive_map_[DEFAULT_PLUGIN_NAME] = "dynamic OpenDDS_Security Service_Object * OpenDDS_Security:_make_BuiltInPluginLoader()";
      98           0 : }
      99             : 
     100             : void
     101           0 : SecurityRegistry::release()
     102             : {
     103             :   DBG_ENTRY_LVL("SecurityRegistry", "release", 6);
     104           0 :   GuardType guard(lock_);
     105             : 
     106           0 :   for (InstMap::iterator iter = registered_plugins_.begin(); iter != registered_plugins_.end(); ++iter) {
     107           0 :     iter->second->shutdown();
     108             :   }
     109           0 :   registered_plugins_.clear();
     110           0 :   config_map_.clear();
     111           0 : }
     112             : 
     113             : void
     114           0 : SecurityRegistry::register_plugin(const OPENDDS_STRING& plugin_name,
     115             :                                   SecurityPluginInst_rch plugin)
     116             : {
     117           0 :   GuardType guard(lock_);
     118             : 
     119           0 :   if (registered_plugins_.find(plugin_name) != registered_plugins_.end()) {
     120           0 :     ACE_ERROR((LM_ERROR,
     121             :                ACE_TEXT("(%P|%t) SecurityRegistry::register_plugin: ")
     122             :                ACE_TEXT("plugin=%C already exists.\n"),
     123             :                plugin_name.c_str()));
     124             :   } else {
     125           0 :     registered_plugins_.insert(std::make_pair(plugin_name, plugin));
     126             :   }
     127           0 : }
     128             : 
     129             : SecurityConfig_rch
     130           0 : SecurityRegistry::create_config(const OPENDDS_STRING& config_name)
     131             : {
     132             :   // If the configuration instance already exists, then it can be reused.
     133             :   // Otherwise create a new one and save it for any later needs
     134           0 :   SecurityConfig_rch existing_config;
     135           0 :   if (find_config(config_name, existing_config)) {
     136           0 :     return existing_config;
     137             :   }
     138             : 
     139             :   // This is making an assumption that the entry map is only written
     140             :   // to in single-threaded operation, and all acess from that point on
     141             :   // is read-only
     142           0 :   ConfigEntryMap::const_iterator iEntry = config_entries_.find(config_name);
     143           0 :   if (iEntry == config_entries_.end()) {
     144           0 :     ACE_ERROR((LM_ERROR,
     145             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     146             :                ACE_TEXT("config=%C does not exist.\n"),
     147             :                config_name.c_str()));
     148           0 :     return SecurityConfig_rch();
     149             :   }
     150             : 
     151             :   // This will load any libraries that need to be loaded, and use the
     152             :   // resulting plugin instance objects to create the concrete implementations
     153           0 :   const SecurityConfigEntry_rch& entry = iEntry->second;
     154           0 :   SecurityPluginInst_rch auth_plugin_inst = get_plugin_inst(entry->get_auth_name());
     155           0 :   if (auth_plugin_inst.is_nil()) {
     156           0 :     ACE_ERROR((LM_ERROR,
     157             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     158             :                ACE_TEXT("Failed to load authentication plugin %C\n"),
     159             :                entry->get_auth_name().c_str()));
     160           0 :     return SecurityConfig_rch();
     161             :   }
     162             : 
     163           0 :   SecurityPluginInst_rch ac_plugin_inst = get_plugin_inst(entry->get_access_control_name());
     164           0 :   if (ac_plugin_inst.is_nil()) {
     165           0 :     ACE_ERROR((LM_ERROR,
     166             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     167             :                ACE_TEXT("Failed to load access control plugin %C\n"),
     168             :                entry->get_access_control_name().c_str()));
     169           0 :     return SecurityConfig_rch();
     170             :   }
     171             : 
     172           0 :   SecurityPluginInst_rch crypto_plugin_inst = get_plugin_inst(entry->get_crypto_name());
     173           0 :   if (crypto_plugin_inst.is_nil()) {
     174           0 :     ACE_ERROR((LM_ERROR,
     175             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     176             :                ACE_TEXT("Failed to load crypto plugin %C\n"),
     177             :                entry->get_crypto_name().c_str()));
     178           0 :     return SecurityConfig_rch();
     179             :   }
     180             : 
     181             :   // Create the new config and try to add it to the container
     182             :   // of existing configs.  If this fails for some reason, then
     183             :   // release the new config and fail
     184             :   SecurityConfig_rch new_config =
     185             :     DCPS::make_rch<SecurityConfig>(config_name,
     186             : #ifdef OPENDDS_SECURITY
     187           0 :                                    auth_plugin_inst->create_authentication(),
     188           0 :                                    ac_plugin_inst->create_access_control(),
     189           0 :                                    crypto_plugin_inst->create_crypto_key_exchange(),
     190           0 :                                    crypto_plugin_inst->create_crypto_key_factory(),
     191           0 :                                    crypto_plugin_inst->create_crypto_transform(),
     192           0 :                                    DCPS::RcHandle<Utility>(),
     193             : #endif
     194           0 :                                    entry->get_properties());
     195             : 
     196           0 :   if (!add_config(config_name, new_config)) {
     197           0 :     ACE_ERROR((LM_ERROR,
     198             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     199             :                ACE_TEXT("Error storing config instance %C\n"),
     200             :                config_name.c_str()));
     201           0 :     return SecurityConfig_rch();
     202             :   }
     203             : 
     204           0 :   return new_config;
     205           0 : }
     206             : 
     207             : SecurityConfig_rch
     208           0 : SecurityRegistry::create_config(const OPENDDS_STRING& config_name,
     209             :                                 SecurityPluginInst_rch plugin)
     210             : {
     211             : #ifndef OPENDDS_SECURITY
     212             :   ACE_UNUSED_ARG(plugin);
     213             : #endif
     214             : 
     215           0 :   SecurityConfig_rch existing_config;
     216           0 :   if (find_config(config_name, existing_config)) {
     217           0 :     return existing_config;
     218             :   }
     219             : 
     220             :   SecurityConfig_rch new_config =
     221             :     DCPS::make_rch<SecurityConfig>(config_name,
     222             : #ifdef OPENDDS_SECURITY
     223           0 :                                    plugin->create_authentication(),
     224           0 :                                    plugin->create_access_control(),
     225           0 :                                    plugin->create_crypto_key_exchange(),
     226           0 :                                    plugin->create_crypto_key_factory(),
     227           0 :                                    plugin->create_crypto_transform(),
     228           0 :                                    plugin->create_utility(),
     229             : #endif
     230           0 :                                    ConfigPropertyList());
     231             : 
     232           0 :   if (!add_config(config_name, new_config)) {
     233           0 :     ACE_ERROR((LM_ERROR,
     234             :                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
     235             :                ACE_TEXT("Error storing config instance %C\n"),
     236             :                config_name.c_str()));
     237           0 :     return SecurityConfig_rch();
     238             :   }
     239             : 
     240           0 :   return new_config;
     241           0 : }
     242             : 
     243             : SecurityConfig_rch
     244           0 : SecurityRegistry::get_config(const OPENDDS_STRING& config_name) const
     245             : {
     246           0 :   GuardType guard(lock_);
     247           0 :   ConfigMap::const_iterator found = config_map_.find(config_name);
     248           0 :   return found == config_map_.end() ? SecurityConfig_rch() : found->second;
     249           0 : }
     250             : 
     251             : SecurityConfig_rch
     252           0 : SecurityRegistry::default_config() const
     253             : {
     254             : #if defined(OPENDDS_SECURITY)
     255           0 :   GuardType guard(lock_);
     256           0 :   if (!default_config_ && !TheServiceParticipant->get_security()) {
     257           0 :     Authentication_var a;
     258           0 :     AccessControl_var b;
     259           0 :     CryptoKeyExchange_var c;
     260           0 :     CryptoKeyFactory_var d;
     261           0 :     CryptoTransform_var e;
     262           0 :     default_config_ = DCPS::make_rch<SecurityConfig>("NoPlugins", a, b, c, d, e,
     263           0 :                                                      DCPS::RcHandle<Utility>(),
     264           0 :                                                      ConfigPropertyList());
     265           0 :   }
     266             : #endif
     267           0 :   return default_config_;
     268           0 : }
     269             : 
     270             : void
     271           0 : SecurityRegistry::default_config(const SecurityConfig_rch& config)
     272             : {
     273           0 :   GuardType guard(lock_);
     274           0 :   default_config_ = config;
     275           0 : }
     276             : 
     277             : SecurityConfig_rch
     278           0 : SecurityRegistry::builtin_config() const
     279             : {
     280             : #if defined(OPENDDS_SECURITY)
     281           0 :   GuardType g1(default_load_lock_);
     282           0 :   GuardType guard(lock_);
     283           0 :   if (!builtin_config_) {
     284             : #if !defined(ACE_AS_STATIC_LIBS)
     285             :     LibDirectiveMap::const_iterator lib_iter = lib_directive_map_.find(DEFAULT_PLUGIN_NAME);
     286             :     OPENDDS_ASSERT(lib_iter != lib_directive_map_.end());
     287             :     ACE_TString directive = ACE_TEXT_CHAR_TO_TCHAR(lib_iter->second.c_str());
     288             :     guard.release();
     289             :     ACE_Service_Config::process_directive(directive.c_str());
     290             :     guard.acquire();
     291             : #endif
     292             :   }
     293             : #endif
     294           0 :   return builtin_config_;
     295           0 : }
     296             : 
     297             : void
     298           0 : SecurityRegistry::builtin_config(const SecurityConfig_rch& config)
     299             : {
     300           0 :   GuardType guard(lock_);
     301           0 :   builtin_config_ = config;
     302           0 : }
     303             : 
     304             : int
     305           0 : SecurityRegistry::load_security_configuration(ACE_Configuration_Heap& cf)
     306             : {
     307           0 :   const ACE_Configuration_Section_Key& root = cf.root_section();
     308           0 :   ACE_TString sect_name;
     309             : 
     310           0 :   for (int index = 0; cf.enumerate_sections(root, index, sect_name) == 0; ++index) {
     311           0 :     if (ACE_OS::strcmp(sect_name.c_str(), ACE_TEXT_CHAR_TO_TCHAR(SECURITY_SECTION_NAME)) == 0) {
     312             :       // found the section, now iterate through subsections...
     313           0 :       ACE_Configuration_Section_Key sect;
     314           0 :       if (cf.open_section(root, sect_name.c_str(), false, sect) != 0) {
     315           0 :         ACE_ERROR_RETURN((LM_ERROR,
     316             :                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
     317             :                           ACE_TEXT("failed to open section %s\n"),
     318             :                           sect_name.c_str()),
     319             :                          -1);
     320             :       }
     321             : 
     322             :       // Ensure there are no properties in this section
     323           0 :       DCPS::ValueMap vm;
     324           0 :       if (DCPS::pullValues(cf, sect, vm) > 0) {
     325             :         // There are values inside [transport]
     326           0 :         ACE_ERROR_RETURN((LM_ERROR,
     327             :                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
     328             :                           ACE_TEXT("[%s] sections must have a section name\n"),
     329             :                           sect_name.c_str()),
     330             :                          -1);
     331             :       }
     332             :       // Process the subsections of this section
     333           0 :       DCPS::KeyList keys;
     334           0 :       if (DCPS::processSections(cf, sect, keys) != 0) {
     335           0 :         ACE_ERROR_RETURN((LM_ERROR,
     336             :                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
     337             :                           ACE_TEXT("too many nesting layers in [%s] section.\n"),
     338             :                           sect_name.c_str()),
     339             :                          -1);
     340             :       }
     341             : 
     342             :       // Save the properties configured for each security entry
     343           0 :       for (DCPS::KeyList::const_iterator it = keys.begin(); it != keys.end(); ++it) {
     344           0 :         const OPENDDS_STRING& entry_name = it->first;
     345             :         // Duplicate entry check
     346           0 :         if (config_entries_.find(entry_name) != config_entries_.end()) {
     347           0 :           ACE_ERROR_RETURN((LM_ERROR,
     348             :                             ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
     349             :                             ACE_TEXT("duplicate sections named [%s/%C].\n"),
     350             :                             sect_name.c_str(), entry_name.c_str()),
     351             :                            -1);
     352             :         }
     353             : 
     354             :         // Copy any existing properties in the entry and create the SecurityConfigEntry, which
     355             :         // will be stored until actual plugin instances are needed for this configuration
     356             :         SecurityConfigEntry_rch newEntry =
     357           0 :           DCPS::make_rch<SecurityConfigEntry>(it->first);
     358           0 :         DCPS::ValueMap values;
     359           0 :         DCPS::pullValues(cf, it->second, values);
     360           0 :         for (DCPS::ValueMap::const_iterator val = values.begin(); val != values.end(); ++val) {
     361           0 :           newEntry->add_property(val->first, val->second);
     362             :         }
     363             : 
     364           0 :         config_entries_[it->first] = newEntry;
     365           0 :       }
     366           0 :     }
     367             :   }
     368             : 
     369           0 :   return 0;
     370           0 : }
     371             : 
     372             : void
     373           0 : SecurityRegistry::load_security_plugin_lib(const OPENDDS_STRING& security_plugin_type)
     374             : {
     375             :   ACE_UNUSED_ARG(security_plugin_type);
     376             : #if !defined(ACE_AS_STATIC_LIBS)
     377             :   GuardType guard(lock_);
     378             :   LibDirectiveMap::iterator lib_iter = lib_directive_map_.find(security_plugin_type);
     379             :   if (lib_iter != lib_directive_map_.end()) {
     380             :     ACE_TString directive = ACE_TEXT_CHAR_TO_TCHAR(lib_iter->second.c_str());
     381             :     guard.release();
     382             :     ACE_Service_Config::process_directive(directive.c_str());
     383             :   }
     384             : #endif
     385           0 : }
     386             : 
     387             : bool
     388           0 : SecurityRegistry::find_config(const OPENDDS_STRING& name, SecurityConfig_rch& config)
     389             : {
     390           0 :   GuardType guard(lock_);
     391             : 
     392           0 :   bool found_config = false;
     393           0 :   ConfigMap::iterator iConfig = config_map_.find(name);
     394           0 :   if (iConfig != config_map_.end()) {
     395           0 :     config = iConfig->second;
     396           0 :     found_config = true;
     397             :   }
     398             : 
     399           0 :   return found_config;
     400           0 : }
     401             : 
     402             : bool
     403           0 : SecurityRegistry::add_config(const OPENDDS_STRING& name, SecurityConfig_rch& config)
     404             : {
     405           0 :   GuardType guard(lock_);
     406             : 
     407           0 :   bool added_config = false;
     408           0 :   ConfigMap::iterator iConfig = config_map_.find(name);
     409           0 :   if (iConfig == config_map_.end()) {
     410           0 :     config_map_[name] = config;
     411           0 :     added_config = true;
     412             :   } else {
     413             :     // Someone else added this already. Use it instead
     414           0 :     config = iConfig->second;
     415           0 :     added_config = true;
     416             :   }
     417             : 
     418           0 :   return added_config;
     419           0 : }
     420             : 
     421           0 : SecurityPluginInst_rch SecurityRegistry::get_plugin_inst(
     422             :   const OPENDDS_STRING& plugin_name, bool attempt_fix)
     423             : {
     424           0 :   GuardType guard(lock_);
     425             : 
     426           0 :   SecurityPluginInst_rch plugin_inst;
     427             : 
     428           0 :   if (find(registered_plugins_, plugin_name, plugin_inst) != 0 && attempt_fix) {
     429             : #if !defined(ACE_AS_STATIC_LIBS)
     430             :     guard.release();
     431             :     // Not present, try to load library
     432             :     load_security_plugin_lib(plugin_name);
     433             :     guard.acquire();
     434             : 
     435             :     // Try to find it again
     436             :     find(registered_plugins_, plugin_name, plugin_inst);
     437             : #endif
     438             :   }
     439             : 
     440           0 :   return plugin_inst;
     441           0 : }
     442             : 
     443           0 : bool SecurityRegistry::has_no_configs() const
     444             : {
     445           0 :   GuardType guard(lock_);
     446           0 :   return config_map_.empty();
     447           0 : }
     448             : 
     449             : } // namespace OpenDDS
     450             : } // namespace Security
     451             : 
     452             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16