OpenDDS  Snapshot(2023/04/28-20:55)
Typedefs | Functions
OpenDDS::Security::XmlUtils Namespace Reference

Typedefs

typedef DCPS::unique_ptr< xercesc::XercesDOMParser > ParserPtr
 

Functions

std::string to_string (const xercesc::SAXParseException &ex)
 
bool get_parser (ParserPtr &parser, const std::string &filename, const std::string &xml)
 
std::string to_string (const XMLCh *in)
 
bool parse_bool (const XMLCh *in, bool &value)
 
bool parse_time (const XMLCh *in, time_t &value)
 
bool parse_domain_id_set (const xercesc::DOMNode *node, Security::DomainIdSet &domain_id_set)
 
std::string to_string (const xercesc::XMLException &ex)
 
std::string to_string (const xercesc::DOMException &ex)
 
std::string to_string (const xercesc::DOMNode *node)
 
bool parse_bool (const xercesc::DOMNode *node, bool &value)
 
bool parse_time (const xercesc::DOMNode *node, time_t &value)
 
bool is_element (const xercesc::DOMNode *node)
 

Typedef Documentation

◆ ParserPtr

typedef DCPS::unique_ptr<xercesc::XercesDOMParser> OpenDDS::Security::XmlUtils::ParserPtr

Definition at line 32 of file XmlUtils.h.

Function Documentation

◆ get_parser()

OpenDDS_Security_Export bool OpenDDS::Security::XmlUtils::get_parser ( ParserPtr parser,
const std::string &  filename,
const std::string &  xml 
)

Definition at line 71 of file XmlUtils.cpp.

References OpenDDS::DCPS::SecurityDebug::access_error, ACE_ERROR, FACE::TS::Initialize(), LM_ERROR, OpenDDS::DCPS::unique_ptr< T, Deleter >::reset(), OpenDDS::DCPS::security_debug, and to_string().

Referenced by OpenDDS::Security::Governance::load(), and OpenDDS::Security::Permissions::load().

72 {
73  try {
75 
76  } catch (const xercesc::XMLException& ex) {
78  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} get_parser: "
79  "XMLPlatformUtils::Initialize XMLException: %C\n",
80  to_string(ex).c_str()));
81  }
82  parser.reset();
83  return false;
84  }
85 
86  parser.reset(new xercesc::XercesDOMParser());
87 
88  parser->setDoNamespaces(true);
89  parser->setIncludeIgnorableWhitespace(false);
90  parser->setCreateCommentNodes(false);
91 
92  ErrorHandler error_handler;
93  parser->setErrorHandler(&error_handler);
94 
95  xercesc::MemBufInputSource contentbuf(
96  reinterpret_cast<const XMLByte*>(xml.c_str()), xml.size(), filename.c_str());
97 
98  try {
99  parser->parse(contentbuf);
100 
101  } catch (const xercesc::XMLException& ex) {
103  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} get_parser: "
104  "XMLException while parsing \"%C\": %C\n",
105  filename.c_str(), to_string(ex).c_str()));
106  }
107  parser.reset();
108  return false;
109 
110  } catch (const xercesc::DOMException& ex) {
112  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} get_parser: "
113  "DOMException while parsing \"%C\": %C\n",
114  filename.c_str(), to_string(ex).c_str()));
115  }
116  parser.reset();
117  return false;
118 
119  } catch (...) {
121  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} get_parser: "
122  "Unexpected exception while parsing \"%C\"",
123  filename.c_str()));
124  }
125  parser.reset();
126  return false;
127  }
128 
129  if (!parser->getDocument()->getDocumentElement()) {
131  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} get_parser: "
132  "XML document \"%C\" is empty\n",
133  filename.c_str()));
134  }
135  parser.reset();
136  return false;
137  }
138 
139  return true;
140 }
#define ACE_ERROR(X)
bool access_error
Permissions and Governance.
Definition: debug.h:132
void Initialize(const CONFIGURATION_RESOURCE configuration_file, RETURN_CODE_TYPE &return_code)
Definition: FaceTSS.cpp:70
std::string to_string(const XMLCh *in)
Definition: XmlUtils.cpp:142
OpenDDS_Dcps_Export SecurityDebug security_debug
Definition: debug.cpp:32

◆ is_element()

bool OpenDDS::Security::XmlUtils::is_element ( const xercesc::DOMNode *  node)
inline

Definition at line 81 of file XmlUtils.h.

References OPENDDS_END_VERSIONED_NAMESPACE_DECL.

Referenced by parse_domain_id_set().

82 {
83  return node->getNodeType() == xercesc::DOMNode::ELEMENT_NODE;
84 }

◆ parse_bool() [1/2]

bool OpenDDS::Security::XmlUtils::parse_bool ( const xercesc::DOMNode *  node,
bool &  value 
)
inline

Definition at line 64 of file XmlUtils.h.

References parse_bool(), and value.

65 {
66  return parse_bool(node->getTextContent(), value);
67 }
const LogLevel::Value value
Definition: debug.cpp:61
bool parse_bool(const xercesc::DOMNode *node, bool &value)
Definition: XmlUtils.h:64

◆ parse_bool() [2/2]

OpenDDS_Security_Export bool OpenDDS::Security::XmlUtils::parse_bool ( const XMLCh *  in,
bool &  value 
)

Definition at line 150 of file XmlUtils.cpp.

References ACE_OS::strcasecmp(), and to_string().

Referenced by OpenDDS::DCPS::StaticDiscovery::add_domain_participant_secure(), OpenDDS::Security::Governance::Governance(), parse_bool(), OpenDDS::DCPS::StaticDiscovery::parse_publisherqos(), and OpenDDS::DCPS::StaticDiscovery::parse_subscriberqos().

151 {
152  /*
153  * The security spec specifies the XML schema spec's boolean type, but the
154  * XML schema spec doesn't specify that true and false can be capitalized
155  * like the security spec uses.
156  */
157  const std::string s = to_string(in);
158  if (!ACE_OS::strcasecmp(s.c_str(), "true") || s == "1") {
159  value = true;
160  } else if (!ACE_OS::strcasecmp(s.c_str(), "false") || s == "0") {
161  value = false;
162  } else {
163  return false;
164  }
165  return true;
166 }
const LogLevel::Value value
Definition: debug.cpp:61
int strcasecmp(const char *s, const char *t)
std::string to_string(const XMLCh *in)
Definition: XmlUtils.cpp:142

◆ parse_domain_id_set()

OpenDDS_Security_Export bool OpenDDS::Security::XmlUtils::parse_domain_id_set ( const xercesc::DOMNode *  node,
Security::DomainIdSet domain_id_set 
)

Convert a node that's a DomainIdSet in the permissions and governance XML Schema in the security spec to a std::set of domain ids.

Definition at line 445 of file XmlUtils.cpp.

References OpenDDS::DCPS::SecurityDebug::access_error, ACE_ERROR, OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::add(), OpenDDS::Security::domain_id_max, OpenDDS::Security::domain_id_min, OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::empty(), is_element(), LM_ERROR, OPENDDS_END_VERSIONED_NAMESPACE_DECL, OpenDDS::DCPS::security_debug, and to_string().

Referenced by OpenDDS::Security::Governance::load(), OpenDDS::Security::Permissions::load(), and parse_time().

446 {
447  const xercesc::DOMNodeList* const domainIdNodes = node->getChildNodes();
448  for (XMLSize_t did = 0, did_len = domainIdNodes->getLength(); did < did_len; ++did) {
449  const xercesc::DOMNode* const domainIdNode = domainIdNodes->item(did);
450  if (!is_element(domainIdNode)) {
451  continue;
452  }
453  const std::string domainIdNodeName = to_string(domainIdNode->getNodeName());
454  if (domainIdNodeName == "id") {
455  DomainId_t domain_id;
456  if (!parse_domain_id(domainIdNode, domain_id)) {
458  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
459  "Invalid domain ID \"%C\" in id\n",
460  to_string(domainIdNode).c_str()));
461  }
462  return false;
463  }
464  domain_id_set.add(domain_id);
465 
466  } else if (domainIdNodeName == "id_range") {
467  const xercesc::DOMNodeList* const domRangeIdNodes = domainIdNode->getChildNodes();
468  DomainId_t min_value = domain_id_min;
469  bool has_min = false;
470  DomainId_t max_value = domain_id_max;
471  bool has_max = false;
472  const XMLSize_t drid_len = domRangeIdNodes->getLength();
473  for (XMLSize_t drid = 0; drid < drid_len; ++drid) {
474  const xercesc::DOMNode* const domRangeIdNode = domRangeIdNodes->item(drid);
475  if (!is_element(domRangeIdNode)) {
476  continue;
477  }
478  const std::string domRangeIdNodeName = to_string(domRangeIdNode->getNodeName());
479  if ("min" == domRangeIdNodeName && !has_min) {
480  if (!parse_domain_id(domRangeIdNode, min_value)) {
482  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
483  "Invalid domain ID \"%C\" in min_value\n",
484  to_string(domRangeIdNode).c_str()));
485  }
486  return false;
487  }
488  has_min = true;
489 
490  } else if ("max" == domRangeIdNodeName && !has_max) {
491  if (!parse_domain_id(domRangeIdNode, max_value)) {
493  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
494  "Invalid domain ID \"%C\" in max_value\n",
495  to_string(domRangeIdNode).c_str()));
496  }
497  return false;
498  }
499  if (min_value > max_value) {
501  ACE_ERROR((LM_ERROR,"(%P|%t) ERROR: {access_error} parse_domain_id_set: "
502  "Permission XML Domain Range invalid.\n"));
503  }
504  return false;
505  }
506  has_max = true;
507 
508  } else {
510  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
511  "Invalid tag \"%C\" in id_range\n",
512  domRangeIdNodeName.c_str()));
513  }
514  return false;
515  }
516  }
517 
518  domain_id_set.add(min_value, max_value);
519 
520  } else {
522  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
523  "Invalid tag \"%C\" in domain ID set\n",
524  domainIdNodeName.c_str()));
525  }
526  return false;
527  }
528  }
529 
530  if (domain_id_set.empty()) {
532  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_domain_id_set: "
533  "empty domain ID set\n"));
534  }
535  return false;
536  }
537 
538  return true;
539 }
#define ACE_ERROR(X)
const DDS::Security::DomainId_t domain_id_max
Definition: DomainIdSet.h:22
const DDS::Security::DomainId_t domain_id_min
Definition: DomainIdSet.h:21
bool is_element(const xercesc::DOMNode *node)
Definition: XmlUtils.h:81
bool access_error
Permissions and Governance.
Definition: debug.h:132
DOMAINID_TYPE_NATIVE DomainId_t
std::string to_string(const XMLCh *in)
Definition: XmlUtils.cpp:142
OpenDDS_Dcps_Export SecurityDebug security_debug
Definition: debug.cpp:32

◆ parse_time() [1/2]

bool OpenDDS::Security::XmlUtils::parse_time ( const xercesc::DOMNode *  node,
time_t &  value 
)
inline

Definition at line 69 of file XmlUtils.h.

References OpenDDS_Security_Export, parse_domain_id_set(), parse_time(), and value.

70 {
71  return parse_time(node->getTextContent(), value);
72 }
bool parse_time(const xercesc::DOMNode *node, time_t &value)
Definition: XmlUtils.h:69
const LogLevel::Value value
Definition: debug.cpp:61

◆ parse_time() [2/2]

OpenDDS_Security_Export bool OpenDDS::Security::XmlUtils::parse_time ( const XMLCh *  in,
time_t &  value 
)

Definition at line 245 of file XmlUtils.cpp.

References OpenDDS::DCPS::SecurityDebug::access_error, ACE_ERROR, ace_timezone(), OpenDDS::Security::domain_id_max, ENOTSUP, LM_ERROR, OpenDDS::DCPS::security_debug, to_string(), and value.

Referenced by OpenDDS::Security::Permissions::load(), and parse_time().

246 {
247  xercesc::XMLDateTime xdt(in);
248  try {
249  xdt.parseDateTime();
250  } catch (const xercesc::XMLException& ex) {
252  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: "
253  "failed to parse date/time \"%C\": %C\n",
254  to_string(in).c_str(), to_string(ex).c_str()));
255  }
256  return false;
257  }
258 
259 #if XMLDATETIME_HAS_GETEPOCH
260  value = xdt.getEpoch();
261 #else
262  /*
263  * Doesn't seem like older Xerces' actually have a way to get the information
264  * from XMLDateTime, so we have to do it ourselves.
265  *
266  * For this we'll follow https://www.w3.org/TR/xmlschema-2/#dateTime, which
267  * is basically the same as ISO8601.
268  * The exceptions are:
269  * - We won't accept a negative datetime (-0001 is the year 2BCE), since the
270  * standard library might not be able to handle such a far back and we're
271  * certainly not expecting it.
272  * - The Schema spec says that times without timezone info should be
273  * interpreted as "local", but seems it be intentionally vague as what that
274  * means. The DDS Security 1.1 spec explicitly says in 9.4.1.3.2.2 that it
275  * would be UTC. Xerces getEpoch values match up with this in the unit test
276  * for this code, so it's also interpreting them as UTC instead of
277  * something like the local system timezone.
278  * - Since we use time_t we will accept but ignore fractional seconds.
279  * NOTE: The security spec is missing fractional seconds in a format
280  * description in a comment in example XML. This comment has been copied
281  * into many permissions files sitting in OpenDDS.
282  */
283 
284  const std::string str = to_string(in);
285  if (str[0] == '-') {
287  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: "
288  "date/time can't be negative: \"%C\"\n",
289  str.c_str()));
290  }
291  return false;
292  }
293 
294  /*
295  * After this the expected lexical format given by the Schema spec is:
296  * yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? ((('+' | '-') hh ':' mm) | 'Z')?
297  * or alternatively as the Security spec says, except with fractional seconds:
298  * CCYY-MM-DDThh:mm:ss[.fffff...][Z|(+|-)hh:mm]
299  * See unit tests for this code for examples
300  */
301  std::tm dttm;
302  size_t pos = 0;
303 
304  // Year
305  if (!parse_time_field(str, pos, dttm.tm_year, 4)) {
306  return false;
307  }
308  dttm.tm_year -= 1900;
309  if (!parse_time_char(str, pos, "-")) {
310  return false;
311  }
312  // Month
313  if (!parse_time_field(str, pos, dttm.tm_mon)) {
314  return false;
315  }
316  --dttm.tm_mon;
317  if (!parse_time_char(str, pos, "-")) {
318  return false;
319  }
320  // Day
321  if (!parse_time_field(str, pos, dttm.tm_mday)) {
322  return false;
323  }
324  if (!parse_time_char(str, pos, "T")) {
325  return false;
326  }
327  // Hour
328  if (!parse_time_field(str, pos, dttm.tm_hour)) {
329  return false;
330  }
331  if (!parse_time_char(str, pos, ":")) {
332  return false;
333  }
334  // Minutes
335  if (!parse_time_field(str, pos, dttm.tm_min)) {
336  return false;
337  }
338  if (!parse_time_char(str, pos, ":")) {
339  return false;
340  }
341  // Seconds
342  if (!parse_time_field(str, pos, dttm.tm_sec)) {
343  return false;
344  }
345 
346  // Ignore Fractional Seconds
347  if (str[pos] == '.') {
348  ++pos;
349  for (; str[pos] >= '0' && str[pos] <= '9'; ++pos) {
350  }
351  }
352 
353  // Optional Timezone Info
354  time_t timezone_offset = 0;
355  char tz_char = '\0';
356  bool end;
357  if (!parse_time_char_or_end(str, pos, "+-Z", tz_char, end)) {
358  return false;
359  }
360  if (!end && tz_char != 'Z') {
361  int tz_hour;
362  if (!parse_time_field(str, pos, tz_hour)) {
363  return false;
364  }
365 
366  if (!parse_time_char(str, pos, ":")) {
367  return false;
368  }
369 
370  int tz_min;
371  if (!parse_time_field(str, pos, tz_min)) {
372  return false;
373  }
374 
375  /*
376  * We will have to do the reverse of the sign to convert the local time to
377  * UTC. For example 00:00:00-06:00 (12AM CST) is 06:00:00+00:00 (6AM UTC).
378  */
379  const int timezone_offset_sign = tz_char == '+' ? -1 : 1;
380 
381  /*
382  * We could modify the tm struct here to account for the timezone, but then
383  * we'd also have to adjust the hour if the minutes carried over and the
384  * date fields if the hour carried over to another date. Instead we're
385  * going to calculate the number of seconds in the offset and add that to
386  * the time_t value later.
387  */
388  timezone_offset = timezone_offset_sign * (tz_hour * 60 * 60 + tz_min * 60);
389  }
390 
391  std::string leftover;
392  if (parse_time_string(str, pos, leftover)) {
394  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: "
395  "leftover characters in \"%C\": \"%C\"\n",
396  str.c_str(), leftover.c_str()));
397  }
398  return false;
399  }
400 
401  dttm.tm_isdst = 0; // Don't try to do anything with DST
402  value = std::mktime(&dttm);
403  if (value == time_t(-1)) {
405  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: "
406  "failed to convert to time_t \"%C\"\n",
407  to_string(in).c_str()));
408  }
409  return false;
410  }
411 
412  // mktime assumes the tm struct is in the local time, so we need to correct
413  // for that.
414  const time_t local_timezone = static_cast<time_t>(ace_timezone());
415  if (local_timezone == 0 && errno == ENOTSUP) {
417  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: {access_error} parse_time: "
418  "ace_timezone not supported\n"));
419  }
420  return false;
421  }
422  value -= local_timezone;
423 
424  // Adjust for the timezone specified in the string if there was one.
425  value += timezone_offset;
426 #endif // XMLDATETIME_HAS_GETEPOCH
427 
428  return value;
429 }
#define ACE_ERROR(X)
const LogLevel::Value value
Definition: debug.cpp:61
bool access_error
Permissions and Governance.
Definition: debug.h:132
long ace_timezone()
std::string to_string(const XMLCh *in)
Definition: XmlUtils.cpp:142
OpenDDS_Dcps_Export SecurityDebug security_debug
Definition: debug.cpp:32

◆ to_string() [1/5]

OpenDDS_Security_Export std::string OpenDDS::Security::XmlUtils::to_string ( const xercesc::SAXParseException &  ex)

Definition at line 30 of file XmlUtils.cpp.

References OpenDDS::DCPS::SecurityDebug::access_error, OpenDDS::DCPS::SecurityDebug::access_warn, ACE_ERROR, LM_ERROR, OpenDDS::DCPS::security_debug, and OpenDDS::DCPS::to_dds_string().

Referenced by get_parser(), OpenDDS::Security::Governance::Governance(), OpenDDS::Security::Governance::load(), parse_bool(), parse_domain_id_set(), parse_time(), and to_string().

31 {
32  return
33  to_string(ex.getSystemId()) +
34  ":" + DCPS::to_dds_string(ex.getLineNumber()) +
35  ":" + DCPS::to_dds_string(ex.getColumnNumber()) +
36  ": " + to_string(ex.getMessage());
37 }
String to_dds_string(unsigned short to_convert)
std::string to_string(const XMLCh *in)
Definition: XmlUtils.cpp:142

◆ to_string() [2/5]

std::string OpenDDS::Security::XmlUtils::to_string ( const xercesc::XMLException &  ex)
inline

Definition at line 49 of file XmlUtils.h.

References to_string().

50 {
51  return to_string(ex.getMessage());
52 }
std::string to_string(const xercesc::DOMNode *node)
Definition: XmlUtils.h:59

◆ to_string() [3/5]

std::string OpenDDS::Security::XmlUtils::to_string ( const xercesc::DOMException &  ex)
inline

Definition at line 54 of file XmlUtils.h.

References to_string().

55 {
56  return to_string(ex.getMessage());
57 }
std::string to_string(const xercesc::DOMNode *node)
Definition: XmlUtils.h:59

◆ to_string() [4/5]

std::string OpenDDS::Security::XmlUtils::to_string ( const xercesc::DOMNode *  node)
inline

Definition at line 59 of file XmlUtils.h.

References to_string().

60 {
61  return to_string(node->getTextContent());
62 }
std::string to_string(const xercesc::DOMNode *node)
Definition: XmlUtils.h:59

◆ to_string() [5/5]

OpenDDS_Security_Export std::string OpenDDS::Security::XmlUtils::to_string ( const XMLCh *  in)

Definition at line 142 of file XmlUtils.cpp.

143 {
144  char* c = xercesc::XMLString::transcode(in);
145  const std::string s(c);
146  xercesc::XMLString::release(&c);
147  return s;
148 }