Security SDK ============ Introduction ------------ *RTI Security Plugins* introduce a robust set of security capabilities, including authentication, encryption, access control and logging. Secure multicast support enables efficient and scalable distribution of data to many subscribers. Performance is also optimized by fine-grained control over the level of security applied to each data flow, such as whether encryption or just data integrity is required. The |rti_me_security_sdk| includes a set of builtin plugins that implement the Service Plugin Interface defined by the DDS Security specification. *RTI Security Plugins* is a separate package, available from the RTI Support Portal, https://support.rti.com/. It is also possible to implement new custom plugins by using the *Security Plugins SDK* bundle (for more information, please contact support@rti.com). See the |rti_security_plugins_rnotes_verbose| and |rti_security_plugins_gsg_verbose| on the |rti_community_documentation|_ page. Installation ------------ Please refer to the main :doc:`../installation/index` section for how to install the |rti_me_security_sdk|. Examples -------- For descriptions and examples of the security configuration in this release, please consult the ``HelloWorld_dpde_secure`` examples under the ``example/[unix, windows]/[C, CPP]`` directory. |rti_me_security_sdk| supports both the C and C++ programming languages. To use the |rti_me_security_sdk|, you will need to create private keys, identity certificates, governance and permission files, as well as signed versions for use in secure authenticated, authorized, and/or encrypted communications. Enabling RTI Security Plugins ----------------------------- To enable the *RTI Security Plugins*, the name of a "plugin suite" (i.e. the collection of security plugins defined by DDS Security) must be specified in a DomainParticipant's QoS. Plugin factories for this suite must also be registered with the RT_Registry before the DomainParticipant is created. When using |rti_me|'s C API, this can be achieved with the following code:: RTI_BOOL result = RTI_FALSE; struct DDS_DomainParticipantQos dp_qos = DDS_DomainParticipantQos_INITIALIZER; struct SECCORE_SecurePluginFactoryProperty sec_plugin_prop = SECCORE_SecurePluginFactoryProperty_INITIALIZER; DDS_DomainParticipantFactory *factory = DDS_DomainParticipantFactory_get_instance(); RT_Registry_T *registry = DDS_DomainParticipantFactory_get_registry(factory); /* Register factories for built-in security plugins, using default * properties and default name */ if (!SECCORE_SecurePluginFactory_register( registry,SECCORE_DEFAULT_SUITE_NAME,&sec_plugin_prop)) { printf("failed to register security plugins\n"); goto done; } /* In order to enable security, the name used to register the suite of * plugins must be set in DomainParticipantQos */ if (!RT_ComponentFactoryId_set_name( &dp_qos->trust.suite, SECCORE_DEFAULT_SUITE_NAME)) { printf("failed to set component id\n"); goto done; } result = RTI_TRUE; done: return result; For users of |rti_me|'s C++ API, the suite can be registered using the following code:: RTI_BOOL result = RTI_FALSE; DDS_DomainParticipantQos dp_qos; SECCORE_SecurePluginFactoryProperty sec_plugin_prop; DDSDomainParticipantFactory *factory = DDSDomainParticipantFactory::get_instance(); RTRegistry_T *registry = factory->get_registry(); /* Register factories for built-in security plugins, using default * properties and default name */ if (!SECCORE_SecurePluginFactory::register_suite( registry,SECCORE_DEFAULT_SUITE_NAME,sec_plugin_prop)) { printf("failed to register security plugins\n"); goto done; } /* In order to enable security, the name used to register the suite of * plugins must be set in DomainParticipantQos */ if (!dp_qos.trust.suite.set_name(SECCORE_DEFAULT_SUITE_NAME)) { printf("failed to set component id\n"); goto done; } result = RTI_TRUE; done: return result; Additional properties can be controlled using (key,value) pairs in a DomainParticipant's DDS_PropertyQosPolicy. The configuration keys (and their corresponding valid values) supported by each security plugin are listed in the tables below: - :numref:`TableSecPrefixProperty`, :ref:`TableSecPrefixProperty` - :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication` - :numref:`TableSecPropsAccess`, :ref:`TableSecPropsAccess` - :numref:`TableSecPropsCrypt`, :ref:`TableSecPropsCrypt` - :numref:`TableSecPropsLog`, :ref:`TableSecPropsLog` In |rti_me|, you must set the security-related participant properties before you create a participant. You cannot create a participant without security and then call ``DomainParticipant::set_qos()`` with security properties, even if the participant has not yet been enabled. .. list-table:: DDS Security Prefix Property :name: TableSecPrefixProperty :widths: 30 70 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY - Optional. The prefix string for security properties. For example: ``com.rti.serv.secure``. If set, you will use this string as the prefix, followed by a “dot”, to some of the property names. Note: This is different than the *Connext DDS Pro* prefix property which also allows you to load the plugin. This property only allows you to use the prefix string. Default : NULL .. list-table:: DDS Security Properties for Configuring Authentication :name: TableSecPropsAuthentication :widths: 30 70 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - DDS_SECURITY_IDENTITY_CA_PROPERTY - Required. The Identity Certificate Authority for signing authentication certificate files. See :numref:`section-DDS_SECURITY_IDENTITY_CA_PROPERTY`. * - DDS_SECURITY_PRIVATE_KEY_PROPERTY - Required. The private key associated with the first certificate that appears in the identity_certificate. See :numref:`section-DDS_SECURITY_PRIVATE_KEY_PROPERTY`. * - DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY - Required. An Identity Certificate, required for secure communication. See :numref:`section-DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY`. * - DDS_SECURITY_PASSWORD_PROPERTY - Only required if private_key is encrypted. The password used to decrypt the private_key. See :numref:`section-DDS_SECURITY_PASSWORD_PROPERTY`. * - RTI_SECURITY_SHARED_SECRET_ALGORITHM_PROPERTY NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The algorithm used to establish a shared secret during authentication. See :numref:`section-RTI_SECURITY_SHARED_SECRET_ALGORITHM_PROPERTY`. * - RTI_SECURITY_CRL_FILE_PROPERTY NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The Certificate Revocation List (CRL) that keeps track of untrusted X.509 certificates. See :numref:`section-RTI_SECURITY_CRL_FILE_PROPERTY`. .. list-table:: DDS Security Properties for Configuring Access Control :name: TableSecPropsAccess :widths: 30 70 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - DDS_SECURITY_PERMISSIONS_CA_PROPERTY - Required. Permissions Certificate Authority for signing access control governance and permissions XML files, and verifying the signatures of those files. See :numref:`section-DDS_SECURITY_PERMISSIONS_CA_PROPERTY`. * - DDS_SECURITY_GOVERNANCE_PROPERTY - Required. Signed document that specifies the level of security required per domain and per topic. See :numref:`section-DDS_SECURITY_GOVERNANCE_PROPERTY`. .. list-table:: RTI Properties for Configuring Cryptography :name: TableSecPropsCrypt :widths: 30 70 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - RTI_SECURITY_ENCRYPTION_ALGORITHM_PROPERTY NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The algorithm used for encrypting and decrypting data and metadata. The options are ``aes-128-gcm``, ``aes-192-gcm``, and ``aes-256-gcm``. (“gcm” is Galois/Counter Mode (GCM) authenticated encryption). The number indicates the number of bits in the key. Participants are not required to set this property to the same value in order to communicate with each other. In the Domain Governance document, a "protection kind" set to ENCRYPT will use GCM, and a "protection kind" set to SIGN will use the GMAC variant of this algorithm. Default: ``aes-128-gcm`` * - RTI_SECURITY_MAX_RECEIVER_SPECIFIC_MACS_PROPERTY NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The maximum number of receiver-specific Message Authentication Codes (MACs) that are appended to an encoded result. For example, if this value is 32 and the Participant is configured to protect both RTPS messages and submessages with origin authentication, there could be 32 receiver-specific MACs in the result of encode_datawriter_submessage, and there could be another 32 receiver-specific MACs in the result of encode_rtps_message. If there are more than 32 receivers, the receivers will be assigned one of the 32 possible MACs in a round-robin fashion. Note that in the case of encode_datawriter_submessage, all the readers belonging to the same participant will always be assigned the same receiver-specific MAC. Setting this value to 0 will completely disable receiver-specific MACs. Default: 0. Range: [0, 3275], excluding 1 * - RTI_SECURITY_MAX_BLOCKS_PER_SESSION_PROPERTY NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The number of message blocks that can be encrypted with the same key material. Whenever the number of blocks exceeds this value, new key material is computed. The block size depends on the encryption algorithm. You can specify this value in decimal, octal, or hexadecimal. This value is an unsigned 64-bit integer. Default: 0xffffffffffffffff .. list-table:: RTI Properties for Configuring Logging :name: TableSecPropsLog :widths: 30 70 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - DDS_PARTICIPANT_TRUST_PLUGINS_LOGGING_DISTRIBUTE_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. This boolean value controls whether security-related log messages should be distributed over a DDS DataWriter. If true, then the Logging Plugin will create a Publisher and DataWriter within the same DomainParticipant that is setting this property. There is no option to use a separate DomainParticipant or to share a DataWriter among multiple DomainParticipants. To subscribe to the log messages, run *rtiddsgen* on ``resource/idl/builtin_logging_type.idl``. Create a DataReader of type ``DDSSecurity::BuiltinLoggingType`` and topic ``DDS:Security:LogTopic``. The DataReader must be allowed to subscribe to this topic according to its DomainParticipant’s permissions file. Default: FALSE * - DDS_PARTICIPANT_TRUST_PLUGINS_LOGGING_LOG_LEVEL_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The logging verbosity level. All log messages at and below the log_level setting will be logged. Possible values: * 0: emergency * 1: alert * 2: critical * 3: error (default) * 4: warning * 5: notice * 6: informational * 7: debug * - DDS_PARTICIPANT_TRUST_PLUGINS_LOGGING_LOG_FILE_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. The file that log messages are printed to. Default: NULL * - DDS_TRUST_PLUGINS_LOGGING_MAX_REMOTE_READERS_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. Maximum remote readers the logging writer can write to. Default: 16 * - DDS_TRUST_PLUGINS_LOGGING_MAX_ROUTES_PER_READER_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. Logging writer resource-limit, which limits the number of routes that can be saved per Reader. Default: 4 * - DDS_TRUST_PLUGINS_LOGGING_WRITER_DEPTH_PROPERTY_NAME NOTE: Prefix with value of DDS_PARTICIPANT_TRUST_PREFIX_PROPERTY if set. - Optional. History depth (in samples) of the logging DataWriter. Integer. Default: 64 .. _section-DDS_SECURITY_IDENTITY_CA_PROPERTY: DDS_SECURITY_IDENTITY_CA_PROPERTY ................................. DDS_SECURITY_IDENTITY_CA_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. This property's value specifies an Identity Certificate Authority document that will be used for signing authentication certificate files. Participants that want to securely communicate with each other must use the same Identity Certificate Authority. You will use OpenSSL and an ``openssl.cnf`` file to create a file in PEM format named ``cacert*.pem``. An example ``openssl.cnf`` file is here: ``rti_workspace/version/examples/dds_security/cert``. You will need to modify this file to match your certificate folder structure and Identity Certificate Authority desired configuration. Example OpenSSL commands are shown below. RSA: .. code-block:: bash % openssl genrsa -out cakey.pem 2048 % openssl req -new -key cakey.pem -out ca.csr -config openssl.cnf % openssl x509 -req -days 3650 -in ca.csr -signkey cakey.pem \ -out cacert.pem DSA: .. code-block:: bash % openssl dsaparam 2048 > dsaparam % openssl gendsa -out cakeydsa.pem dsaparam % openssl req -new -key cakeydsa.pem -out dsaca.csr \ -config openssldsa.cnf % openssl x509 -req -days 3650 -in dsaca.csr -signkey cakeydsa.pem \ -out cacertdsa.pem ECDSA: .. code-block:: bash % openssl ecparam -name prime256v1 > ecdsaparam % openssl req -nodes -x509 -days 3650 -newkey ec:ecdsaparam \ -keyout cakeyECdsa.pem -out cacertECdsa.pem -config opensslECdsa.cnf .. note:: When running the above commands for ECDSA, you may run into these OpenSSL warnings:: WARNING: can't open config file: [default openssl built-inpath]/openssl.cnf unable to write 'random state' To resolve the first warning, set the environmental variable OPENSSL_CONF with the path to the ``openssl.cnf`` file you are using. To resolve the second warning, set the environmental variable RANDFILE with the path to a writable file. You may specify the value as either a file name or the document contents. The document should be in PEM format. - If setting the property value to a file name: The property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the ``cacert*.pem`` file that appears after the ``-out`` parameter in the above commands. - If setting the property value to the contents of the document: The property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example: .. code-block:: bash "data:,-----BEGIN CERTIFICATE-----\nabcdef\n-----END CERTIFICATE-----" Note that the two ``\n`` characters are required. .. _section-DDS_SECURITY_PRIVATE_KEY_PROPERTY: DDS_SECURITY_PRIVATE_KEY_PROPERTY ................................. DDS_SECURITY_PRIVATE_KEY_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. Its value is a private key associated with the first certificate that appears in the identity_certificate. The default value is NULL. After generating the ca_file, ``cacert*.pem`` (described in :numref:`section-DDS_SECURITY_IDENTITY_CA_PROPERTY`), use OpenSSL to generate a ``peer1key*.pem`` file using commands such as the following. - RSA: .. code-block:: bash % openssl genrsa -out peer1key.pem 2048 - DSA: .. code-block:: bash % openssl dsaparam 2048 > dsaparam % openssl gendsa -out peer1keydsa.pem dsaparam - ECDSA: .. code-block:: bash % openssl ecparam -name prime256v1 > ecdsaparam1 % openssl req -nodes -new -newkey ec:ecdsaparam1 -config example1ECdsa.cnf \ -keyout peer1keyECdsa.pem -out peer1reqECdsa.pem Notice that for ECDSA, OpenSSL also generates ``peer1reqECdsa.pem``. That file will be used later to generate the certificate file for :ref:`section-DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY`. The document should be in PEM format. You may specify either the file name or the document contents. - If setting the property value to a file name: The property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the file ``peer1key*.pem`` that appears after the ``-out`` parameters in the above commands. - If setting the property value to the contents of the document: The property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example:: "data:,-----BEGIN PRIVATE KEY-----\nabcdef\n-----END PRIVATE KEY-----" Note that the two ``\n`` characters are required. .. _section-DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY: DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY .......................................... DDS_SECURITY_IDENTITY_CERTIFICATE_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. Its value is an Identity Certificate, required for secure communication. Before generating the certificate file for this property, first generate the ca_file (see :numref:`section-DDS_SECURITY_IDENTITY_CA_PROPERTY`) and the private_key_file (see :numref:`section-DDS_SECURITY_PRIVATE_KEY_PROPERTY`). Next, create a serial file whose contents are 01 and a blank ``index.txt`` file. The names of these files will depend on the contents of the ``openssl*.cnf`` file. Then use OpenSSL to generate the certificate file using commands such as those seen below. Example ``.cnf`` files are here: ``rti_workspace/version/examples/dds_security/cert``. Note: You will need to modify this file to match your certificate folder structure and Identity Certificate desired configuration: - RSA: .. code-block:: bash % openssl req -config example1.cnf -new -key peer1key.pem \ -out user.csr % openssl ca -config openssl.cnf -days 365 -in user.csr \ -out peer1.pem - DSA: .. code-block:: bash % openssl req -config example1dsa.cnf -new -key peer1keydsa.pem \ -out dsauser.csr % openssl ca -config openssldsa.cnf -days 365 \ -in dsauser.csr -out peer1dsa.pem ECDSA: Generate ``peer1reqECdsa.pem`` using the instructions for private_key_file (see :numref:`section-DDS_SECURITY_PRIVATE_KEY_PROPERTY`). .. code-block:: bash % openssl ca -batch -create_serial -config opensslECdsa.cnf \ -days 365 -in peer1reqECdsa.pem -out peer1ECdsa.pem Notes: - ``openssl((EC)dsa).cnf`` must have the same countryName, stateOrProvinceName, and localityName as the example ``.cnf`` files. - Example ``.cnf`` files for different participants must have different commonNames. The document should be in PEM format. You may specify either the file name or the document contents. - If setting the property value to a file name: The property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the file ``peer1*.pem`` that appears after the ``-out`` parameters in the above commands. - If setting the property value to the contents of the document: The property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example:: "data:,-----BEGIN CERTIFICATE-----\nabcdef\n-----END CERTIFICATE-----" Note that the two “\n” characters are required. You may put a chain of certificates in the Identity Certificate by concatenating individual certificates and specifying the concatenated result as a single file or string. See Section 4.1, Identity Certificate Chaining, in the *Security Plugins User's Manual* for 6.0.1 (available |rti_security_plugins_um_id_cert_chaining|_ if you have Internet access). Default: NULL .. _section-DDS_SECURITY_PASSWORD_PROPERTY: DDS_SECURITY_PASSWORD_PROPERTY .............................. This property is only required if private_key is encrypted. Its value specifies the password used to decrypt the private_key (see :numref:`section-DDS_SECURITY_PRIVATE_KEY_PROPERTY`). This property appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. The value is interpreted as the Base64 encoding of the symmetric key that will be used to decrypt the private_key. For example, suppose the private_key was encrypted using this command: .. code-block:: bash % openssl req -new -newkey ec:ecdsaparam2 \ -config example2ECdsa.cnf -keyout peer2keyECdsa.pem \ -passout pass:MyPassword -out peer2reqECdsa.pem Then you can obtain the Base64 encoding of MyPassword with commands such as: .. code-block:: bash % echo MyPassword > foo % openssl base64 -e -in foo TXlQYXNzd29yZAo= For the above example, the value of the password property should be "TXlQYXNzd29yZAo=". If the private_key was not encrypted, the password must be NULL. Default: NULL .. _section-RTI_SECURITY_SHARED_SECRET_ALGORITHM_PROPERTY: RTI_SECURITY_SHARED_SECRET_ALGORITHM_PROPERTY ............................................. This is an optional property. Its value sets the algorithm used to establish a shared secret during authentication. The options are ``dh`` and ``ecdh`` for (Elliptic Curve) Diffie-Hellman. This property appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. If two participants discover each other and they specify different values for this algorithm, the algorithm that will be used is the one that belongs to the participant with the lower-valued participant_key. Note: ``ecdh`` does not work with static OpenSSL libraries when using Certicom® Security Builder® engine. Default: ``ecdh`` .. _section-RTI_SECURITY_CRL_FILE_PROPERTY: RTI_SECURITY_CRL_FILE_PROPERTY .............................. This is an optional property. This Certificate Revocation List (CRL) keeps track of untrusted X.509 certificates. This property appears in :numref:`TableSecPropsAuthentication`, :ref:`TableSecPropsAuthentication`. Use OpenSSL to generate this file using commands such as those seen below. An example ``opensslECdsa.cnf`` file is here: ``rti_workspace/version/examples/dds_security/cert``. You will need to modify this file to match your certificate folder structure and Certificate Revocation List desired configuration. .. code-block:: bash % touch indexECdsa.txt % echo 01 > crlnumberECdsa % openssl ca -config opensslECdsa.cnf -batch \ -revoke peerRevokedECdsa.pem % openssl ca -config opensslECdsa.cnf -batch -gencrl \ -out democaECdsa.crl In this example: - ``crlnumberECdsa`` is the database of revoked certificates. This file should match the ``crlnumber`` value in ``opensslECdsa.cnf``. - ``peerRevokedECdsa.pem`` is the certificate_file of a revoked DomainParticipant. - ``democaECdsa.crl`` should be the value of the crl_file property. - If crl_file is set to NULL, no CRL is checked and all valid certificates will be considered trusted. - If crl_file is set to an invalid CRL file, DomainParticipant creation will fail. - If crl_file is set to a valid CRL file, the CRL will be checked upon DomainParticipant creation and upon discovering other DomainParticipants. Creating a DomainParticipant with a revoked certificate will fail. If ParticipantA uses a certificate that does not appear in ParticipantA’s CRL, but does appear in ParticipantB’s CRL, then ParticipantB will reject and ignore ParticipantA. Changes in the CRL will not be enforced until the DomainParticipant using the CRL is deleted and recreated. Default: NULL .. _section-DDS_SECURITY_PERMISSIONS_CA_PROPERTY: DDS_SECURITY_PERMISSIONS_CA_PROPERTY .................................... DDS_SECURITY_PERMISSIONS_CA_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAccess`, :ref:`TableSecPropsAccess`. This Permissions Certificate Authority is used for signing access control governance and permissions XML files, and verifying the signatures of those files. The Permissions Certificate Authority file may or may not be the same as the Identity Certificate Authority file, but both files are generated in the same way. See :numref:`section-DDS_SECURITY_IDENTITY_CA_PROPERTY` for the steps to generate this file. Two participants that want to securely communicate with each other must use the same Permissions Certificate Authority. The document should be in PEM format. You may specify either the file name or the document contents. - If specifying the file name, the property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the file. - If specifying the contents of the document, the property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example:: ``data:,-----BEGIN CERTIFICATE-----\nabcdef\n-----END CERTIFICATE-----`` Note that the two “\n” characters are required. Default: NULL .. _section-DDS_SECURITY_GOVERNANCE_PROPERTY: DDS_SECURITY_GOVERNANCE_PROPERTY ................................ DDS_SECURITY_GOVERNANCE_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAccess`, :ref:`TableSecPropsAccess`. The Governance property configures the signed document that specifies the level of security required per domain and per topic. To sign an XML document with a Permissions Certificate Authority, run the following OpenSSL command (enter this all on one line):: openssl smime -sign -in Governance.xml -text -out signed_Governance.p7s -signer cacert.pem -inkey cakey.pem Then set this property's value to ``signed_Governance.p7s``. You may specify either the file name or the document contents. - If specifying the file name, the property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the file. - If specifying the contents of the document, the property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example:: "data:,MIME-Version: 1.0\nContent-Type:...boundary=\”---7236\”\n\n" Note that for signed XML files, all whitespace characters (‘ ‘, ‘\r’, ‘\n’) are significant, and all quotes must be escaped with a backslash. The safest way to get the correct property value is to call the ``fread()`` function on the file and use the resulting buffer as the property value. Default: NULL .. _section-DDS_SECURITY_PERMISSIONS_PROPERTY: DDS_SECURITY_PERMISSIONS_PROPERTY ................................. DDS_SECURITY_PERMISSIONS_PROPERTY is a **required** property. It appears in :numref:`TableSecPropsAccess`, :ref:`TableSecPropsAccess`. This property configures the signed document that specifies the access control permissions per domain and per topic. The element identifies the DomainParticipant to which the permissions apply. Each subject name can only appear in a single section within the XML Permissions document. The contents of the element should be the X.509 subject name for the DomainParticipant, as given in the "Subject" field of its Identity Certificate. A section with a subject name that does not match the subject name given in the corresponding Identity Certificate will be ignored. To sign an XML document with a Permissions Certificate Authority, run the following OpenSSL command (enter this all on one line):: openssl smime -sign -in PermissionsA.xml -text -out signed_PermissionsA.p7s -signer cacert.pem -inkey cakey.pem Then set this property value to ``signed_PermissionsA.p7s``. The signed permissions document only supports validity dates between 1970010100 and 2038011903. Any dates before 1970010100 will result in an error, and any dates after 2038011903 will be treated as 2038011903. Currently, *Connext DDS* will not work if the system time is after January 19th, 2038. You may specify either the file name or the document contents. - If specifying the file name, the property value must have the prefix ``file:`` (no space after the colon), followed by the fully qualified path and name of the file. - If specifying the contents of the document, the property value must have the prefix ``data:,`` (no space after the comma), followed by the contents inside the document. For example:: "data:,MIME-Version: 1.0\nContent-Type:...boundary=\”---7236\”\n\n" Note that for signed XML files, all whitespace characters (‘ ‘, ‘\r’, ‘\n’) are significant, and all quotes must be escaped with a backslash. The safest way to get the correct property value is to call the ``fread()`` function on the file and use the resulting buffer as the property value. Default: NULL