OpenDDS  Snapshot(2023/04/28-20:55)
SecurityRegistry.cpp
Go to the documentation of this file.
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 
15 #include <dds/DCPS/Util.h>
17 #include <dds/DCPS/EntityImpl.h>
18 #include <dds/DCPS/ConfigUtils.h>
21 
22 #include <ace/Singleton.h>
23 #include <ace/OS_NS_strings.h>
24 #include <ace/Service_Config.h>
25 
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 
42  : entry_name_(entryName)
43  , auth_name_(DEFAULT_PLUGIN_NAME)
44  , access_ctrl_name_(DEFAULT_PLUGIN_NAME)
45  , crypto_name_(DEFAULT_PLUGIN_NAME)
46 {
47 }
48 
50 {
51  DBG_ENTRY_LVL("SecurityRegistry", "~SecurityRegistry", 6);
52  release();
53 }
54 
56 {
57 }
58 
59 void
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  properties_.push_back(std::make_pair(name, value));
78  //}
79 }
80 
81 
84 {
86 }
87 
88 void
90 {
92 }
93 
95 {
96  DBG_ENTRY_LVL("SecurityRegistry", "SecurityRegistry", 6);
97  lib_directive_map_[DEFAULT_PLUGIN_NAME] = "dynamic OpenDDS_Security Service_Object * OpenDDS_Security:_make_BuiltInPluginLoader()";
98 }
99 
100 void
102 {
103  DBG_ENTRY_LVL("SecurityRegistry", "release", 6);
104  GuardType guard(lock_);
105 
106  for (InstMap::iterator iter = registered_plugins_.begin(); iter != registered_plugins_.end(); ++iter) {
107  iter->second->shutdown();
108  }
109  registered_plugins_.clear();
110  config_map_.clear();
111 }
112 
113 void
115  SecurityPluginInst_rch plugin)
116 {
117  GuardType guard(lock_);
118 
119  if (registered_plugins_.find(plugin_name) != registered_plugins_.end()) {
121  ACE_TEXT("(%P|%t) SecurityRegistry::register_plugin: ")
122  ACE_TEXT("plugin=%C already exists.\n"),
123  plugin_name.c_str()));
124  } else {
125  registered_plugins_.insert(std::make_pair(plugin_name, plugin));
126  }
127 }
128 
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  SecurityConfig_rch existing_config;
135  if (find_config(config_name, existing_config)) {
136  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  ConfigEntryMap::const_iterator iEntry = config_entries_.find(config_name);
143  if (iEntry == config_entries_.end()) {
145  ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
146  ACE_TEXT("config=%C does not exist.\n"),
147  config_name.c_str()));
148  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  const SecurityConfigEntry_rch& entry = iEntry->second;
154  SecurityPluginInst_rch auth_plugin_inst = get_plugin_inst(entry->get_auth_name());
155  if (auth_plugin_inst.is_nil()) {
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  return SecurityConfig_rch();
161  }
162 
163  SecurityPluginInst_rch ac_plugin_inst = get_plugin_inst(entry->get_access_control_name());
164  if (ac_plugin_inst.is_nil()) {
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  return SecurityConfig_rch();
170  }
171 
172  SecurityPluginInst_rch crypto_plugin_inst = get_plugin_inst(entry->get_crypto_name());
173  if (crypto_plugin_inst.is_nil()) {
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  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  auth_plugin_inst->create_authentication(),
188  ac_plugin_inst->create_access_control(),
189  crypto_plugin_inst->create_crypto_key_exchange(),
190  crypto_plugin_inst->create_crypto_key_factory(),
191  crypto_plugin_inst->create_crypto_transform(),
193 #endif
194  entry->get_properties());
195 
196  if (!add_config(config_name, new_config)) {
198  ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
199  ACE_TEXT("Error storing config instance %C\n"),
200  config_name.c_str()));
201  return SecurityConfig_rch();
202  }
203 
204  return new_config;
205 }
206 
209  SecurityPluginInst_rch plugin)
210 {
211 #ifndef OPENDDS_SECURITY
212  ACE_UNUSED_ARG(plugin);
213 #endif
214 
215  SecurityConfig_rch existing_config;
216  if (find_config(config_name, existing_config)) {
217  return existing_config;
218  }
219 
220  SecurityConfig_rch new_config =
221  DCPS::make_rch<SecurityConfig>(config_name,
222 #ifdef OPENDDS_SECURITY
223  plugin->create_authentication(),
224  plugin->create_access_control(),
225  plugin->create_crypto_key_exchange(),
226  plugin->create_crypto_key_factory(),
227  plugin->create_crypto_transform(),
228  plugin->create_utility(),
229 #endif
230  ConfigPropertyList());
231 
232  if (!add_config(config_name, new_config)) {
234  ACE_TEXT("(%P|%t) SecurityRegistry::create_config: ")
235  ACE_TEXT("Error storing config instance %C\n"),
236  config_name.c_str()));
237  return SecurityConfig_rch();
238  }
239 
240  return new_config;
241 }
242 
245 {
246  GuardType guard(lock_);
247  ConfigMap::const_iterator found = config_map_.find(config_name);
248  return found == config_map_.end() ? SecurityConfig_rch() : found->second;
249 }
250 
253 {
254 #if defined(OPENDDS_SECURITY)
255  GuardType guard(lock_);
256  if (!default_config_ && !TheServiceParticipant->get_security()) {
257  Authentication_var a;
258  AccessControl_var b;
259  CryptoKeyExchange_var c;
260  CryptoKeyFactory_var d;
261  CryptoTransform_var e;
262  default_config_ = DCPS::make_rch<SecurityConfig>("NoPlugins", a, b, c, d, e,
264  ConfigPropertyList());
265  }
266 #endif
267  return default_config_;
268 }
269 
270 void
272 {
273  GuardType guard(lock_);
274  default_config_ = config;
275 }
276 
279 {
280 #if defined(OPENDDS_SECURITY)
282  GuardType guard(lock_);
283  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  return builtin_config_;
295 }
296 
297 void
299 {
300  GuardType guard(lock_);
301  builtin_config_ = config;
302 }
303 
304 int
306 {
307  const ACE_Configuration_Section_Key& root = cf.root_section();
308  ACE_TString sect_name;
309 
310  for (int index = 0; cf.enumerate_sections(root, index, sect_name) == 0; ++index) {
312  // found the section, now iterate through subsections...
314  if (cf.open_section(root, sect_name.c_str(), false, sect) != 0) {
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  DCPS::ValueMap vm;
324  if (DCPS::pullValues(cf, sect, vm) > 0) {
325  // There are values inside [transport]
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  DCPS::KeyList keys;
334  if (DCPS::processSections(cf, sect, keys) != 0) {
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  for (DCPS::KeyList::const_iterator it = keys.begin(); it != keys.end(); ++it) {
344  const OPENDDS_STRING& entry_name = it->first;
345  // Duplicate entry check
346  if (config_entries_.find(entry_name) != config_entries_.end()) {
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  DCPS::make_rch<SecurityConfigEntry>(it->first);
358  DCPS::ValueMap values;
359  DCPS::pullValues(cf, it->second, values);
360  for (DCPS::ValueMap::const_iterator val = values.begin(); val != values.end(); ++val) {
361  newEntry->add_property(val->first, val->second);
362  }
363 
364  config_entries_[it->first] = newEntry;
365  }
366  }
367  }
368 
369  return 0;
370 }
371 
372 void
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();
383  }
384 #endif
385 }
386 
387 bool
389 {
390  GuardType guard(lock_);
391 
392  bool found_config = false;
393  ConfigMap::iterator iConfig = config_map_.find(name);
394  if (iConfig != config_map_.end()) {
395  config = iConfig->second;
396  found_config = true;
397  }
398 
399  return found_config;
400 }
401 
402 bool
404 {
405  GuardType guard(lock_);
406 
407  bool added_config = false;
408  ConfigMap::iterator iConfig = config_map_.find(name);
409  if (iConfig == config_map_.end()) {
410  config_map_[name] = config;
411  added_config = true;
412  } else {
413  // Someone else added this already. Use it instead
414  config = iConfig->second;
415  added_config = true;
416  }
417 
418  return added_config;
419 }
420 
422  const OPENDDS_STRING& plugin_name, bool attempt_fix)
423 {
424  GuardType guard(lock_);
425 
426  SecurityPluginInst_rch plugin_inst;
427 
428  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  return plugin_inst;
441 }
442 
444 {
445  GuardType guard(lock_);
446  return config_map_.empty();
447 }
448 
449 } // namespace OpenDDS
450 } // namespace Security
451 
#define ACE_ERROR(X)
const char * c_str(void) const
const LogLevel::Value value
Definition: debug.cpp:61
int load_security_configuration(ACE_Configuration_Heap &cf)
bool add_config(const OPENDDS_STRING &name, SecurityConfig_rch &config)
static int process_directive(const ACE_TCHAR directive[])
static SecurityRegistry * instance()
Return a singleton instance of this class.
bool find_config(const OPENDDS_STRING &name, SecurityConfig_rch &config)
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:72
SecurityConfig_rch default_config() const
int acquire(void)
virtual const ACE_Configuration_Section_Key & root_section(void) const
static const char * AUTHENTICATION_PLUGIN_NAME
static const char * ACCESS_CTRL_PLUGIN_NAME
int release(void)
static TYPE * instance(void)
#define OPENDDS_STRING
SecurityConfig_rch builtin_config() const
void register_plugin(const OPENDDS_STRING &plugin_name, SecurityPluginInst_rch plugin)
static const char * SECURITY_SECTION_NAME
void add_property(const OPENDDS_STRING &name, const OPENDDS_STRING &value)
#define ACE_TEXT_CHAR_TO_TCHAR(STRING)
int strcmp(const char *s, const char *t)
const char *const name
Definition: debug.cpp:60
int find(const PG_Property_Set &decoder, const ACE_CString &key, TYPE &value)
ACE_TEXT("TCP_Factory")
#define DBG_ENTRY_LVL(CNAME, MNAME, DBG_LVL)
Definition: EntryExit.h:68
SecurityConfig_rch get_config(const OPENDDS_STRING &config_name) const
SecurityPluginInst_rch get_plugin_inst(const OPENDDS_STRING &plugin_name, bool attempt_fix=true)
virtual int open_section(const ACE_Configuration_Section_Key &base, const ACE_TCHAR *sub_section, bool create, ACE_Configuration_Section_Key &result)
void load_security_plugin_lib(const OPENDDS_STRING &security_plugin_type)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
int processSections(ACE_Configuration_Heap &cf, const ACE_Configuration_Section_Key &key, KeyList &subsections)
Definition: ConfigUtils.cpp:41
SecurityConfig_rch create_config(const OPENDDS_STRING &config_name)
virtual int enumerate_sections(const ACE_Configuration_Section_Key &key, int index, ACE_TString &name)
#define ACE_ERROR_RETURN(X, Y)
static void close(void)
int pullValues(ACE_Configuration_Heap &cf, const ACE_Configuration_Section_Key &key, ValueMap &values)
Definition: ConfigUtils.cpp:17
DCPS::RcHandle< SecurityConfig > SecurityConfig_rch
#define TheServiceParticipant
LM_ERROR
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
static void close()
Close the singleton instance of this class.