SecurityRegistry.cpp

Go to the documentation of this file.
00001  /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "DCPS/DdsDcps_pch.h"
00009 #include "SecurityRegistry.h"
00010 #include "SecurityConfig.h"
00011 #include "dds/DCPS/transport/framework/EntryExit.h"
00012 #include "dds/DCPS/Util.h"
00013 #include "dds/DCPS/Service_Participant.h"
00014 #include "dds/DCPS/EntityImpl.h"
00015 #include "dds/DCPS/ConfigUtils.h"
00016 #include "dds/DCPS/SafetyProfileStreams.h"
00017 #include "dds/DCPS/DomainParticipantImpl.h"
00018 
00019 #include "ace/Singleton.h"
00020 #include "ace/OS_NS_strings.h"
00021 #include "ace/Service_Config.h"
00022 
00023 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 namespace OpenDDS {
00026 namespace Security {
00027 
00028 const OPENDDS_STRING SecurityRegistry::DEFAULT_CONFIG_NAME("_OPENDDS_DEFAULT_CONFIG");
00029 const OPENDDS_STRING SecurityRegistry::DEFAULT_INST_PREFIX("_OPENDDS_");
00030 const OPENDDS_STRING SecurityRegistry::DEFAULT_PLUGIN_NAME("BuiltIn");
00031 const OPENDDS_STRING SecurityRegistry::SECURITY_SECTION_NAME("security");
00032 const OPENDDS_STRING SecurityRegistry::ACCESS_CTRL_PLUGIN_NAME("access_ctrl_plugin");
00033 const OPENDDS_STRING SecurityRegistry::AUTHENTICATION_PLUGIN_NAME("auth_plugin");
00034 const OPENDDS_STRING SecurityRegistry::CRYPTO_PLUGIN_NAME("crypto_plugin");
00035 
00036 
00037 SecurityRegistry::SecurityConfigEntry::SecurityConfigEntry(const OPENDDS_STRING& entryName)
00038   : entry_name_(entryName)
00039   , auth_name_(DEFAULT_PLUGIN_NAME)
00040   , access_ctrl_name_(DEFAULT_PLUGIN_NAME)
00041   , crypto_name_(DEFAULT_PLUGIN_NAME)
00042 {
00043 }
00044 
00045 SecurityRegistry::~SecurityRegistry()
00046 {
00047   DBG_ENTRY_LVL("SecurityRegistry", "~SecurityRegistry", 6);
00048   release();
00049 }
00050 
00051 SecurityRegistry::SecurityConfigEntry::~SecurityConfigEntry()
00052 {
00053 }
00054 
00055 void
00056 SecurityRegistry::SecurityConfigEntry::add_property(const OPENDDS_STRING& name, const OPENDDS_STRING& value)
00057 {
00058   // Move these up
00059   static const OPENDDS_STRING AUTH_CONFIG_PROP_NAME("auth_config");
00060   static const OPENDDS_STRING ACCESS_CTRL_CONFIG_PROP_NAME("access_ctrl_config");
00061   static const OPENDDS_STRING CRYPTO_CONFIG_PROP_NAME("crypto_config");
00062 
00063   // Config properties can either identity a specific plugin, or
00064   // a configuration property for the security plugins
00065   // TODO - External plugins are not enable yet
00066   //if (0 == name.compare(AUTH_CONFIG_PROP_NAME)) {
00067   //      auth_config_name_ = name;
00068   //} else if (0 == name.compare(ACCESS_CTRL_CONFIG_PROP_NAME)) {
00069   //      access_ctrl_name_ = name;
00070   //} else if (0 == name.compare(CRYPTO_CONFIG_PROP_NAME)) {
00071   //      crypto_name_ = name;
00072   //} else {
00073   properties_.push_back(std::make_pair(name, value));
00074   //}
00075 }
00076 
00077 
00078 SecurityRegistry*
00079 SecurityRegistry::instance()
00080 {
00081   return ACE_Unmanaged_Singleton<SecurityRegistry, ACE_Recursive_Thread_Mutex>::instance();
00082 }
00083 
00084 void
00085 SecurityRegistry::close()
00086 {
00087   ACE_Unmanaged_Singleton<SecurityRegistry, ACE_Recursive_Thread_Mutex>::close();
00088 }
00089 
00090 SecurityRegistry::SecurityRegistry()
00091 {
00092   DBG_ENTRY_LVL("SecurityRegistry", "SecurityRegistry", 6);
00093 
00094   lib_directive_map_[DEFAULT_PLUGIN_NAME] = "dynamic OpenDDS_Security Service_Object * OpenDDS_Security:_make_BuiltInPluginLoader()";
00095 }
00096 
00097 void
00098 SecurityRegistry::release()
00099 {
00100   DBG_ENTRY_LVL("SecurityRegistry", "release", 6);
00101   GuardType guard(lock_);
00102 
00103   for (InstMap::iterator iter = registered_plugins_.begin(); iter != registered_plugins_.end(); ++iter) {
00104     iter->second->shutdown();
00105   }
00106 
00107   registered_plugins_.clear();
00108   config_map_.clear();
00109 }
00110 
00111 void
00112 SecurityRegistry::register_plugin(const OPENDDS_STRING& plugin_name,
00113                                   SecurityPluginInst_rch plugin)
00114 {
00115   GuardType guard(lock_);
00116 
00117   if (registered_plugins_.find(plugin_name) != registered_plugins_.end()) {
00118     guard.release();
00119     ACE_ERROR((LM_ERROR,
00120                ACE_TEXT("(%P|%t) SecurityRegistry::register_plugin: ")
00121                ACE_TEXT("plugin=%C already exists.\n"),
00122                plugin_name.c_str()));
00123   } else {
00124     registered_plugins_.insert(std::make_pair(plugin_name, plugin));
00125   }
00126 }
00127 
00128 SecurityConfig_rch
00129 SecurityRegistry::create_config(const OPENDDS_STRING& config_name)
00130 {
00131   // If the configuration instance already exists, then it can be reused.
00132   // Otherwise create a new one and save it for any later needs
00133   SecurityConfig_rch existing_config;
00134   if (find_config(config_name, existing_config)) {
00135     return existing_config;
00136   }
00137 
00138   // This is making an assumption that the entry map is only written
00139   // to in single-threaded operation, and all acess from that point on
00140   // is read-only
00141   ConfigEntryMap::const_iterator iEntry = config_entries_.find(config_name);
00142   if (iEntry == config_entries_.end()) {
00143     ACE_ERROR((LM_ERROR,
00144                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00145                ACE_TEXT("config=%C does not exist.\n"),
00146                config_name.c_str()));
00147     return SecurityConfig_rch();
00148   }
00149 
00150   // This will load any libraries that need to be loaded, and use the
00151   // resulting plugin instance objects to create the concrete implementations
00152   const SecurityConfigEntry_rch& entry = iEntry->second;
00153   SecurityPluginInst_rch auth_plugin_inst = get_plugin_inst(entry->get_auth_name());
00154   if (auth_plugin_inst.is_nil()) {
00155     ACE_ERROR((LM_ERROR,
00156                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00157                ACE_TEXT("Failed to load authentication plugin %C\n"),
00158                entry->get_auth_name().c_str()));
00159     return SecurityConfig_rch();
00160   }
00161 
00162   SecurityPluginInst_rch ac_plugin_inst = get_plugin_inst(entry->get_access_control_name());
00163   if (ac_plugin_inst.is_nil()) {
00164     ACE_ERROR((LM_ERROR,
00165                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00166                ACE_TEXT("Failed to load access control plugin %C\n"),
00167                entry->get_access_control_name().c_str()));
00168     return SecurityConfig_rch();
00169   }
00170 
00171   SecurityPluginInst_rch crypto_plugin_inst = get_plugin_inst(entry->get_crypto_name());
00172   if (crypto_plugin_inst.is_nil()) {
00173     ACE_ERROR((LM_ERROR,
00174                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00175                ACE_TEXT("Failed to load crypto plugin %C\n"),
00176                entry->get_crypto_name().c_str()));
00177     return SecurityConfig_rch();
00178   }
00179 
00180   // Create the new config and try to add it to the container
00181   // of existing configs.  If this fails for some reason, then
00182   // release the new config and fail
00183   SecurityConfig_rch new_config =
00184     DCPS::make_rch<SecurityConfig>(config_name,
00185                                    auth_plugin_inst->create_authentication(),
00186                                    ac_plugin_inst->create_access_control(),
00187                                    crypto_plugin_inst->create_crypto_key_exchange(),
00188                                    crypto_plugin_inst->create_crypto_key_factory(),
00189                                    crypto_plugin_inst->create_crypto_transform(),
00190                                    entry->get_properties());
00191 
00192   if (!add_config(config_name, new_config)) {
00193     ACE_ERROR((LM_ERROR,
00194                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00195                ACE_TEXT("Error storing config instance %C\n"),
00196                config_name.c_str()));
00197     return SecurityConfig_rch();
00198   }
00199 
00200   return new_config;
00201 }
00202 
00203 SecurityConfig_rch
00204 SecurityRegistry::create_config(const OPENDDS_STRING& config_name,
00205                                 SecurityPluginInst_rch plugin)
00206 {
00207   SecurityConfig_rch existing_config;
00208   if (find_config(config_name, existing_config)) {
00209     return existing_config;
00210   }
00211 
00212   SecurityConfig_rch new_config =
00213     DCPS::make_rch<SecurityConfig>(config_name,
00214                                    plugin->create_authentication(),
00215                                    plugin->create_access_control(),
00216                                    plugin->create_crypto_key_exchange(),
00217                                    plugin->create_crypto_key_factory(),
00218                                    plugin->create_crypto_transform(),
00219                                    ConfigPropertyList());
00220 
00221   if (!add_config(config_name, new_config)) {
00222     ACE_ERROR((LM_ERROR,
00223                ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
00224                ACE_TEXT("Error storing config instance %C\n"),
00225                config_name.c_str()));
00226     return SecurityConfig_rch();
00227   }
00228 
00229   return new_config;
00230 }
00231 
00232 SecurityConfig_rch
00233 SecurityRegistry::get_config(const OPENDDS_STRING& config_name) const
00234 {
00235   GuardType guard(lock_);
00236   ConfigMap::const_iterator found = config_map_.find(config_name);
00237   return found == config_map_.end() ? SecurityConfig_rch() : found->second;
00238 }
00239 
00240 SecurityConfig_rch
00241 SecurityRegistry::default_config() const
00242 {
00243 #if defined(OPENDDS_SECURITY)
00244   GuardType guard(lock_);
00245   if (!default_config_ && !TheServiceParticipant->get_security()) {
00246     Authentication_var a;
00247     AccessControl_var b;
00248     CryptoKeyExchange_var c;
00249     CryptoKeyFactory_var d;
00250     CryptoTransform_var e;
00251     default_config_ = DCPS::make_rch<SecurityConfig>("NoPlugins", a, b, c, d, e,
00252                                                      ConfigPropertyList());
00253   }
00254 #endif
00255   return default_config_;
00256 }
00257 
00258 void
00259 SecurityRegistry::default_config(const SecurityConfig_rch& config)
00260 {
00261   GuardType guard(lock_);
00262   default_config_ = config;
00263 }
00264 
00265 void
00266 SecurityRegistry::bind_config(const OPENDDS_STRING& name,
00267                               DDS::DomainParticipant_ptr domain_participant)
00268 {
00269   bind_config(get_config(name), domain_participant);
00270 }
00271 
00272 void
00273 SecurityRegistry::bind_config(const SecurityConfig_rch& config,
00274                               DDS::DomainParticipant_ptr domain_participant)
00275 {
00276 
00277 #if defined(OPENDDS_SECURITY)
00278   DCPS::DomainParticipantImpl* const dpi =
00279     dynamic_cast<DCPS::DomainParticipantImpl*>(domain_participant);
00280   if (dpi) {
00281     dpi->set_security_config(config);
00282   }
00283 
00284 #else
00285   ACE_UNUSED_ARG(config);
00286   ACE_UNUSED_ARG(domain_participant);
00287 #endif
00288 
00289 }
00290 
00291 int
00292 SecurityRegistry::load_security_configuration(ACE_Configuration_Heap& cf)
00293 {
00294   const ACE_Configuration_Section_Key& root = cf.root_section();
00295   ACE_TString sect_name;
00296 
00297   for (int index = 0; cf.enumerate_sections(root, index, sect_name) == 0; ++index) {
00298     if (ACE_OS::strcmp(sect_name.c_str(), SECURITY_SECTION_NAME.c_str()) == 0) {
00299       // found the section, now iterate through subsections...
00300       ACE_Configuration_Section_Key sect;
00301       if (cf.open_section(root, sect_name.c_str(), 0, sect) != 0) {
00302         ACE_ERROR_RETURN((LM_ERROR,
00303                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
00304                           ACE_TEXT("failed to open section %s\n"),
00305                           sect_name.c_str()),
00306                          -1);
00307       }
00308 
00309       // Ensure there are no properties in this section
00310       DCPS::ValueMap vm;
00311       if (DCPS::pullValues(cf, sect, vm) > 0) {
00312         // There are values inside [transport]
00313         ACE_ERROR_RETURN((LM_ERROR,
00314                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
00315                           ACE_TEXT("[%s] sections must have a section name\n"),
00316                           sect_name.c_str()),
00317                          -1);
00318       }
00319       // Process the subsections of this section
00320       DCPS::KeyList keys;
00321       if (DCPS::processSections(cf, sect, keys) != 0) {
00322         ACE_ERROR_RETURN((LM_ERROR,
00323                           ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
00324                           ACE_TEXT("too many nesting layers in [%s] section.\n"),
00325                           sect_name.c_str()),
00326                          -1);
00327       }
00328 
00329       // Save the properties configured for each security entry
00330       for (DCPS::KeyList::const_iterator it = keys.begin(); it != keys.end(); ++it) {
00331         const OPENDDS_STRING& entry_name = it->first;
00332         // Duplicate entry check
00333         if (config_entries_.find(entry_name) != config_entries_.end()) {
00334           ACE_ERROR_RETURN((LM_ERROR,
00335                             ACE_TEXT("(%P|%t) SecurityRegistry::load_plugin_properties: ")
00336                             ACE_TEXT("duplicate sections named [%s/%C].\n"),
00337                             sect_name.c_str(), entry_name.c_str()),
00338                            -1);
00339         }
00340 
00341         // Copy any existing properties in the entry and create the SecurityConfigEntry, which
00342         // will be stored until actual plugin instances are needed for this configuration
00343         SecurityConfigEntry_rch newEntry =
00344           DCPS::make_rch<SecurityConfigEntry>(it->first);
00345         DCPS::ValueMap values;
00346         DCPS::pullValues(cf, it->second, values);
00347         for (DCPS::ValueMap::const_iterator val = values.begin(); val != values.end(); ++val) {
00348           newEntry->add_property(val->first, val->second);
00349         }
00350 
00351         config_entries_[it->first] = newEntry;
00352       }
00353     }
00354   }
00355 
00356   return 0;
00357 }
00358 
00359 SecurityConfig_rch
00360 SecurityRegistry::fix_empty_default()
00361 {
00362 #if defined(OPENDDS_SECURITY)
00363   if (!default_config()) {
00364     load_security_plugin_lib(DEFAULT_PLUGIN_NAME);
00365   }
00366 #endif
00367 
00368   return default_config();
00369 }
00370 
00371 void
00372 SecurityRegistry::load_security_plugin_lib(const OPENDDS_STRING& security_plugin_type)
00373 {
00374   ACE_UNUSED_ARG(security_plugin_type);
00375 #if !defined(ACE_AS_STATIC_LIBS)
00376   GuardType guard(lock_);
00377   LibDirectiveMap::iterator lib_iter = lib_directive_map_.find(security_plugin_type);
00378   if (lib_iter != lib_directive_map_.end()) {
00379     ACE_TString directive = ACE_TEXT_CHAR_TO_TCHAR(lib_iter->second.c_str());
00380     guard.release();
00381     ACE_Service_Config::process_directive(directive.c_str());
00382   }
00383 #endif
00384 }
00385 
00386 bool
00387 SecurityRegistry::find_config(const OPENDDS_STRING& name, SecurityConfig_rch& config)
00388 {
00389   GuardType guard(lock_);
00390 
00391   bool found_config = false;
00392   ConfigMap::iterator iConfig = config_map_.find(name);
00393   if (iConfig != config_map_.end()) {
00394     config = iConfig->second;
00395     found_config = true;
00396   }
00397 
00398   return found_config;
00399 }
00400 
00401 bool
00402 SecurityRegistry::add_config(const OPENDDS_STRING& name, SecurityConfig_rch& config)
00403 {
00404   GuardType guard(lock_);
00405 
00406   bool added_config = false;
00407   ConfigMap::iterator iConfig = config_map_.find(name);
00408   if (iConfig == config_map_.end()) {
00409     config_map_[name] = config;
00410     added_config = true;
00411   } else {
00412     // Someone else added this already. Use it instead
00413     config = iConfig->second;
00414     added_config = true;
00415   }
00416 
00417   return added_config;
00418 }
00419 
00420 SecurityPluginInst_rch
00421 SecurityRegistry::get_plugin_inst(const OPENDDS_STRING& plugin_name)
00422 {
00423   GuardType guard(lock_);
00424 
00425   SecurityPluginInst_rch plugin_inst;
00426 
00427   if (find(registered_plugins_, plugin_name, plugin_inst) != 0) {
00428 #if !defined(ACE_AS_STATIC_LIBS)
00429     guard.release();
00430     // Not present, try to load library
00431     load_security_plugin_lib(plugin_name);
00432     guard.acquire();
00433 
00434     // Try to find it again
00435     if (find(registered_plugins_, plugin_name, plugin_inst) != 0) {
00436 #endif
00437       ACE_ERROR((LM_ERROR,
00438                  ACE_TEXT("(%P|%t) SecurityRegistry::create_inst: ")
00439                  ACE_TEXT("plugin_type=%C is not registered.\n"),
00440                  plugin_name.c_str()));
00441       return SecurityPluginInst_rch();
00442 #if !defined(ACE_AS_STATIC_LIBS)
00443     }
00444 #endif
00445   }
00446 
00447   return plugin_inst;
00448 }
00449 
00450 
00451 }
00452 }
00453 
00454 OPENDDS_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1