security: Convert ValidatorConfig to ValidationPolicyConfig
The security API also provides a convenience ValidatorConfig helper.
Change-Id: Ic86dec4904b917361cb4740204de4b6710d2a386
Refs: #3920
diff --git a/docs/tutorials/security-validator-config.rst b/docs/tutorials/security-validator-config.rst
index 9df0020..044161d 100644
--- a/docs/tutorials/security-validator-config.rst
+++ b/docs/tutorials/security-validator-config.rst
@@ -9,7 +9,7 @@
The configuration file consists of **rules** and **trust-anchors** that will be used in
validation. **Rules** tell the validator how to validate a packet, while **trust-anchors**
tell the validator which certificates are valid immediately. Here is an example of
-configuration file containing two rules.
+configuration file containing two rules and a trust anchor.
::
@@ -30,7 +30,7 @@
key-locator
{
type name
- name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
+ name /ndn/edu/ucla/yingdi/KEY/ksk-1234
relation equal
}
}
@@ -61,64 +61,73 @@
- The second part is to check whether further validation process is
necessary.
-When receiving a packet, the validator will apply rules in the configuration file
-one-by-one against the packet, until finding a rule that the packet qualifies for. And the
-second part of the matched rule will be used to check the validity of the packet. If the
-packet cannot qualify for any rules, it is treated as an invalid packet. Once a packet has
-been matched by a rule, the rest rules will not be applied against the packet. Therefore,
-you should always put the most specific rule to the top, otherwise it will become useless.
+When a packet is presented for validation, the validator will check the rules one-by-one
+in the configuration file using **for** and **filter** conditions against the packet,
+until finding a rule for which the packet qualifies. After that, the **checker**
+conditions of the matched rule will be used to check the validity of the packet. If the
+packet does not match any rules, it is treated as an invalid packet. Once a packet has
+been matched by a rule, the remaining rules are not applied to the packet (i.e., the
+matched rule "captures" the packet). Therefore, you should always put the most specific
+rule first.
In the example configuration, the first rule indicates that all the data packets under the
-name prefix ``/localhost/example`` must be signed by a key whose certificate name is
-``/ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT``. If a packet does not have a name under prefix
-``/localhost/example``, validator will skip the first rule and apply the second rule. The
-second rule indicates that any data packets must be validated along a hierarchy. And a
-certificate stored in a file "testbed-trust-anchor.cert" is valid.
+name prefix ``/localhost/example`` must be signed by a certificate whose name (the key
+part) is ``/ndn/edu/ucla/yingdi/KEY/ksk-1234``. If a packet does not have a name under
+prefix ``/localhost/example``, the validator will skip the first rule and apply the second
+rule. The second rule indicates that all other data packets must be validated using the
+hierarchical policy (data name should be prefix or equal to the identity part of the
+certificate name). The example configuration defines that all certificate chains must be
+rooted in the certificate defined in the file "testbed-trust-anchor.cert".
Rules in general
----------------
-A rule has four types of properties: **id**, **for**, **filter**, and **checker**.
+A rule has four properties: **id**, **for**, **filter**, and **checker**.
-The property **id** uniquely identifies the rule in the configuration file. As long as
+The **id** property uniquely identifies the rule in the configuration file. As long as
being unique, any name can be given to a rule, e.g., "Simple Rule", "Testbed Validation
Rule". A rule must have one and only one **id** property.
-A rule is either used to validate an interest packet or a data packet. This information
-is specified in the property **for**. Only two value can be specified: **data** and
-**interest**. A rule must have one and only one **for** property.
+A rule is either used to validate a data packet or an interest packet. This information
+is specified in the **for** property, which can be either **data** or **interest**. A
+rule must have exactly one **for** property.
-The property **filter** further constrains the packets that can be checked by the
-rule. Filter property is not required in a rule, in this case, the rule will capture all
-the packets passed to it. A rule may contain more than one filters, in this case, a packet
-can be checked by a rule only if the packet satisfies all the filters.
+The **filter** property further constrains the packets that can be checked by the
+rule. The filter property is not required in a rule; if omitted, the rule will capture all
+packets passed to it. A rule may contain multiple filters, in this case, a packet
+is captured by the rule only if all filters are satisfied.
.. note::
**ATTENTION: A packet that satisfies all the filters may not be valid**.
-The property **checker** defines the conditions that a matched packet must fulfill to be
+The **checker** property defines the conditions that a matched packet must fulfill to be
treated as a valid packet. A rule must have at least one **checker** property. A packet is
treated as valid if it can pass at least one of the checkers and as invalid when it cannot
pass any checkers.
-**filter** and **checker** have their own properties. Next, we will introduce them
-separately.
-
Filter Property
---------------
-Filter has its own **type** property. Although a rule may contain more than one filters,
-there is at most one filter of each type. So far, only one type of filter is defined:
-**name**. In other word, only one filter can be specified in a rule for now.
+Filter has a **type** property and type-specific properties. Although a rule can contain
+more than one filters, there can be at most one filter of each type.
+
+Currently, only the packet name filter is defined.
Name Filter
~~~~~~~~~~~
-There are two ways to express the conditions on name. The first way is to specify a
-relationship between the packet name and a particular name. In this case, two more
-properties are required: **name** and **relation**. A packet can fulfill the condition if
-the **name** has a **relation\* to the packet name. Three types of **\ relation\*\* has
-been defined: **equal**, **is-prefix-of**, **is-strict-prefix-of**. For example, a filter
+There are two ways to express the conditions on packet name:
+
+- relationship between the packet name and the specified name
+- :doc:`NDN regular expression <utils-ndn-regex>` match.
+
+Name and Relation
+^^^^^^^^^^^^^^^^^
+
+In the first case, two more properties are required: **name** and **relation**. A packet
+can fulfill the condition if the **name** has a **relation** to the packet's name. Three
+types of **relation** has been defined: **equal**, **is-prefix-of**,
+**is-strict-prefix-of**. For example, the filter
::
@@ -129,8 +138,9 @@
relation equal
}
-shall only capture a packet with the exact name ``/localhost/example``.
-And a filter
+will capture only a packet with the exact name ``/localhost/example``.
+
+The filter
::
@@ -141,8 +151,8 @@
relation is-prefix-of
}
-shall capture a packet with name ``/localhost/example`` or ``/localhost/example/data``, but
-cannot catch a packet with name ``/localhost/another_example``. And a filter
+will capture a packet with name ``/localhost/example`` or ``/localhost/example/data``, but
+will not capture a packet with name ``/localhost/another_example``. And the filter
::
@@ -153,42 +163,46 @@
relation is-strict-prefix-of
}
-shall capture a packet with name ``/localhost/example/data``, but cannot catch a packet
+will capture a packet with name ``/localhost/example/data``, but will not capture a packet
with name ``/localhost/example``.
+NDN Regular Expression Match
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
The second way is to specify an :doc:`utils-ndn-regex` that can match the packet. In this
-case, only one property **regex** is required. For example, a filter
+case, only one property **regex** is required. For example, the filter
::
filter
{
type name
- regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
+ regex ^<>*<KEY><><><>$
}
-shall capture all the identity certificates.
+will capture all certificates.
Checker Property
----------------
Passing all the filters in a rule only indicates that a packet can be checked using the
-rule, and it does not necessarily implies that the packet is valid. The validity of a
+rule, and it does not necessarily imply that the packet is valid. The validity of a
packet is determined by the property **checker**, which defines the conditions that a
valid packet must fulfill.
-Same as **filter**, **checker** has a property **type**. We have defined three types of
-checkers: **customized**, and **hierarchical**, and **fixed-signer**. As suggested by its
-name, **customized** checker allows you to customize the conditions according to specific
-requirements. **hierarchical** checker and **fixed-signer** checker are pre-defined
-shortcuts, which specify specific trust models separately.
+Same as **filter**, **checker** has a property **type**. We have defined two types of
+checkers:
+
+- **customized** is a checker that allows customization of the conditions according to specific
+ requirements;
+
+- **hierarchical** is a checker with pre-defined hierarchical trust model.
Customized Checker
~~~~~~~~~~~~~~~~~~
-So far, we only allow three customized properties in a customized
-checker: **sig-type**, **key-locator**. All of them are related to the
-``SignatureInfo`` of a packet.
+The customized checker requires two properties: **sig-type**, **key-locator**. Both must
+appear exactly once and are related to the ``SignatureInfo`` of a packet.
::
@@ -202,18 +216,16 @@
}
}
-The property **sig-type** specifies the acceptable signature type. Right now three
-signature types have been defined: **rsa-sha256** and **ecdsa-sha256** (which are strong
-signature types) and **sha256** (which is a weak signature type). If sig-type is sha256,
-then **key-locator** will be ignored. Validator will simply calculate the digest of a
-packet and compare it with the one in ``SignatureValue``. If sig-type is rsa-sha256 or
-ecdsa-sha256, you have to further customize the checker with **key-locator**.
+The property **sig-type** specifies the acceptable signature type and can be
+**rsa-sha256**, **ecdsa-sha256** (strong signature types), or **sha256** (weak signature
+type). If sig-type is sha256, **key-locator** is ignored, and the validator will simply
+calculate the digest of a packet and compare it with the one in ``SignatureValue``. If
+sig-type is rsa-sha256 or ecdsa-sha256, you have to further customize the checker with
+**key-locator**.
-The property **key-locator** which specifies the conditions on ``KeyLocator``. If the
+The property **key-locator** specifies the conditions on ``KeyLocator``. If the
**key-locator** property is specified, it requires the existence of the ``KeyLocator``
-field in ``SignatureInfo``. Although there are more than one types of ``KeyLocator``
-defined in the `Packet Format <http://named-data.net/doc/ndn-tlv/signature.html>`__,
-**key-locator** property only supports one type: **name**:
+field in ``SignatureInfo``. **key-locator** property only supports one type: **name**:
::
@@ -223,9 +235,9 @@
...
}
-Such a key-locator property specifies the conditions on the certificate name of the
-signing key. Since the conditions are about name, they can be specified in the same way as
-the name filter. For example, a checker could be:
+This key-locator property specifies the conditions on the certificate name of the signing
+key. Since the conditions are about name, they can be specified in the same way as the
+name filter. For example, a checker can be:
::
@@ -236,23 +248,23 @@
key-locator
{
type name
- name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
+ name /ndn/edu/ucla/yingdi/KEY/ksk-1234
relation equal
}
}
-This checker property requires that the packet must have a ``rsa-sha256`` signature generated
-by a key whose certificate name is ``/ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT``.
+This checker property requires that the packet must have a ``rsa-sha256`` signature that
+can be verified with ``/ndn/edu/ucla/yingdi/KEY/ksk-1234`` key.
Besides the two ways to express conditions on the ``KeyLocator`` name (name and regex),
you can further constrain the ``KeyLocator`` name using the information extracted from the
packet name. This third type of condition is expressed via a property
**hyper-relation**. The **hyper-relation** property consists of three parts:
-- an NDN regular expression that can extract information from packet name
-- an NDN regular expression that can extract information from ``KeyLocator`` name
-- relation from the part extracted from ``KeyLocator`` name to the one extracted from the
- packet name
+- an NDN regular expression that extracts information from the packet name
+- an NDN regular expression that extracts information from the ``KeyLocator`` name
+- relation from the part extracted from the ``KeyLocator`` name to the one extracted from
+ the packet name
For example, a checker:
@@ -267,8 +279,8 @@
type name
hyper-relation
{
- k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
- k-expand \\1\\2
+ k-regex ^(<>*)<KEY><>$
+ k-expand \\1
h-relation is-prefix-of
p-regex ^(<>*)$
p-expand \\1
@@ -277,30 +289,8 @@
}
}
-requires the packet name must be under the corresponding namespace of the ``KeyLocator``
-name.
-
-In some cases, you can even customize checker with another property For example:
-
-::
-
- checker
- {
- type customized
- sig-type rsa-sha256
- key-locator
- {
- type name
- hyper-relation
- {
- k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
- k-expand \\1\\2
- h-relation is-prefix-of
- p-regex ^(<>*)$
- p-expand \\1
- }
- }
- }
+requires the packet name must be under the corresponding namespace (identity part) of the
+``KeyLocator`` name.
Hierarchical Checker
~~~~~~~~~~~~~~~~~~~~
@@ -329,8 +319,8 @@
type name
hyper-relation
{
- k-regex ^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$
- k-expand \\1\\2
+ k-regex ^(<>*)<KEY><>$
+ k-expand \\1
h-relation is-prefix-of
p-regex ^(<>*)$
p-expand \\1
@@ -338,42 +328,14 @@
}
}
-Fixed-Signer Checker
-~~~~~~~~~~~~~~~~~~~~
-
-In some cases, you only accept packets signed with pre-trusted certificates,
-i.e. "one-step validation". Such a trust model can be expressed with **fixed-signer**
-checker. And you only need to specify the trusted certificate via property **signer**. The
-definition of **signer** is the same as **trust-anchor**. For example:
-
-::
-
- checker
- {
- type fixed-signer
- sig-type rsa-sha256
- signer
- {
- type file
- file-name "trusted-signer.cert"
- }
- signer
- {
- type base64
- base64-string "Bv0DGwdG...amHFvHIMDw=="
- }
- }
-
.. _validator-conf-trust-anchors:
Trust Anchors
-------------
-Although **trust-anchor** is always not required in the configuration file (for example,
-if fixed-signer checker is used), it is very common to have a few trust-anchors in the
-configuration file, otherwise most packets cannot be validated. A configuration file may
-contain more than one trust anchors, but the order of trust anchors does not matter. The
-structure of trust-anchor is same as the **signer** in fixed-signer checker, for example:
+**trust-anchor** is a necessary option in order to properly validate packets. A
+configuration file may contain more than one trust anchors and the order of trust anchors
+does not matter. The structure of trust-anchor is as follows:
::
@@ -389,7 +351,7 @@
}
You may also specify a trust-anchor directory. All certificates under this directory are
-taken as trust anchors. For example, if all trust anchors are put into
+taken as static trust anchors. For example, if all trust anchors are put into
``/usr/local/etc/ndn/keys``.
::
@@ -397,7 +359,7 @@
trust-anchor
{
type dir
- file-name /usr/local/etc/ndn/keys
+ dir /usr/local/etc/ndn/keys
}
If certificates under the directory might be changed during runtime, you can set a refresh
@@ -408,11 +370,11 @@
trust-anchor
{
type dir
- file-name /usr/local/etc/ndn/keys
+ dir /usr/local/etc/ndn/keys
refresh 1h ; refresh certificates every hour, other units include m (for minutes) and s (for seconds)
}
-There is another special trust anchor **any**. As long as such a trust-anchor is defined
+There is also a special trust anchor **any**. As long as such a trust-anchor is defined
in config file, packet validation will be turned off.
.. note::
@@ -430,6 +392,10 @@
Example Configuration For NLSR
------------------------------
+.. note::
+ **These example assumes the v1 certificate naming convention that is no longer in
+ use. The example will be updated later.**
+
The trust model of NLSR is semi-hierarchical. An example certificate signing hierarchy is:
::
@@ -584,43 +550,63 @@
::
- rule
- {
- id "NRD Prefix Registration Command Rule"
- for interest
- filter
- {
- type name
- regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]
- }
- checker
- {
- type customized
- sig-type rsa-sha256
- key-locator
- {
- type name
- regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
- }
- }
- }
- rule
- {
- id "Testbed Hierarchy Rule"
- for data
- filter
- {
- type name
- regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
- }
- checker
- {
- type hierarchical
- sig-type rsa-sha256
- }
- }
- trust-anchor
- {
- type file
- file-name "testbed-trust-anchor.cert"
- }
+ rule
+ {
+ id "RIB Prefix Registration Command Rule"
+ for interest ; rule for Interests (to validate CommandInterests)
+ filter
+ {
+ type name ; condition on interest name (w/o signature)
+ regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<><><>$ ; prefix before
+ ; SigInfo & SigValue
+ }
+ checker
+ {
+ type customized
+ sig-type rsa-sha256 ; interest must have a rsa-sha256 signature
+ key-locator
+ {
+ type name ; key locator must be the certificate name of the
+ ; signing key
+ regex ^<>*<KEY><><><>$
+ }
+ }
+ checker
+ {
+ type customized
+ sig-type ecdsa-sha256 ; interest must have a ecdsa-sha256 signature
+ key-locator
+ {
+ type name ; key locator must be the certificate name of the
+ ; signing key
+ regex ^<>*<KEY><><><>$
+ }
+ }
+ }
+ rule
+ {
+ id "NDN Testbed Hierarchy Rule"
+ for data ; rule for Data (to validate NDN certificates)
+ filter
+ {
+ type name ; condition on data name
+ regex ^<>*<KEY><><><>$
+ }
+ checker
+ {
+ type hierarchical ; the certificate name of the signing key and
+ ; the data name must follow the hierarchical model
+ sig-type rsa-sha256 ; data must have a rsa-sha256 signature
+ }
+ checker
+ {
+ type hierarchical ; the certificate name of the signing key and
+ ; the data name must follow the hierarchical model
+ sig-type ecdsa-sha256 ; data must have a ecdsa-sha256 signature
+ }
+ }
+ trust-anchor
+ {
+ type file
+ file-name keys/ndn-testbed-root.ndncert.base64
+ }
diff --git a/src/security/conf/checker.hpp b/src/security/conf/checker.hpp
deleted file mode 100644
index b928906..0000000
--- a/src/security/conf/checker.hpp
+++ /dev/null
@@ -1,483 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
- */
-
-#ifndef NDN_SECURITY_CONF_CHECKER_HPP
-#define NDN_SECURITY_CONF_CHECKER_HPP
-
-#include "common.hpp"
-
-#include "key-locator-checker.hpp"
-#include "../../util/io.hpp"
-#include "../validator.hpp"
-#include "../v1/identity-certificate.hpp"
-
-#include <boost/algorithm/string.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-
-namespace ndn {
-namespace security {
-namespace conf {
-
-class Checker
-{
-public:
- typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
- typedef function<void(const shared_ptr<const Interest>&,
- const std::string&)> OnInterestCheckFailed;
- typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
- typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;
-
- virtual
- ~Checker()
- {
- }
-
- /**
- * @brief check if data satisfies condition defined in the specific checker implementation
- *
- * @param data Data packet
- * @retval -1 if data is immediately invalid
- * @retval 1 if data is immediately valid
- * @retval 0 if further signature verification is needed.
- */
- virtual int8_t
- check(const Data& data) = 0;
-
- /**
- * @brief check if interest satisfies condition defined in the specific checker implementation
- *
- * @param interest Interest packet
- * @retval -1 if interest is immediately invalid
- * @retval 1 if interest is immediately valid
- * @retval 0 if further signature verification is needed.
- */
- virtual int8_t
- check(const Interest& interest) = 0;
-};
-
-class CustomizedChecker : public Checker
-{
-public:
- CustomizedChecker(uint32_t sigType,
- shared_ptr<KeyLocatorChecker> keyLocatorChecker)
- : m_sigType(sigType)
- , m_keyLocatorChecker(keyLocatorChecker)
- {
- switch (sigType) {
- case tlv::SignatureSha256WithRsa:
- case tlv::SignatureSha256WithEcdsa: {
- if (!static_cast<bool>(m_keyLocatorChecker))
- BOOST_THROW_EXCEPTION(Error("Strong signature requires KeyLocatorChecker"));
- return;
- }
- case tlv::DigestSha256:
- return;
- default:
- BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
- }
- }
-
- int8_t
- check(const Data& data) override
- {
- return check(data, data.getSignature());
- }
-
- int8_t
- check(const Interest& interest) override
- {
- try {
- const Name& interestName = interest.getName();
- Signature signature(interestName[command_interest::POS_SIG_INFO].blockFromValue(),
- interestName[command_interest::POS_SIG_VALUE].blockFromValue());
- return check(interest, signature);
- }
- catch (const Signature::Error& e) {
- // Invalid signature
- return -1;
- }
- catch (const tlv::Error& e) {
- // Cannot decode signature related TLVs
- return -1;
- }
- }
-
-private:
- template<class Packet>
- int8_t
- check(const Packet& packet, const Signature& signature)
- {
- if (m_sigType != signature.getType()) {
- // Signature type does not match
- return -1;
- }
-
- if (signature.getType() == tlv::DigestSha256)
- return 0;
-
- try {
- switch (signature.getType()) {
- case tlv::SignatureSha256WithRsa:
- case tlv::SignatureSha256WithEcdsa: {
- if (!signature.hasKeyLocator()) {
- // Missing KeyLocator in SignatureInfo
- return -1;
- }
- break;
- }
- default: {
- // Unsupported signature type
- return -1;
- }
- }
- }
- catch (const KeyLocator::Error& e) {
- // Cannot decode KeyLocator
- return -1;
- }
- catch (const tlv::Error& e) {
- // Cannot decode signature
- return -1;
- }
-
- std::string failInfo;
- if (m_keyLocatorChecker->check(packet, signature.getKeyLocator(), failInfo))
- return 0;
- else {
- return -1;
- }
- }
-
-private:
- uint32_t m_sigType;
- shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
-};
-
-class HierarchicalChecker : public CustomizedChecker
-{
-public:
- explicit
- HierarchicalChecker(uint32_t sigType)
- : CustomizedChecker(sigType,
- make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
- "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
- "\\1\\2",
- KeyLocatorChecker::RELATION_IS_PREFIX_OF))
- {
- }
-};
-
-class FixedSignerChecker : public Checker
-{
-public:
- FixedSignerChecker(uint32_t sigType,
- const std::vector<shared_ptr<v1::IdentityCertificate>>& signers)
- : m_sigType(sigType)
- {
- for (std::vector<shared_ptr<v1::IdentityCertificate>>::const_iterator it = signers.begin();
- it != signers.end(); it++)
- m_signers[(*it)->getName().getPrefix(-1)] = (*it);
-
- if (sigType != tlv::SignatureSha256WithRsa &&
- sigType != tlv::SignatureSha256WithEcdsa) {
- BOOST_THROW_EXCEPTION(Error("FixedSigner is only meaningful for strong signature type"));
- }
- }
-
- int8_t
- check(const Data& data) override
- {
- return check(data, data.getSignature());
- }
-
- int8_t
- check(const Interest& interest) override
- {
- try {
- const Name& interestName = interest.getName();
- Signature signature(interestName[command_interest::POS_SIG_INFO].blockFromValue(),
- interestName[command_interest::POS_SIG_VALUE].blockFromValue());
- return check(interest, signature);
- }
- catch (const Signature::Error& e) {
- // Invalid signature
- return -1;
- }
- catch (const tlv::Error& e) {
- // Cannot decode signature related TLVs
- return -1;
- }
- }
-
-private:
- template<class Packet>
- int8_t
- check(const Packet& packet, const Signature& signature)
- {
- if (m_sigType != signature.getType()) {
- // Signature type does not match
- return -1;
- }
-
- if (signature.getType() == tlv::DigestSha256) {
- // FixedSigner does not allow Sha256 signature type
- return -1;
- }
-
- try {
- switch (signature.getType()) {
- case tlv::SignatureSha256WithRsa:
- case tlv::SignatureSha256WithEcdsa: {
- if (!signature.hasKeyLocator()) {
- // Missing KeyLocator in SignatureInfo
- return -1;
- }
- break;
- }
-
- default: {
- // Unsupported signature type
- return -1;
- }
- }
-
- const Name& keyLocatorName = signature.getKeyLocator().getName();
-
- if (m_signers.find(keyLocatorName) == m_signers.end()) {
- // Signer is not in the fixed signer list
- return -1;
- }
-
- if (Validator::verifySignature(packet, signature,
- m_signers[keyLocatorName]->getPublicKeyInfo())) {
- return 1;
- }
- else {
- // Signature cannot be validated
- return -1;
- }
- }
- catch (const KeyLocator::Error& e) {
- // KeyLocator does not have name
- return -1;
- }
- catch (const tlv::Error& e) {
- // Cannot decode signature
- return -1;
- }
- }
-
-private:
- typedef std::map<Name, shared_ptr<v1::IdentityCertificate>> SignerList;
- uint32_t m_sigType;
- SignerList m_signers;
-};
-
-class CheckerFactory
-{
-public:
- /**
- * @brief create a checker from configuration file.
- *
- * @param configSection The section containing the definition of checker.
- * @param configFilename The configuration file name.
- * @return a shared pointer to the created checker.
- */
- static shared_ptr<Checker>
- create(const ConfigSection& configSection, const std::string& configFilename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- // Get checker.type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
-
- std::string type = propertyIt->second.data();
-
- if (boost::iequals(type, "customized"))
- return createCustomizedChecker(configSection, configFilename);
- else if (boost::iequals(type, "hierarchical"))
- return createHierarchicalChecker(configSection, configFilename);
- else if (boost::iequals(type, "fixed-signer"))
- return createFixedSignerChecker(configSection, configFilename);
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
- }
-
-private:
- static shared_ptr<Checker>
- createCustomizedChecker(const ConfigSection& configSection,
- const std::string& configFilename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
- propertyIt++;
-
- // Get checker.sig-type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
-
- std::string sigType = propertyIt->second.data();
- propertyIt++;
-
- // Get checker.key-locator
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
-
- shared_ptr<KeyLocatorChecker> keyLocatorChecker =
- KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
-
- return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
- }
-
- static shared_ptr<Checker>
- createHierarchicalChecker(const ConfigSection& configSection,
- const std::string& configFilename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
- propertyIt++;
-
- // Get checker.sig-type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
-
- std::string sigType = propertyIt->second.data();
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
-
- return make_shared<HierarchicalChecker>(getSigType(sigType));
- }
-
- static shared_ptr<Checker>
- createFixedSignerChecker(const ConfigSection& configSection,
- const std::string& configFilename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
- propertyIt++;
-
- // Get checker.sig-type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
-
- std::string sigType = propertyIt->second.data();
- propertyIt++;
-
- std::vector<shared_ptr<v1::IdentityCertificate>> signers;
- for (; propertyIt != configSection.end(); propertyIt++) {
- if (!boost::iequals(propertyIt->first, "signer"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.signer> but get <checker." +
- propertyIt->first + ">"));
-
- signers.push_back(getSigner(propertyIt->second, configFilename));
- }
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
-
- return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
- signers));
- }
-
- static shared_ptr<v1::IdentityCertificate>
- getSigner(const ConfigSection& configSection, const std::string& configFilename)
- {
- using namespace boost::filesystem;
-
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- // Get checker.signer.type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.type>"));
-
- std::string type = propertyIt->second.data();
- propertyIt++;
-
- if (boost::iequals(type, "file")) {
- // Get checker.signer.file-name
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.file-name>"));
-
- path certfilePath = absolute(propertyIt->second.data(),
- path(configFilename).parent_path());
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
-
- shared_ptr<v1::IdentityCertificate> idCert
- = io::load<v1::IdentityCertificate>(certfilePath.c_str());
-
- if (static_cast<bool>(idCert))
- return idCert;
- else
- BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " +
- certfilePath.native()));
- }
- else if (boost::iequals(type, "base64")) {
- // Get checker.signer.base64-string
- if (propertyIt == configSection.end() ||
- !boost::iequals(propertyIt->first, "base64-string"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.base64-string>"));
-
- std::stringstream ss(propertyIt->second.data());
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
-
- shared_ptr<v1::IdentityCertificate> idCert = io::load<v1::IdentityCertificate>(ss);
-
- if (static_cast<bool>(idCert))
- return idCert;
- else
- BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from string"));
- }
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported checker.signer type: " + type));
- }
-
- static uint32_t
- getSigType(const std::string& sigType)
- {
- if (boost::iequals(sigType, "rsa-sha256"))
- return tlv::SignatureSha256WithRsa;
- else if (boost::iequals(sigType, "ecdsa-sha256"))
- return tlv::SignatureSha256WithEcdsa;
- else if (boost::iequals(sigType, "sha256"))
- return tlv::DigestSha256;
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
- }
-};
-
-} // namespace conf
-} // namespace security
-} // namespace ndn
-
-#endif // NDN_SECURITY_CONF_CHECKER_HPP
diff --git a/src/security/conf/filter.hpp b/src/security/conf/filter.hpp
deleted file mode 100644
index 2ebc4e6..0000000
--- a/src/security/conf/filter.hpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
- */
-
-#ifndef NDN_SECURITY_CONF_FILTER_HPP
-#define NDN_SECURITY_CONF_FILTER_HPP
-
-#include "../../common.hpp"
-#include "../../data.hpp"
-#include "../../interest.hpp"
-#include "../../util/regex.hpp"
-#include "../security-common.hpp"
-#include <boost/algorithm/string.hpp>
-
-#include "common.hpp"
-
-namespace ndn {
-namespace security {
-namespace conf {
-
-/**
- * @brief Filter is one of the classes used by ValidatorConfig.
- *
- * The ValidatorConfig class consists of a set of rules.
- * The Filter class is a part of a rule and is used to match packet.
- * Matched packets will be checked against the checkers defined in the rule.
- */
-
-class Filter
-{
-public:
-
- virtual
- ~Filter()
- {
- }
-
- bool
- match(const Data& data)
- {
- return matchName(data.getName());
- }
-
- bool
- match(const Interest& interest)
- {
- if (interest.getName().size() < command_interest::MIN_SIZE)
- return false;
-
- Name unsignedName = interest.getName().getPrefix(-command_interest::MIN_SIZE);
- return matchName(unsignedName);
- }
-
-protected:
- virtual bool
- matchName(const Name& name) = 0;
-};
-
-class RelationNameFilter : public Filter
-{
-public:
- enum Relation
- {
- RELATION_EQUAL,
- RELATION_IS_PREFIX_OF,
- RELATION_IS_STRICT_PREFIX_OF
- };
-
- RelationNameFilter(const Name& name, Relation relation)
- : m_name(name)
- , m_relation(relation)
- {
- }
-
- virtual
- ~RelationNameFilter()
- {
- }
-
-protected:
- virtual bool
- matchName(const Name& name)
- {
- switch (m_relation)
- {
- case RELATION_EQUAL:
- return (name == m_name);
- case RELATION_IS_PREFIX_OF:
- return m_name.isPrefixOf(name);
- case RELATION_IS_STRICT_PREFIX_OF:
- return (m_name.isPrefixOf(name) && m_name.size() < name.size());
- default:
- return false;
- }
- }
-
-private:
- Name m_name;
- Relation m_relation;
-};
-
-class RegexNameFilter : public Filter
-{
-public:
- explicit
- RegexNameFilter(const Regex& regex)
- : m_regex(regex)
- {
- }
-
- virtual
- ~RegexNameFilter()
- {
- }
-
-protected:
- virtual bool
- matchName(const Name& name)
- {
- return m_regex.match(name);
- }
-
-private:
- Regex m_regex;
-};
-
-class FilterFactory
-{
-public:
- static shared_ptr<Filter>
- create(const ConfigSection& configSection)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
- BOOST_THROW_EXCEPTION(Error("Expect <filter.type>!"));
-
- std::string type = propertyIt->second.data();
-
- if (boost::iequals(type, "name"))
- return createNameFilter(configSection);
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported filter.type: " + type));
- }
-private:
- static shared_ptr<Filter>
- createNameFilter(const ConfigSection& configSection)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
- propertyIt++;
-
- if (propertyIt == configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect more properties for filter(name)"));
-
- if (boost::iequals(propertyIt->first, "name"))
- {
- // Get filter.name
- Name name;
- try
- {
- name = Name(propertyIt->second.data());
- }
- catch (Name::Error& e)
- {
- BOOST_THROW_EXCEPTION(Error("Wrong filter.name: " + propertyIt->second.data()));
- }
-
- propertyIt++;
-
- // Get filter.relation
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
- BOOST_THROW_EXCEPTION(Error("Expect <filter.relation>!"));
-
- std::string relationString = propertyIt->second.data();
- propertyIt++;
-
- RelationNameFilter::Relation relation;
- if (boost::iequals(relationString, "equal"))
- relation = RelationNameFilter::RELATION_EQUAL;
- else if (boost::iequals(relationString, "is-prefix-of"))
- relation = RelationNameFilter::RELATION_IS_PREFIX_OF;
- else if (boost::iequals(relationString, "is-strict-prefix-of"))
- relation = RelationNameFilter::RELATION_IS_STRICT_PREFIX_OF;
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported relation: " + relationString));
-
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of filter!"));
-
- return make_shared<RelationNameFilter>(name, relation);
- }
- else if (boost::iequals(propertyIt->first, "regex"))
- {
- std::string regexString = propertyIt->second.data();
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of filter!"));
-
- try
- {
- return shared_ptr<RegexNameFilter>(new RegexNameFilter(regexString));
- }
- catch (Regex::Error& e)
- {
- BOOST_THROW_EXCEPTION(Error("Wrong filter.regex: " + regexString));
- }
- }
- else
- BOOST_THROW_EXCEPTION(Error("Wrong filter(name) properties"));
- }
-};
-
-} // namespace conf
-} // namespace security
-} // namespace ndn
-
-#endif // NDN_SECURITY_CONF_FILTER_HPP
diff --git a/src/security/conf/key-locator-checker.hpp b/src/security/conf/key-locator-checker.hpp
deleted file mode 100644
index 04f43e0..0000000
--- a/src/security/conf/key-locator-checker.hpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
- */
-
-#ifndef NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
-#define NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
-
-#include "../../common.hpp"
-#include "../../data.hpp"
-#include "../../interest.hpp"
-#include "../../util/regex.hpp"
-#include "../security-common.hpp"
-#include <boost/algorithm/string.hpp>
-
-#include "common.hpp"
-
-namespace ndn {
-namespace security {
-namespace conf {
-
-class KeyLocatorCheckerFactory;
-
-/**
- * @brief KeyLocatorChecker is one of the classes used by ValidatorConfig.
- *
- * The ValidatorConfig class consists of a set of rules.
- * The KeyLocatorChecker class is part of a rule and is used to check if the KeyLocator field of a
- * packet satisfy the requirements.
- */
-
-
-class KeyLocatorChecker
-{
-public:
- enum Relation {
- RELATION_EQUAL,
- RELATION_IS_PREFIX_OF,
- RELATION_IS_STRICT_PREFIX_OF
- };
-
- virtual
- ~KeyLocatorChecker()
- {
- }
-
- bool
- check(const Data& data,
- const KeyLocator& keyLocator,
- std::string& failInfo)
- {
- return check(data.getName(), keyLocator, failInfo);
- }
-
- bool
- check(const Interest& interest,
- const KeyLocator& keyLocator,
- std::string& failInfo)
- {
- if (interest.getName().size() < command_interest::MIN_SIZE)
- {
- failInfo = "No Signature";
- return false;
- }
-
- Name signedName = interest.getName().getPrefix(-command_interest::MIN_SIZE);
- return check(signedName, keyLocator, failInfo);
- }
-
-protected:
-
- virtual bool
- check(const Name& packetName,
- const KeyLocator& keyLocator,
- std::string& failInfo) = 0;
-
- bool
- checkRelation(const Relation& relation, const Name& name1, const Name& name2)
- {
- switch (relation)
- {
- case RELATION_EQUAL:
- return (name1 == name2);
- case RELATION_IS_PREFIX_OF:
- return name1.isPrefixOf(name2);
- case RELATION_IS_STRICT_PREFIX_OF:
- return (name1.isPrefixOf(name2) && name1 != name2);
- default:
- return false;
- }
- }
-};
-
-class RelationKeyLocatorNameChecker : public KeyLocatorChecker
-{
-public:
- RelationKeyLocatorNameChecker(const Name& name,
- const KeyLocatorChecker::Relation& relation)
- : m_name(name)
- , m_relation(relation)
- {
- }
-
-protected:
- virtual bool
- check(const Name& packetName,
- const KeyLocator& keyLocator,
- std::string& failInfo)
- {
- try
- {
- if (checkRelation(m_relation, m_name, keyLocator.getName()))
- return true;
-
- failInfo = "KeyLocatorChecker failed!";
- return false;
- }
- catch (KeyLocator::Error& e)
- {
- failInfo = "KeyLocator does not have name";
- return false;
- }
- }
-
-private:
- Name m_name;
- KeyLocatorChecker::Relation m_relation;
-};
-
-class RegexKeyLocatorNameChecker : public KeyLocatorChecker
-{
-public:
- explicit
- RegexKeyLocatorNameChecker(const Regex& regex)
- : m_regex(regex)
- {
- }
-
-protected:
- virtual bool
- check(const Name& packetName,
- const KeyLocator& keyLocator,
- std::string& failInfo)
- {
- try
- {
- if (m_regex.match(keyLocator.getName()))
- return true;
-
- failInfo = "KeyLocatorChecker failed!";
- return false;
- }
- catch (KeyLocator::Error& e)
- {
- failInfo = "KeyLocator does not have name";
- return false;
- }
- }
-
-private:
- Regex m_regex;
-};
-
-class HyperKeyLocatorNameChecker : public KeyLocatorChecker
-{
-public:
- HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
- const std::string& kExpr, const std::string kExpand,
- const Relation& hyperRelation)
- : m_hyperPRegex(new Regex(pExpr, pExpand))
- , m_hyperKRegex(new Regex(kExpr, kExpand))
- , m_hyperRelation(hyperRelation)
- {
- }
-
-protected:
- virtual bool
- check(const Name& packetName,
- const KeyLocator& keyLocator,
- std::string& failInfo)
- {
- try
- {
- if (m_hyperPRegex->match(packetName) &&
- m_hyperKRegex->match(keyLocator.getName()) &&
- checkRelation(m_hyperRelation,
- m_hyperKRegex->expand(),
- m_hyperPRegex->expand()))
- return true;
-
- failInfo = "KeyLocatorChecker failed!";
- return false;
- }
- catch (KeyLocator::Error& e)
- {
- failInfo = "KeyLocator does not have name";
- return false;
- }
-
- }
-
-private:
- shared_ptr<Regex> m_hyperPRegex;
- shared_ptr<Regex> m_hyperKRegex;
- Relation m_hyperRelation;
-};
-
-
-class KeyLocatorCheckerFactory
-{
-public:
- static shared_ptr<KeyLocatorChecker>
- create(const ConfigSection& configSection, const std::string& filename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- // Get checker.key-locator.type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.type>!"));
-
- std::string type = propertyIt->second.data();
-
- if (boost::iequals(type, "name"))
- return createKeyLocatorNameChecker(configSection, filename);
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.type: " + type));
- }
-
-private:
- static shared_ptr<KeyLocatorChecker>
- createKeyLocatorNameChecker(const ConfigSection& configSection,
- const std::string& filename)
- {
- ConfigSection::const_iterator propertyIt = configSection.begin();
- propertyIt++;
-
- if (propertyIt == configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect more checker.key-locator properties"));
-
- if (boost::iequals(propertyIt->first, "name"))
- {
- Name name;
- try
- {
- name = Name(propertyIt->second.data());
- }
- catch (Name::Error& e)
- {
- BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.name: " +
- propertyIt->second.data()));
- }
- propertyIt++;
-
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.relation>!"));
-
- std::string relationString = propertyIt->second.data();
- propertyIt++;
-
- KeyLocatorChecker::Relation relation;
- if (boost::iequals(relationString, "equal"))
- relation = KeyLocatorChecker::RELATION_EQUAL;
- else if (boost::iequals(relationString, "is-prefix-of"))
- relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
- else if (boost::iequals(relationString, "is-strict-prefix-of"))
- relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported relation: " + relationString));
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator!"));
-
- return shared_ptr<RelationKeyLocatorNameChecker>
- (new RelationKeyLocatorNameChecker(name, relation));
- }
- else if (boost::iequals(propertyIt->first, "regex"))
- {
- std::string regexString = propertyIt->second.data();
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator!"));
-
- try
- {
- return shared_ptr<RegexKeyLocatorNameChecker>
- (new RegexKeyLocatorNameChecker(regexString));
- }
- catch (Regex::Error& e)
- {
- BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.regex: " + regexString));
- }
- }
- else if (boost::iequals(propertyIt->first, "hyper-relation"))
- {
- const ConfigSection& hSection = propertyIt->second;
-
- ConfigSection::const_iterator hPropertyIt = hSection.begin();
-
- // Get k-regex
- if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-regex>!"));
-
- std::string kRegex = hPropertyIt->second.data();
- hPropertyIt++;
-
- // Get k-expand
- if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-expand>!"));
-
- std::string kExpand = hPropertyIt->second.data();
- hPropertyIt++;
-
- // Get h-relation
- if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.h-relation>!"));
-
- std::string hRelation = hPropertyIt->second.data();
- hPropertyIt++;
-
- // Get p-regex
- if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-regex>!"));
-
- std::string pRegex = hPropertyIt->second.data();
- hPropertyIt++;
-
- // Get p-expand
- if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
- BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-expand>!"));
-
- std::string pExpand = hPropertyIt->second.data();
- hPropertyIt++;
-
- if (hPropertyIt != hSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator.hyper-relation!"));
-
- KeyLocatorChecker::Relation relation;
- if (boost::iequals(hRelation, "equal"))
- relation = KeyLocatorChecker::RELATION_EQUAL;
- else if (boost::iequals(hRelation, "is-prefix-of"))
- relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
- else if (boost::iequals(hRelation, "is-strict-prefix-of"))
- relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.hyper-relation.h-relation: "
- + hRelation));
-
- try
- {
- return shared_ptr<HyperKeyLocatorNameChecker>
- (new HyperKeyLocatorNameChecker(pRegex, pExpand,
- kRegex, kExpand,
- relation));
- }
- catch (Regex::Error& e)
- {
- BOOST_THROW_EXCEPTION(Error("Invalid regex for key-locator.hyper-relation"));
- }
- }
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator"));
- }
-};
-
-
-} // namespace conf
-} // namespace security
-} // namespace ndn
-
-#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
diff --git a/src/security/conf/rule.hpp b/src/security/conf/rule.hpp
deleted file mode 100644
index 03af661..0000000
--- a/src/security/conf/rule.hpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
- * @author Zhiyi Zhang <zhangzhiyi1919@gmail.com>
- */
-
-#ifndef NDN_SECURITY_CONF_RULE_HPP
-#define NDN_SECURITY_CONF_RULE_HPP
-
-#include "filter.hpp"
-#include "checker.hpp"
-
-
-namespace ndn {
-namespace security {
-namespace conf {
-
-template<class Packet>
-class Rule
-{
-public:
- explicit
- Rule(const std::string& id)
- : m_id(id)
- {
- }
-
- virtual
- ~Rule()
- {
- }
-
- const std::string&
- getId()
- {
- return m_id;
- }
-
- void
- addFilter(const shared_ptr<Filter>& filter)
- {
- m_filters.push_back(filter);
- }
-
- void
- addChecker(const shared_ptr<Checker>& checker)
- {
- m_checkers.push_back(checker);
- }
-
- bool
- match(const Packet& packet)
- {
- if (m_filters.empty())
- return true;
-
- for (FilterList::iterator it = m_filters.begin();
- it != m_filters.end(); it++)
- {
- if (!(*it)->match(packet))
- return false;
- }
-
- return true;
- }
-
- /**
- * @brief check if packet satisfies certain condition
- *
- * @param packet The packet
- * @param onValidated Callback function which is called when packet is immediately valid
- * @param onValidationFailed Call function which is called when packet is immediately invalid
- * @return -1 if packet is immediately invalid (onValidationFailed has been called)
- * 1 if packet is immediately valid (onValidated has been called)
- * 0 if further signature verification is needed.
- */
- template<class ValidatedCallback, class ValidationFailureCallback>
- int8_t
- check(const Packet& packet,
- const ValidatedCallback& onValidated,
- const ValidationFailureCallback& onValidationFailed)
- {
- bool hasPendingResult = false;
- for (CheckerList::iterator it = m_checkers.begin(); it != m_checkers.end(); it++) {
- int8_t result = (*it)->check(packet);
- if (result > 0) {
- onValidated(packet.shared_from_this());
- return result;
- }
- else if (result == 0)
- hasPendingResult = true;
- }
- if (hasPendingResult) {
- return 0;
- }
- else {
- onValidationFailed(packet.shared_from_this(), "Packet cannot pass any checkers.");
- return -1;
- }
- }
-
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- typedef std::vector<shared_ptr<Filter>> FilterList;
- typedef std::vector<shared_ptr<Checker>> CheckerList;
-
- std::string m_id;
- FilterList m_filters;
- CheckerList m_checkers;
-};
-
-} // namespace conf
-} // namespace security
-} // namespace ndn
-
-#endif // NDN_SECURITY_CONF_RULE_HPP
diff --git a/src/security/v2/trust-anchor-group.cpp b/src/security/v2/trust-anchor-group.cpp
index 24f5b9e..6d702ab 100644
--- a/src/security/v2/trust-anchor-group.cpp
+++ b/src/security/v2/trust-anchor-group.cpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -96,6 +96,8 @@
BOOST_THROW_EXCEPTION(std::runtime_error("Refresh period for the dynamic group must be positive"));
}
+ NDN_LOG_TRACE("Create dynamic trust anchor group " << id << " for file/dir " << path
+ << " with refresh time " << refreshPeriod);
refresh();
}
diff --git a/src/security/v2/validation-policy-config.cpp b/src/security/v2/validation-policy-config.cpp
new file mode 100644
index 0000000..ba87a23
--- /dev/null
+++ b/src/security/v2/validation-policy-config.cpp
@@ -0,0 +1,314 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "validation-policy-config.hpp"
+#include "validator.hpp"
+#include "../../util/io.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/property_tree/info_parser.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+ValidationPolicyConfig::ValidationPolicyConfig()
+ : m_shouldBypass(false)
+ , m_isConfigured(false)
+{
+}
+
+void
+ValidationPolicyConfig::load(const std::string& filename)
+{
+ std::ifstream inputFile;
+ inputFile.open(filename.c_str());
+ if (!inputFile.good() || !inputFile.is_open()) {
+ std::string msg = "Failed to read configuration file: ";
+ msg += filename;
+ BOOST_THROW_EXCEPTION(Error(msg));
+ }
+ load(inputFile, filename);
+ inputFile.close();
+}
+
+void
+ValidationPolicyConfig::load(const std::string& input, const std::string& filename)
+{
+ std::istringstream inputStream(input);
+ load(inputStream, filename);
+}
+
+void
+ValidationPolicyConfig::load(std::istream& input, const std::string& filename)
+{
+ ConfigSection tree;
+ try {
+ boost::property_tree::read_info(input, tree);
+ }
+ catch (const boost::property_tree::info_parser_error& error) {
+ std::stringstream msg;
+ msg << "Failed to parse configuration file";
+ msg << " " << filename;
+ msg << " " << error.message() << " line " << error.line();
+ BOOST_THROW_EXCEPTION(Error(msg.str()));
+ }
+
+ load(tree, filename);
+}
+
+void
+ValidationPolicyConfig::load(const ConfigSection& configSection,
+ const std::string& filename)
+{
+ if (m_isConfigured) {
+ BOOST_THROW_EXCEPTION(std::logic_error("ValidationPolicyConfig can be configured only once"));
+ }
+ m_isConfigured = true;
+
+ BOOST_ASSERT(!filename.empty());
+
+ if (configSection.begin() == configSection.end()) {
+ std::string msg = "Error processing configuration file";
+ msg += ": ";
+ msg += filename;
+ msg += " no data";
+ BOOST_THROW_EXCEPTION(Error(msg));
+ }
+
+ for (const auto& subSection : configSection) {
+ const std::string& sectionName = subSection.first;
+ const ConfigSection& section = subSection.second;
+
+ if (boost::iequals(sectionName, "rule")) {
+ auto rule = Rule::create(section, filename);
+ if (rule->getPktType() == tlv::Data) {
+ m_dataRules.push_back(std::move(rule));
+ }
+ else if (rule->getPktType() == tlv::Interest) {
+ m_interestRules.push_back(std::move(rule));
+ }
+ }
+ else if (boost::iequals(sectionName, "trust-anchor")) {
+ processConfigTrustAnchor(section, filename);
+ }
+ else {
+ std::string msg = "Error processing configuration file";
+ msg += " ";
+ msg += filename;
+ msg += " unrecognized section: " + sectionName;
+ BOOST_THROW_EXCEPTION(Error(msg));
+ }
+ }
+}
+
+void
+ValidationPolicyConfig::processConfigTrustAnchor(const ConfigSection& configSection, const std::string& filename)
+{
+ using namespace boost::filesystem;
+
+ ConfigSection::const_iterator propertyIt = configSection.begin();
+
+ // Get trust-anchor.type
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <trust-anchor.type>"));
+ }
+
+ std::string type = propertyIt->second.data();
+ propertyIt++;
+
+ if (boost::iequals(type, "file")) {
+ // Get trust-anchor.file
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <trust-anchor.file-name>"));
+ }
+
+ std::string file = propertyIt->second.data();
+ propertyIt++;
+
+ time::nanoseconds refresh = getRefreshPeriod(propertyIt, configSection.end());
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));
+ }
+
+ m_validator->loadAnchor(filename, absolute(file, path(filename).parent_path()).string(),
+ refresh, false);
+ return;
+ }
+ else if (boost::iequals(type, "base64")) {
+ // Get trust-anchor.base64-string
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
+ BOOST_THROW_EXCEPTION(Error("Expecting <trust-anchor.base64-string>"));
+
+ std::stringstream ss(propertyIt->second.data());
+ propertyIt++;
+
+ // Check other stuff
+ if (propertyIt != configSection.end())
+ BOOST_THROW_EXCEPTION(Error("Expecting the end of trust-anchor"));
+
+ auto idCert = io::load<Certificate>(ss);
+ if (idCert != nullptr) {
+ m_validator->loadAnchor("", std::move(*idCert));
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from base64-string"));
+ }
+
+ return;
+ }
+ else if (boost::iequals(type, "dir")) {
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
+ BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.dir>"));
+
+ std::string dirString(propertyIt->second.data());
+ propertyIt++;
+
+ time::nanoseconds refresh = getRefreshPeriod(propertyIt, configSection.end());
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expecting the end of trust-anchor"));
+ }
+
+ path dirPath = absolute(dirString, path(filename).parent_path());
+ m_validator->loadAnchor(dirString, dirPath.string(), refresh, true);
+ return;
+ }
+ else if (boost::iequals(type, "any")) {
+ m_shouldBypass = true;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unsupported trust-anchor.type: " + type));
+ }
+}
+
+time::nanoseconds
+ValidationPolicyConfig::getRefreshPeriod(ConfigSection::const_iterator& it,
+ const ConfigSection::const_iterator& end)
+{
+ time::nanoseconds refresh = time::nanoseconds::max();
+ if (it == end) {
+ return refresh;
+ }
+
+ if (!boost::iequals(it->first, "refresh")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <trust-anchor.refresh>"));
+ }
+
+ std::string inputString = it->second.data();
+ ++it;
+
+ char unit = inputString[inputString.size() - 1];
+ std::string refreshString = inputString.substr(0, inputString.size() - 1);
+
+ uint32_t refreshPeriod = 0;
+
+ try {
+ refreshPeriod = boost::lexical_cast<uint32_t>(refreshString);
+ }
+ catch (const boost::bad_lexical_cast&) {
+ BOOST_THROW_EXCEPTION(Error("Bad number: " + refreshString));
+ }
+
+ if (refreshPeriod == 0) {
+ return getDefaultRefreshPeriod();
+ }
+
+ switch (unit) {
+ case 'h':
+ return time::duration_cast<time::nanoseconds>(time::hours(refreshPeriod));
+ case 'm':
+ return time::duration_cast<time::nanoseconds>(time::minutes(refreshPeriod));
+ case 's':
+ return time::duration_cast<time::nanoseconds>(time::seconds(refreshPeriod));
+ default:
+ BOOST_THROW_EXCEPTION(Error(std::string("Wrong time unit: ") + unit));
+ }
+}
+
+time::nanoseconds
+ValidationPolicyConfig::getDefaultRefreshPeriod()
+{
+ return time::duration_cast<time::nanoseconds>(time::seconds(3600));
+}
+
+void
+ValidationPolicyConfig::checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
+ const ValidationContinuation& continueValidation)
+{
+ BOOST_ASSERT_MSG(!hasInnerPolicy(), "ValidationPolicyConfig must be a terminal inner policy");
+
+ if (m_shouldBypass) {
+ return continueValidation(nullptr, state);
+ }
+
+ Name klName = getKeyLocatorName(data, *state);
+ if (!state->getOutcome()) { // already failed
+ return;
+ }
+
+ for (const auto& rule : m_dataRules) {
+ if (rule->match(tlv::Data, data.getName())) {
+ if (rule->check(tlv::Data, data.getName(), klName, state)) {
+ return continueValidation(make_shared<CertificateRequest>(Interest(klName)), state);
+ }
+ // rule->check calls state->fail(...) if the check fails
+ return;
+ }
+ }
+
+ return state->fail({ValidationError::POLICY_ERROR, "No rule matched for data `" + data.getName().toUri() + "`"});
+}
+
+void
+ValidationPolicyConfig::checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
+ const ValidationContinuation& continueValidation)
+{
+ BOOST_ASSERT_MSG(!hasInnerPolicy(), "ValidationPolicyConfig must be a terminal inner policy");
+
+ if (m_shouldBypass) {
+ return continueValidation(nullptr, state);
+ }
+
+ Name klName = getKeyLocatorName(interest, *state);
+ if (!state->getOutcome()) { // already failed
+ return;
+ }
+
+ for (const auto& rule : m_interestRules) {
+ if (rule->match(tlv::Interest, interest.getName())) {
+ if (rule->check(tlv::Interest, interest.getName(), klName, state)) {
+ return continueValidation(make_shared<CertificateRequest>(Interest(klName)), state);
+ }
+ // rule->check calls state->fail(...) if the check fails
+ return;
+ }
+ }
+
+ return state->fail({ValidationError::POLICY_ERROR, "No rule matched for interest `" + interest.getName().toUri() + "`"});
+}
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validation-policy-config.hpp b/src/security/v2/validation-policy-config.hpp
new file mode 100644
index 0000000..7690cc1
--- /dev/null
+++ b/src/security/v2/validation-policy-config.hpp
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V2_VALIDATION_POLICY_CONFIG_HPP
+#define NDN_SECURITY_V2_VALIDATION_POLICY_CONFIG_HPP
+
+#include "validation-policy.hpp"
+#include "validator-config/rule.hpp"
+#include "validator-config/common.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+/**
+ * @brief The validator which can be set up via a configuration file.
+ *
+ * @note For command Interest validation, this policy must be combined with
+ * @p ValidationPolicyCommandInterest, in order to guard against replay attacks.
+ * @note This policy does not support inner policies (a sole policy or a terminal inner policy)
+ * @sa https://named-data.net/doc/ndn-cxx/current/tutorials/security-validator-config.html
+ */
+class ValidationPolicyConfig : public ValidationPolicy
+{
+public:
+ ValidationPolicyConfig();
+
+ void
+ load(const std::string& filename);
+
+ void
+ load(const std::string& input, const std::string& filename);
+
+ void
+ load(std::istream& input, const std::string& filename);
+
+ void
+ load(const ConfigSection& configSection, const std::string& filename);
+
+protected:
+ void
+ checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
+ const ValidationContinuation& continueValidation) override;
+
+ void
+ checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
+ const ValidationContinuation& continueValidation) override;
+
+private:
+ void
+ processConfigTrustAnchor(const ConfigSection& section, const std::string& filename);
+
+ time::nanoseconds
+ getRefreshPeriod(ConfigSection::const_iterator& it, const ConfigSection::const_iterator& end);
+
+ time::nanoseconds
+ getDefaultRefreshPeriod();
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /** @brief whether to always bypass validation
+ *
+ * This is set to true when 'any' is specified as a trust anchor.
+ * It causes all packets to bypass validation.
+ */
+ bool m_shouldBypass;
+ bool m_isConfigured;
+
+ std::vector<unique_ptr<Rule>> m_dataRules;
+ std::vector<unique_ptr<Rule>> m_interestRules;
+};
+
+} // namespace validator_config
+
+using validator_config::ValidationPolicyConfig;
+
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_V2_VALIDATION_POLICY_CONFIG_HPP
diff --git a/src/security/v2/validation-policy.hpp b/src/security/v2/validation-policy.hpp
index 351ffed..d7a261b 100644
--- a/src/security/v2/validation-policy.hpp
+++ b/src/security/v2/validation-policy.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -65,6 +65,20 @@
void
setInnerPolicy(unique_ptr<ValidationPolicy> innerPolicy);
+ /**
+ * @brief Check if inner policy is set
+ */
+ bool
+ hasInnerPolicy() const
+ {
+ return m_innerPolicy != nullptr;
+ }
+
+ /**
+ * @brief Return the inner policy
+ *
+ * If the inner policy was not set, behavior is undefined.
+ */
ValidationPolicy&
getInnerPolicy();
diff --git a/src/security/v2/validator-config/checker.cpp b/src/security/v2/validator-config/checker.cpp
new file mode 100644
index 0000000..47415af
--- /dev/null
+++ b/src/security/v2/validator-config/checker.cpp
@@ -0,0 +1,334 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "checker.hpp"
+#include "security/v2/validation-state.hpp"
+#include "security/verification-helpers.hpp"
+#include "security/pib/key.hpp"
+#include "util/logger.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+bool
+Checker::check(uint32_t pktType, const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
+{
+ BOOST_ASSERT(pktType == tlv::Interest || pktType == tlv::Data);
+
+ if (pktType == tlv::Interest) {
+ if (pktName.size() < signed_interest::MIN_SIZE)
+ return false;
+
+ return checkNames(pktName.getPrefix(-signed_interest::MIN_SIZE), klName, state);
+ }
+ else {
+ return checkNames(pktName, klName, state);
+ }
+}
+
+NameRelationChecker::NameRelationChecker(const Name& name, const NameRelation& relation)
+ : m_name(name)
+ , m_relation(relation)
+{
+}
+
+bool
+NameRelationChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
+{
+ // pktName not used in this check
+ Name identity = extractIdentityFromKeyName(klName);
+ bool result = checkNameRelation(m_relation, m_name, identity);
+ if (!result) {
+ std::ostringstream os;
+ os << "KeyLocator check failed: name relation " << m_name << " " << m_relation
+ << " for packet " << pktName << " is invalid"
+ << " (KeyLocator=" << klName << ", identity=" << identity << ")";
+ state->fail({ValidationError::POLICY_ERROR, os.str()});
+ }
+ return result;
+}
+
+RegexChecker::RegexChecker(const Regex& regex)
+ : m_regex(regex)
+{
+}
+
+bool
+RegexChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
+{
+ // pktName not used in this check
+ Name identity = extractIdentityFromKeyName(klName);
+ bool result = m_regex.match(identity);
+ if (!result) {
+ std::ostringstream os;
+ os << "KeyLocator check failed: regex " << m_regex << " for packet " << pktName << " is invalid"
+ << " (KeyLocator=" << klName << ", identity=" << identity << ")";
+ state->fail({ValidationError::POLICY_ERROR, os.str()});
+ }
+
+ return result;
+}
+
+HyperRelationChecker::HyperRelationChecker(const std::string& pktNameExpr, const std::string pktNameExpand,
+ const std::string& klNameExpr, const std::string klNameExpand,
+ const NameRelation& hyperRelation)
+ : m_hyperPRegex(pktNameExpr, pktNameExpand)
+ , m_hyperKRegex(klNameExpr, klNameExpand)
+ , m_hyperRelation(hyperRelation)
+{
+}
+
+bool
+HyperRelationChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
+{
+ if (!m_hyperPRegex.match(pktName) || !m_hyperKRegex.match(klName)) {
+ std::ostringstream os;
+ os << "Packet " << pktName << " (" << "KeyLocator=" << klName << ") does not match "
+ << "the hyper relation rule pkt=" << m_hyperPRegex << ", key=" << m_hyperKRegex;
+ state->fail({ValidationError::POLICY_ERROR, os.str()});
+ return false;
+ }
+
+ bool result = checkNameRelation(m_hyperRelation, m_hyperKRegex.expand(), m_hyperPRegex.expand());
+ if (!result) {
+ std::ostringstream os;
+ os << "KeyLocator check failed: hyper relation " << m_hyperRelation
+ << " pkt=" << m_hyperPRegex << ", key=" << m_hyperKRegex
+ << " of packet " << pktName << " (KeyLocator=" << klName << ") is invalid";
+ state->fail({ValidationError::POLICY_ERROR, os.str()});
+ }
+ return result;
+}
+
+unique_ptr<Checker>
+Checker::create(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+
+ // Get checker.type
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
+ }
+
+ std::string type = propertyIt->second.data();
+
+ if (boost::iequals(type, "customized")) {
+ return createCustomizedChecker(configSection, configFilename);
+ }
+ else if (boost::iequals(type, "hierarchical")) {
+ return createHierarchicalChecker(configSection, configFilename);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
+ }
+}
+
+unique_ptr<Checker>
+Checker::createCustomizedChecker(const ConfigSection& configSection,
+ const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+ propertyIt++;
+
+ // TODO implement restrictions based on signature type (outside this checker)
+
+ if (propertyIt != configSection.end() && boost::iequals(propertyIt->first, "sig-type")) {
+ // ignore sig-type
+ propertyIt++;
+ }
+
+ // Get checker.key-locator
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
+ }
+
+ auto checker = createKeyLocatorChecker(propertyIt->second, configFilename);
+ propertyIt++;
+
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
+ }
+
+ return checker;
+}
+
+unique_ptr<Checker>
+Checker::createHierarchicalChecker(const ConfigSection& configSection,
+ const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+ propertyIt++;
+
+ // TODO implement restrictions based on signature type (outside this checker)
+
+ if (propertyIt != configSection.end() && boost::iequals(propertyIt->first, "sig-type")) {
+ // ignore sig-type
+ propertyIt++;
+ }
+
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
+ }
+
+ return make_unique<HyperRelationChecker>("^(<>*)$", "\\1",
+ "^(<>*)<KEY><>$", "\\1",
+ NameRelation::IS_PREFIX_OF);
+}
+
+///
+
+unique_ptr<Checker>
+Checker::createKeyLocatorChecker(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+
+ // Get checker.key-locator.type
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.type>"));
+
+ std::string type = propertyIt->second.data();
+
+ if (boost::iequals(type, "name"))
+ return createKeyLocatorNameChecker(configSection, configFilename);
+ else
+ BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.type: " + type));
+}
+
+unique_ptr<Checker>
+Checker::createKeyLocatorNameChecker(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+ propertyIt++;
+
+ if (propertyIt == configSection.end())
+ BOOST_THROW_EXCEPTION(Error("Expect more checker.key-locator properties"));
+
+ if (boost::iequals(propertyIt->first, "name")) {
+ Name name;
+ try {
+ name = Name(propertyIt->second.data());
+ }
+ catch (const Name::Error& e) {
+ BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.name: " + propertyIt->second.data()));
+ }
+ propertyIt++;
+
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.relation>"));
+ }
+
+ std::string relationString = propertyIt->second.data();
+ propertyIt++;
+
+ NameRelation relation = getNameRelationFromString(relationString);
+
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator"));
+ }
+ return make_unique<NameRelationChecker>(name, relation);
+ }
+ else if (boost::iequals(propertyIt->first, "regex")) {
+ std::string regexString = propertyIt->second.data();
+ propertyIt++;
+
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator"));
+ }
+
+ try {
+ return make_unique<RegexChecker>(regexString);
+ }
+ catch (const Regex::Error& e) {
+ BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.regex: " + regexString));
+ }
+ }
+ else if (boost::iequals(propertyIt->first, "hyper-relation")) {
+ const ConfigSection& hSection = propertyIt->second;
+
+ ConfigSection::const_iterator hPropertyIt = hSection.begin();
+
+ // Get k-regex
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-regex>"));
+ }
+
+ std::string kRegex = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get k-expand
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-expand>"));
+ }
+
+ std::string kExpand = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get h-relation
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.h-relation>"));
+ }
+
+ std::string hRelation = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get p-regex
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-regex>"));
+ }
+
+ std::string pRegex = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ // Get p-expand
+ if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-expand>"));
+ }
+
+ std::string pExpand = hPropertyIt->second.data();
+ hPropertyIt++;
+
+ if (hPropertyIt != hSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator.hyper-relation"));
+ }
+
+ NameRelation relation = getNameRelationFromString(hRelation);
+ try {
+ return make_unique<HyperRelationChecker>(pRegex, pExpand, kRegex, kExpand, relation);
+ }
+ catch (const Regex::Error& e) {
+ BOOST_THROW_EXCEPTION(Error("Invalid regex for key-locator.hyper-relation"));
+ }
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator"));
+ }
+}
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validator-config/checker.hpp b/src/security/v2/validator-config/checker.hpp
new file mode 100644
index 0000000..390dc08
--- /dev/null
+++ b/src/security/v2/validator-config/checker.hpp
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V2_VALIDATOR_CONFIG_CHECKER_HPP
+#define NDN_SECURITY_V2_VALIDATOR_CONFIG_CHECKER_HPP
+
+#include "common.hpp"
+#include "name-relation.hpp"
+#include "../../../name.hpp"
+#include "../../../util/regex.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+
+class ValidationState;
+
+namespace validator_config {
+
+class Checker : noncopyable
+{
+public:
+ virtual
+ ~Checker() = default;
+
+ /**
+ * @brief Check if packet name ane KeyLocator satisfy the checker's conditions
+ *
+ * @param pktType tlv::Interest or tlv::Data
+ * @param pktName packet's name
+ * @param klName KeyLocator's name
+ * @param state Validation state
+ *
+ * @retval false data is immediately invalid. Will call state::fail() with proper code and message.
+ * @retval true further signature verification is needed.
+ */
+ bool
+ check(uint32_t pktType, const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state);
+
+ /**
+ * @brief create a checker from configuration section
+ *
+ * @param configSection The section containing the definition of checker.
+ * @param configFilename The configuration file name.
+ * @return a checker created from configuration
+ */
+ static unique_ptr<Checker>
+ create(const ConfigSection& configSection, const std::string& configFilename);
+
+private:
+ static unique_ptr<Checker>
+ createCustomizedChecker(const ConfigSection& configSection, const std::string& configFilename);
+
+ static unique_ptr<Checker>
+ createHierarchicalChecker(const ConfigSection& configSection, const std::string& configFilename);
+
+ static unique_ptr<Checker>
+ createKeyLocatorChecker(const ConfigSection& configSection, const std::string& configFilename);
+
+ static unique_ptr<Checker>
+ createKeyLocatorNameChecker(const ConfigSection& configSection, const std::string& configFilename);
+
+protected:
+ virtual bool
+ checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) = 0;
+};
+
+class NameRelationChecker : public Checker
+{
+public:
+ NameRelationChecker(const Name& name, const NameRelation& relation);
+
+protected:
+ bool
+ checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) override;
+
+private:
+ Name m_name;
+ NameRelation m_relation;
+};
+
+class RegexChecker : public Checker
+{
+public:
+ explicit
+ RegexChecker(const Regex& regex);
+
+protected:
+ bool
+ checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) override;
+
+private:
+ Regex m_regex;
+};
+
+class HyperRelationChecker : public Checker
+{
+public:
+ HyperRelationChecker(const std::string& pktNameExpr, const std::string pktNameExpand,
+ const std::string& klNameExpr, const std::string klNameExpand,
+ const NameRelation& hyperRelation);
+
+protected:
+ bool
+ checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) override;
+
+private:
+ Regex m_hyperPRegex;
+ Regex m_hyperKRegex;
+ NameRelation m_hyperRelation;
+};
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_V2_VALIDATOR_CONFIG_CHECKER_HPP
diff --git a/src/security/conf/common.hpp b/src/security/v2/validator-config/common.hpp
similarity index 75%
rename from src/security/conf/common.hpp
rename to src/security/v2/validator-config/common.hpp
index 3c79b7b..1663e5a 100644
--- a/src/security/conf/common.hpp
+++ b/src/security/v2/validator-config/common.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2014 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -21,31 +21,28 @@
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
-#ifndef NDN_SECURITY_CONF_COMMON_HPP
-#define NDN_SECURITY_CONF_COMMON_HPP
+#ifndef NDN_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+#define NDN_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
-#include "../../common.hpp"
-#include <string>
+#include "../../../common.hpp"
#include <boost/property_tree/ptree.hpp>
namespace ndn {
namespace security {
-namespace conf {
+namespace v2 {
+namespace validator_config {
typedef boost::property_tree::ptree ConfigSection;
class Error : public std::runtime_error
{
public:
- explicit
- Error(const std::string& what)
- : std::runtime_error(what)
- {
- }
+ using std::runtime_error::runtime_error;
};
-} // namespace conf
+} // namespace validator_config
+} // namespace v2
} // namespace security
} // namespace ndn
-#endif // NDN_SECURITY_CONF_COMMON_HPP
+#endif // NDN_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
diff --git a/src/security/v2/validator-config/filter.cpp b/src/security/v2/validator-config/filter.cpp
new file mode 100644
index 0000000..baeba1d
--- /dev/null
+++ b/src/security/v2/validator-config/filter.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "filter.hpp"
+
+#include "data.hpp"
+#include "interest.hpp"
+#include "util/regex.hpp"
+#include "security/security-common.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+bool
+Filter::match(uint32_t pktType, const Name& pktName)
+{
+ BOOST_ASSERT(pktType == tlv::Interest || pktType == tlv::Data);
+
+ if (pktType == tlv::Interest) {
+ if (pktName.size() < signed_interest::MIN_SIZE)
+ return false;
+
+ return matchName(pktName.getPrefix(-signed_interest::MIN_SIZE));
+ }
+ else {
+ return matchName(pktName);
+ }
+}
+
+RelationNameFilter::RelationNameFilter(const Name& name, NameRelation relation)
+ : m_name(name)
+ , m_relation(relation)
+{
+}
+
+bool
+RelationNameFilter::matchName(const Name& name)
+{
+ return checkNameRelation(m_relation, m_name, name);
+}
+
+RegexNameFilter::RegexNameFilter(const Regex& regex)
+ : m_regex(regex)
+{
+}
+
+bool
+RegexNameFilter::matchName(const Name& name)
+{
+ return m_regex.match(name);
+}
+
+unique_ptr<Filter>
+Filter::create(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <filter.type>"));
+ }
+
+ std::string type = propertyIt->second.data();
+
+ if (boost::iequals(type, "name"))
+ return createNameFilter(configSection, configFilename);
+ else
+ BOOST_THROW_EXCEPTION(Error("Unsupported filter.type: " + type));
+}
+
+unique_ptr<Filter>
+Filter::createNameFilter(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+ propertyIt++;
+
+ if (propertyIt == configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expect more properties for filter(name)"));
+ }
+
+ if (boost::iequals(propertyIt->first, "name")) {
+ // Get filter.name
+ Name name;
+ try {
+ name = Name(propertyIt->second.data());
+ }
+ catch (const Name::Error& e) {
+ BOOST_THROW_EXCEPTION(Error("Wrong filter.name: " + propertyIt->second.data()));
+ }
+
+ propertyIt++;
+
+ // Get filter.relation
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation")) {
+ BOOST_THROW_EXCEPTION(Error("Expect <filter.relation>"));
+ }
+
+ NameRelation relation = getNameRelationFromString(propertyIt->second.data());
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ BOOST_THROW_EXCEPTION(Error("Expect the end of filter"));
+
+ return make_unique<RelationNameFilter>(name, relation);
+ }
+ else if (boost::iequals(propertyIt->first, "regex")) {
+ std::string regexString = propertyIt->second.data();
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ BOOST_THROW_EXCEPTION(Error("Expect the end of filter"));
+
+ try {
+ return make_unique<RegexNameFilter>(regexString);
+ }
+ catch (const Regex::Error& e) {
+ BOOST_THROW_EXCEPTION(Error("Wrong filter.regex: " + regexString));
+ }
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Wrong filter(name) properties"));
+ }
+}
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validator-config/filter.hpp b/src/security/v2/validator-config/filter.hpp
new file mode 100644
index 0000000..cbd5275
--- /dev/null
+++ b/src/security/v2/validator-config/filter.hpp
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V2_VALIDATOR_CONFIG_FILTER_HPP
+#define NDN_SECURITY_V2_VALIDATOR_CONFIG_FILTER_HPP
+
+#include "common.hpp"
+#include "name-relation.hpp"
+#include "../../../interest.hpp"
+#include "../../../data.hpp"
+#include "../../../util/regex.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+/**
+ * @brief Filter is one of the classes used by ValidatorConfig.
+ *
+ * The ValidatorConfig class consists of a set of rules.
+ * The Filter class is a part of a rule and is used to match packet.
+ * Matched packets will be checked against the checkers defined in the rule.
+ */
+class Filter : noncopyable
+{
+public:
+ virtual
+ ~Filter() = default;
+
+ bool
+ match(uint32_t pktType, const Name& pktName);
+
+public:
+ /**
+ * @brief Create a filter from the configuration section
+ *
+ * @param configSection The section containing the definition of filter.
+ * @param configFilename The configuration file name.
+ * @return a filter created from configuration
+ */
+ static unique_ptr<Filter>
+ create(const ConfigSection& configSection, const std::string& configFilename);
+
+private:
+ static unique_ptr<Filter>
+ createNameFilter(const ConfigSection& configSection, const std::string& configFilename);
+
+private:
+ virtual bool
+ matchName(const Name& pktName) = 0;
+};
+
+/**
+ * @brief Check that name is in relation to the packet name
+ *
+ * The following configuration
+ * @code
+ * filter
+ * {
+ * type name
+ * name /example
+ * relation is-prefix-of
+ * }
+ * @endcode
+ *
+ * creates
+ * @code
+ * RelationNameFilter("/example", RelationNameFilter::RELATION_IS_PREFIX_OF);
+ * @endcode
+ */
+class RelationNameFilter : public Filter
+{
+public:
+ RelationNameFilter(const Name& name, NameRelation relation);
+
+private:
+ bool
+ matchName(const Name& pktName) override;
+
+private:
+ Name m_name;
+ NameRelation m_relation;
+};
+
+/**
+ * @brief Filter to check that packet name matches the specified regular expression
+ *
+ * The following configuration
+ * @code
+ * filter
+ * {
+ * type name
+ * regex ^[^<KEY>]*<KEY><>*<ksk-.*>$
+ * }
+ * @endcode
+ *
+ * creates
+ * @code
+ * RegexNameFilter("^[^<KEY>]*<KEY><>*<ksk-.*>$");
+ * @endcode
+ *
+ * @sa Regex
+ */
+class RegexNameFilter : public Filter
+{
+public:
+ explicit
+ RegexNameFilter(const Regex& regex);
+
+private:
+ bool
+ matchName(const Name& pktName) override;
+
+private:
+ Regex m_regex;
+};
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_V2_VALIDATOR_CONFIG_FILTER_HPP
diff --git a/src/security/v2/validator-config/name-relation.cpp b/src/security/v2/validator-config/name-relation.cpp
new file mode 100644
index 0000000..ad65e9a
--- /dev/null
+++ b/src/security/v2/validator-config/name-relation.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "name-relation.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+std::ostream&
+operator<<(std::ostream& os, NameRelation relation)
+{
+ switch (relation) {
+ case NameRelation::EQUAL:
+ return os << "equal";
+ case NameRelation::IS_PREFIX_OF:
+ return os << "is-prefix-of";
+ case NameRelation::IS_STRICT_PREFIX_OF:
+ return os << "is-strict-prefix-of";
+ }
+ return os;
+}
+
+bool
+checkNameRelation(NameRelation relation, const Name& name1, const Name& name2)
+{
+ switch (relation) {
+ case NameRelation::EQUAL:
+ return name1 == name2;
+ case NameRelation::IS_PREFIX_OF:
+ return name1.isPrefixOf(name2);
+ case NameRelation::IS_STRICT_PREFIX_OF:
+ return name1.isPrefixOf(name2) && name1.size() < name2.size();
+ }
+ return false;
+}
+
+NameRelation
+getNameRelationFromString(const std::string& relationString)
+{
+ if (boost::iequals(relationString, "equal")) {
+ return NameRelation::EQUAL;
+ }
+ else if (boost::iequals(relationString, "is-prefix-of")) {
+ return NameRelation::IS_PREFIX_OF;
+ }
+ else if (boost::iequals(relationString, "is-strict-prefix-of")) {
+ return NameRelation::IS_STRICT_PREFIX_OF;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unsupported relation: " + relationString));
+ }
+}
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validator-config/name-relation.hpp b/src/security/v2/validator-config/name-relation.hpp
new file mode 100644
index 0000000..5aa0dcf
--- /dev/null
+++ b/src/security/v2/validator-config/name-relation.hpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V2_VALIDATOR_CONFIG_NAME_RELATION_HPP
+#define NDN_SECURITY_V2_VALIDATOR_CONFIG_NAME_RELATION_HPP
+
+#include "common.hpp"
+#include "../../../name.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+enum class NameRelation {
+ EQUAL,
+ IS_PREFIX_OF,
+ IS_STRICT_PREFIX_OF
+};
+
+std::ostream&
+operator<<(std::ostream& os, NameRelation relation);
+
+/**
+ * @brief check whether @p name1 and @p name2 satisfies @p relation
+ */
+bool
+checkNameRelation(NameRelation relation, const Name& name1, const Name& name2);
+
+/**
+ * @brief convert @p relationString to NameRelation
+ * @throw Error if @p relationString cannot be converted
+ */
+NameRelation
+getNameRelationFromString(const std::string& relationString);
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_V2_VALIDATOR_CONFIG_NAME_RELATION_HPP
diff --git a/src/security/v2/validator-config/rule.cpp b/src/security/v2/validator-config/rule.cpp
new file mode 100644
index 0000000..93b8df4
--- /dev/null
+++ b/src/security/v2/validator-config/rule.cpp
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "rule.hpp"
+#include "util/logger.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+NDN_LOG_INIT(ndn.security.validator_config.Rule);
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+
+Rule::Rule(const std::string& id, uint32_t pktType)
+ : m_id(id)
+ , m_pktType(pktType)
+{
+}
+
+void
+Rule::addFilter(unique_ptr<Filter> filter)
+{
+ m_filters.push_back(std::move(filter));
+}
+
+void
+Rule::addChecker(unique_ptr<Checker> checker)
+{
+ m_checkers.push_back(std::move(checker));
+}
+
+bool
+Rule::match(uint32_t pktType, const Name& pktName) const
+{
+ NDN_LOG_TRACE("Trying to match " << pktName);
+ if (pktType != m_pktType) {
+ BOOST_THROW_EXCEPTION(Error("Invalid packet type supplied (" +
+ to_string(pktType) + " != " + to_string(m_pktType) + ")"));
+ }
+
+ if (m_filters.empty()) {
+ return true;
+ }
+
+ bool retval = false;
+ for (const auto& filter : m_filters) {
+ retval |= filter->match(pktType, pktName);
+ if (retval) {
+ break;
+ }
+ }
+ return retval;
+}
+
+bool
+Rule::check(uint32_t pktType, const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) const
+{
+ NDN_LOG_TRACE("Trying to check " << pktName << " with keyLocator " << klName);
+
+ if (pktType != m_pktType) {
+ BOOST_THROW_EXCEPTION(Error("Invalid packet type supplied (" +
+ to_string(pktType) + " != " + to_string(m_pktType) + ")"));
+ }
+
+ bool hasPendingResult = false;
+ for (const auto& checker : m_checkers) {
+ bool result = checker->check(pktType, pktName, klName, state);
+ if (!result) {
+ return result;
+ }
+ hasPendingResult = true;
+ }
+
+ return hasPendingResult;
+}
+
+unique_ptr<Rule>
+Rule::create(const ConfigSection& configSection, const std::string& configFilename)
+{
+ auto propertyIt = configSection.begin();
+
+ // Get rule.id
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <rule.id>"));
+ }
+
+ std::string ruleId = propertyIt->second.data();
+ propertyIt++;
+
+ // Get rule.for
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "for")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <rule.for> in rule: " + ruleId));
+ }
+
+ std::string usage = propertyIt->second.data();
+ propertyIt++;
+
+ bool isForData = false;
+ if (boost::iequals(usage, "data")) {
+ isForData = true;
+ }
+ else if (boost::iequals(usage, "interest")) {
+ isForData = false;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unrecognized <rule.for>: " + usage + " in rule: " + ruleId));
+ }
+
+ auto rule = make_unique<Rule>(ruleId, isForData ? tlv::Data : tlv::Interest);
+
+ // Get rule.filter(s)
+ for (; propertyIt != configSection.end(); propertyIt++) {
+ if (!boost::iequals(propertyIt->first, "filter")) {
+ if (boost::iequals(propertyIt->first, "checker")) {
+ break;
+ }
+ BOOST_THROW_EXCEPTION(Error("Expecting <rule.filter> in rule: " + ruleId));
+ }
+
+ rule->addFilter(Filter::create(propertyIt->second, configFilename));
+ }
+
+ // Get rule.checker(s)
+ bool hasCheckers = false;
+ for (; propertyIt != configSection.end(); propertyIt++) {
+ if (!boost::iequals(propertyIt->first, "checker")) {
+ BOOST_THROW_EXCEPTION(Error("Expecting <rule.checker> in rule: " + ruleId));
+ }
+
+ rule->addChecker(Checker::create(propertyIt->second, configFilename));
+ hasCheckers = true;
+ }
+
+ // Check other stuff
+ if (propertyIt != configSection.end()) {
+ BOOST_THROW_EXCEPTION(Error("Expecting the end of rule: " + ruleId));
+ }
+
+ if (!hasCheckers) {
+ BOOST_THROW_EXCEPTION(Error("No <rule.checker> is specified in rule: " + ruleId));
+ }
+
+ return rule;
+}
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validator-config/rule.hpp b/src/security/v2/validator-config/rule.hpp
new file mode 100644
index 0000000..66d6d6a
--- /dev/null
+++ b/src/security/v2/validator-config/rule.hpp
@@ -0,0 +1,113 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_V2_VALIDATOR_CONFIG_RULE_HPP
+#define NDN_SECURITY_V2_VALIDATOR_CONFIG_RULE_HPP
+
+#include "filter.hpp"
+#include "checker.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+
+class ValidationState;
+
+namespace validator_config {
+
+class Rule : noncopyable
+{
+public:
+ Rule(const std::string& id, uint32_t pktType);
+
+ const std::string&
+ getId() const
+ {
+ return m_id;
+ }
+
+ uint32_t
+ getPktType() const
+ {
+ return m_pktType;
+ }
+
+ void
+ addFilter(unique_ptr<Filter> filter);
+
+ void
+ addChecker(unique_ptr<Checker> checker);
+
+ /**
+ * @brief check if the packet name matches rule's filter
+ *
+ * If no filters were added, the rule matches everything.
+ *
+ * @param pktType tlv::Interest or tlv::Data
+ * @param pktName packet name, for signed Interests the last two components are not removed
+ * @retval true If at least one filter matches @p pktName
+ * @retval false If none of the filters match @p pktName
+ *
+ * @throw Error the supplied pktType doesn't match one for which the rule is designed
+ */
+ bool
+ match(uint32_t pktType, const Name& pktName) const;
+
+ /**
+ * @brief check if packet satisfies rule's condition
+ *
+ * @param pktType tlv::Interest or tlv::Data
+ * @param pktName packet name, for signed Interests the last two components are not removed
+ * @param klName KeyLocator name
+ * @param state Validation state
+ *
+ * @retval false packet violates at least one checker. Will call state::fail() with proper code and message.
+ * @retval true packet satisfies all checkers, further validation is needed
+ *
+ * @throw Error the supplied pktType doesn't match one for which the rule is designed
+ */
+ bool
+ check(uint32_t pktType, const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state) const;
+
+public:
+ /**
+ * @brief create a rule from configuration section
+ *
+ * @param configSection The section containing the definition of checker.
+ * @param configFilename The configuration file name.
+ * @return a rule created from configuration
+ */
+ static unique_ptr<Rule>
+ create(const ConfigSection& configSection, const std::string& configFilename);
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ std::string m_id;
+ uint32_t m_pktType;
+ std::vector<unique_ptr<Filter>> m_filters;
+ std::vector<unique_ptr<Checker>> m_checkers;
+};
+
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_V2_VALIDATOR_CONFIG_RULE_HPP
diff --git a/src/security/validator-config.cpp b/src/security/validator-config.cpp
index f267377..a8c5abc 100644
--- a/src/security/validator-config.cpp
+++ b/src/security/validator-config.cpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -20,770 +20,47 @@
*/
#include "validator-config.hpp"
-#include "certificate-cache-ttl.hpp"
-#include "../util/io.hpp"
-#include "../lp/tags.hpp"
-
-#include <boost/filesystem.hpp>
-#include <boost/property_tree/info_parser.hpp>
-#include <boost/algorithm/string.hpp>
+#include "v2/certificate-fetcher-from-network.hpp"
namespace ndn {
namespace security {
-const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
-const time::milliseconds ValidatorConfig::DEFAULT_GRACE_INTERVAL(3000);
-const time::system_clock::Duration ValidatorConfig::DEFAULT_KEY_TIMESTAMP_TTL = time::hours(1);
-
-ValidatorConfig::ValidatorConfig(Face* face,
- const shared_ptr<CertificateCache>& certificateCache,
- const time::milliseconds& graceInterval,
- const size_t stepLimit,
- const size_t maxTrackedKeys,
- const time::system_clock::Duration& keyTimestampTtl)
- : Validator(face)
- , m_shouldValidate(true)
- , m_stepLimit(stepLimit)
- , m_certificateCache(certificateCache)
- , m_graceInterval(graceInterval < time::milliseconds::zero() ?
- DEFAULT_GRACE_INTERVAL : graceInterval)
- , m_maxTrackedKeys(maxTrackedKeys)
- , m_keyTimestampTtl(keyTimestampTtl)
+ValidatorConfig::ValidatorConfig(std::unique_ptr<v2::CertificateFetcher> fetcher, const Options& options)
+ : v2::Validator(make_unique<v2::ValidationPolicyCommandInterest>(make_unique<v2::ValidationPolicyConfig>(),
+ options),
+ std::move(fetcher))
+ , m_policyConfig(static_cast<v2::ValidationPolicyConfig&>(getPolicy().getInnerPolicy()))
{
- if (m_certificateCache == nullptr && face != nullptr)
- m_certificateCache = make_shared<CertificateCacheTtl>(ref(face->getIoService()));
}
-ValidatorConfig::ValidatorConfig(Face& face,
- const shared_ptr<CertificateCache>& certificateCache,
- const time::milliseconds& graceInterval,
- const size_t stepLimit,
- const size_t maxTrackedKeys,
- const time::system_clock::Duration& keyTimestampTtl)
- : Validator(face)
- , m_shouldValidate(true)
- , m_stepLimit(stepLimit)
- , m_certificateCache(certificateCache)
- , m_graceInterval(graceInterval < time::milliseconds::zero() ?
- DEFAULT_GRACE_INTERVAL : graceInterval)
- , m_maxTrackedKeys(maxTrackedKeys)
- , m_keyTimestampTtl(keyTimestampTtl)
+ValidatorConfig::ValidatorConfig(Face& face, const Options& options)
+ : ValidatorConfig(make_unique<v2::CertificateFetcherFromNetwork>(face), options)
{
- if (m_certificateCache == nullptr)
- m_certificateCache = make_shared<CertificateCacheTtl>(ref(face.getIoService()));
}
void
ValidatorConfig::load(const std::string& filename)
{
- std::ifstream inputFile;
- inputFile.open(filename.c_str());
- if (!inputFile.good() || !inputFile.is_open()) {
- std::string msg = "Failed to read configuration file: ";
- msg += filename;
- BOOST_THROW_EXCEPTION(security::conf::Error(msg));
- }
- load(inputFile, filename);
- inputFile.close();
+ m_policyConfig.load(filename);
}
void
ValidatorConfig::load(const std::string& input, const std::string& filename)
{
- std::istringstream inputStream(input);
- load(inputStream, filename);
+ m_policyConfig.load(input, filename);
}
-
void
ValidatorConfig::load(std::istream& input, const std::string& filename)
{
- security::conf::ConfigSection tree;
- try {
- boost::property_tree::read_info(input, tree);
- }
- catch (const boost::property_tree::info_parser_error& error) {
- std::stringstream msg;
- msg << "Failed to parse configuration file";
- msg << " " << filename;
- msg << " " << error.message() << " line " << error.line();
- BOOST_THROW_EXCEPTION(security::conf::Error(msg.str()));
- }
-
- load(tree, filename);
+ m_policyConfig.load(input, filename);
}
void
-ValidatorConfig::load(const security::conf::ConfigSection& configSection,
+ValidatorConfig::load(const v2::validator_config::ConfigSection& configSection,
const std::string& filename)
{
- BOOST_ASSERT(!filename.empty());
-
- reset();
-
- if (configSection.begin() == configSection.end()) {
- std::string msg = "Error processing configuration file";
- msg += ": ";
- msg += filename;
- msg += " no data";
- BOOST_THROW_EXCEPTION(security::conf::Error(msg));
- }
-
- for (security::conf::ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end(); ++i) {
- const std::string& sectionName = i->first;
- const security::conf::ConfigSection& section = i->second;
-
- if (boost::iequals(sectionName, "rule")) {
- onConfigRule(section, filename);
- }
- else if (boost::iequals(sectionName, "trust-anchor")) {
- onConfigTrustAnchor(section, filename);
- }
- else {
- std::string msg = "Error processing configuration file";
- msg += " ";
- msg += filename;
- msg += " unrecognized section: " + sectionName;
- BOOST_THROW_EXCEPTION(security::conf::Error(msg));
- }
- }
-}
-
-void
-ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
- const std::string& filename)
-{
- using namespace ndn::security::conf;
-
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- // Get rule.id
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
- BOOST_THROW_EXCEPTION(Error("Expect <rule.id>!"));
-
- std::string ruleId = propertyIt->second.data();
- propertyIt++;
-
- // Get rule.for
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
- BOOST_THROW_EXCEPTION(Error("Expect <rule.for> in rule: " + ruleId + "!"));
-
- std::string usage = propertyIt->second.data();
- propertyIt++;
-
- bool isForData = false;
- if (boost::iequals(usage, "data"))
- isForData = true;
- else if (boost::iequals(usage, "interest"))
- isForData = false;
- else
- BOOST_THROW_EXCEPTION(Error("Unrecognized <rule.for>: " + usage
- + " in rule: " + ruleId));
-
- // Get rule.filter(s)
- std::vector<shared_ptr<Filter>> filters;
- for (; propertyIt != configSection.end(); propertyIt++) {
- if (!boost::iequals(propertyIt->first, "filter")) {
- if (boost::iequals(propertyIt->first, "checker"))
- break;
- BOOST_THROW_EXCEPTION(Error("Expect <rule.filter> in rule: " + ruleId));
- }
-
- filters.push_back(FilterFactory::create(propertyIt->second));
- continue;
- }
-
- // Get rule.checker(s)
- std::vector<shared_ptr<Checker>> checkers;
- for (; propertyIt != configSection.end(); propertyIt++) {
- if (!boost::iequals(propertyIt->first, "checker"))
- BOOST_THROW_EXCEPTION(Error("Expect <rule.checker> in rule: " + ruleId));
-
- checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
- continue;
- }
-
- // Check other stuff
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of rule: " + ruleId));
-
- if (checkers.empty())
- BOOST_THROW_EXCEPTION(Error("No <rule.checker> is specified in rule: " + ruleId));
-
- if (isForData) {
- shared_ptr<DataRule> rule = make_shared<DataRule>(ruleId);
- for (const auto& filter : filters)
- rule->addFilter(filter);
- for (const auto& checker : checkers)
- rule->addChecker(checker);
-
- m_dataRules.push_back(rule);
- }
- else {
- shared_ptr<InterestRule> rule = make_shared<InterestRule>(ruleId);;
- for (const auto& filter : filters)
- rule->addFilter(filter);
- for (const auto& checker : checkers)
- rule->addChecker(checker);
-
- m_interestRules.push_back(rule);
- }
-}
-
-void
-ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
- const std::string& filename)
-{
- using namespace ndn::security::conf;
- using namespace boost::filesystem;
-
- ConfigSection::const_iterator propertyIt = configSection.begin();
-
- // Get trust-anchor.type
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
- BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.type>!"));
-
- std::string type = propertyIt->second.data();
- propertyIt++;
-
- if (boost::iequals(type, "file")) {
- // Get trust-anchor.file
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
- BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.file-name>!"));
-
- std::string file = propertyIt->second.data();
- propertyIt++;
-
- // Check other stuff
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));
-
- path certfilePath = absolute(file, path(filename).parent_path());
- auto idCert = io::load<v1::IdentityCertificate>(certfilePath.string());
-
- if (idCert != nullptr) {
- BOOST_ASSERT(idCert->getName().size() >= 1);
- m_staticContainer.add(idCert);
- m_anchors[idCert->getName().getPrefix(-1)] = idCert;
- }
- else
- BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " + certfilePath.native()));
-
- return;
- }
- else if (boost::iequals(type, "base64")) {
- // Get trust-anchor.base64-string
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
- BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.base64-string>!"));
-
- std::stringstream ss(propertyIt->second.data());
- propertyIt++;
-
- // Check other stuff
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));
-
- auto idCert = io::load<v1::IdentityCertificate>(ss);
-
- if (idCert != nullptr) {
- BOOST_ASSERT(idCert->getName().size() >= 1);
- m_staticContainer.add(idCert);
- m_anchors[idCert->getName().getPrefix(-1)] = idCert;
- }
- else
- BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from base64-string"));
-
- return;
- }
- else if (boost::iequals(type, "dir")) {
- if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
- BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.dir>"));
-
- std::string dirString(propertyIt->second.data());
- propertyIt++;
-
- if (propertyIt != configSection.end()) {
- if (boost::iequals(propertyIt->first, "refresh")) {
- using namespace boost::filesystem;
-
- time::nanoseconds refresh = getRefreshPeriod(propertyIt->second.data());
- propertyIt++;
-
- if (propertyIt != configSection.end())
- BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor"));
-
- path dirPath = absolute(dirString, path(filename).parent_path());
-
- m_dynamicContainers.push_back(DynamicTrustAnchorContainer(dirPath, true, refresh));
-
- m_dynamicContainers.rbegin()->setLastRefresh(time::system_clock::now() - refresh);
-
- return;
- }
- else
- BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.refresh>!"));
- }
- else {
- using namespace boost::filesystem;
-
- path dirPath = absolute(dirString, path(filename).parent_path());
-
- directory_iterator end;
-
- for (directory_iterator it(dirPath); it != end; it++) {
- auto idCert = io::load<v1::IdentityCertificate>(it->path().string());
-
- if (idCert != nullptr)
- m_staticContainer.add(idCert);
- }
-
- return;
- }
- }
- else if (boost::iequals(type, "any")) {
- m_shouldValidate = false;
- }
- else
- BOOST_THROW_EXCEPTION(Error("Unsupported trust-anchor.type: " + type));
-}
-
-void
-ValidatorConfig::reset()
-{
- if (m_certificateCache != nullptr)
- m_certificateCache->reset();
- m_interestRules.clear();
- m_dataRules.clear();
-
- m_anchors.clear();
-
- m_staticContainer = TrustAnchorContainer();
-
- m_dynamicContainers.clear();
-}
-
-bool
-ValidatorConfig::isEmpty()
-{
- return ((m_certificateCache == nullptr || m_certificateCache->isEmpty()) &&
- m_interestRules.empty() && m_dataRules.empty() && m_anchors.empty());
-}
-
-time::nanoseconds
-ValidatorConfig::getRefreshPeriod(std::string inputString)
-{
- char unit = inputString[inputString.size() - 1];
- std::string refreshString = inputString.substr(0, inputString.size() - 1);
-
- uint32_t refreshPeriod = 0;
-
- try {
- refreshPeriod = boost::lexical_cast<uint32_t>(refreshString);
- }
- catch (const boost::bad_lexical_cast&) {
- BOOST_THROW_EXCEPTION(Error("Bad number: " + refreshString));
- }
-
- if (refreshPeriod == 0)
- return getDefaultRefreshPeriod();
-
- switch (unit) {
- case 'h':
- return time::duration_cast<time::nanoseconds>(time::hours(refreshPeriod));
- case 'm':
- return time::duration_cast<time::nanoseconds>(time::minutes(refreshPeriod));
- case 's':
- return time::duration_cast<time::nanoseconds>(time::seconds(refreshPeriod));
- default:
- BOOST_THROW_EXCEPTION(Error(std::string("Wrong time unit: ") + unit));
- }
-}
-
-time::nanoseconds
-ValidatorConfig::getDefaultRefreshPeriod()
-{
- return time::duration_cast<time::nanoseconds>(time::seconds(3600));
-}
-
-void
-ValidatorConfig::refreshAnchors()
-{
- time::system_clock::TimePoint now = time::system_clock::now();
-
- bool isRefreshed = false;
-
- for (auto cIt = m_dynamicContainers.begin();
- cIt != m_dynamicContainers.end() && cIt->getLastRefresh() + cIt->getRefreshPeriod() < now;
- cIt++) {
- isRefreshed = true;
- cIt->refresh();
- cIt->setLastRefresh(now);
- }
-
- if (isRefreshed) {
- m_anchors.clear();
-
- for (const auto& cert : m_staticContainer.getAll()) {
- m_anchors[cert->getName().getPrefix(-1)] = cert;
- }
-
- for (const auto& container : m_dynamicContainers) {
- const CertificateList& certList = container.getAll();
-
- for (const auto& cert :certList) {
- m_anchors[cert->getName().getPrefix(-1)] = cert;
- }
- }
- m_dynamicContainers.sort(ValidatorConfig::compareDynamicContainer);
- }
-}
-
-void
-ValidatorConfig::checkPolicy(const Data& data,
- int nSteps,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps)
-{
- if (!m_shouldValidate)
- return onValidated(data.shared_from_this());
-
- bool isMatched = false;
- int8_t checkResult = -1;
-
- for (const auto& dataRule : m_dataRules) {
- if (dataRule->match(data)) {
- isMatched = true;
- checkResult = dataRule->check(data, onValidated, onValidationFailed);
- break;
- }
- }
-
- if (!isMatched)
- return onValidationFailed(data.shared_from_this(), "No rule matched!");
-
- if (checkResult == 0) {
- const Signature& signature = data.getSignature();
- checkSignature(data, signature, nSteps,
- onValidated, onValidationFailed, nextSteps);
- }
-}
-
-void
-ValidatorConfig::checkPolicy(const Interest& interest,
- int nSteps,
- const OnInterestValidated& onValidated,
- const OnInterestValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps)
-{
- if (!m_shouldValidate)
- return onValidated(interest.shared_from_this());
-
- // If interestName has less than 4 name components,
- // it is definitely not a signed interest.
- if (interest.getName().size() < command_interest::MIN_SIZE)
- return onValidationFailed(interest.shared_from_this(),
- "Interest is not signed: " + interest.getName().toUri());
-
- try {
- const Name& interestName = interest.getName();
- Signature signature(interestName[command_interest::POS_SIG_INFO].blockFromValue(),
- interestName[command_interest::POS_SIG_VALUE].blockFromValue());
-
- if (!signature.hasKeyLocator())
- return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
-
- const KeyLocator& keyLocator = signature.getKeyLocator();
-
- if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
- return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");
-
- Name keyName = v1::IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
-
- bool isMatched = false;
- int8_t checkResult = -1;
-
- for (const auto& interestRule : m_interestRules) {
- if (interestRule->match(interest)) {
- isMatched = true;
- checkResult = interestRule->check(interest,
- bind(&ValidatorConfig::checkTimestamp, this, _1,
- keyName, onValidated, onValidationFailed),
- onValidationFailed);
- break;
- }
- }
-
- if (!isMatched)
- return onValidationFailed(interest.shared_from_this(), "No rule matched!");
-
- if (checkResult == 0) {
- checkSignature<Interest, OnInterestValidated, OnInterestValidationFailed>
- (interest, signature, nSteps,
- bind(&ValidatorConfig::checkTimestamp, this, _1,
- keyName, onValidated, onValidationFailed),
- onValidationFailed,
- nextSteps);
- }
- }
- catch (const Signature::Error& e) {
- return onValidationFailed(interest.shared_from_this(), "No valid signature");
- }
- catch (const KeyLocator::Error& e){
- return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
- }
- catch (const v1::IdentityCertificate::Error& e){
- return onValidationFailed(interest.shared_from_this(), "Cannot determine the signing key");
- }
- catch (const tlv::Error& e){
- return onValidationFailed(interest.shared_from_this(), "Cannot decode signature");
- }
-}
-
-void
-ValidatorConfig::checkTimestamp(const shared_ptr<const Interest>& interest,
- const Name& keyName,
- const OnInterestValidated& onValidated,
- const OnInterestValidationFailed& onValidationFailed)
-{
- const Name& interestName = interest->getName();
- time::system_clock::TimePoint interestTime;
-
- try {
- interestTime =
- time::fromUnixTimestamp(time::milliseconds(interestName.at(command_interest::POS_TIMESTAMP).toNumber()));
- }
- catch (const tlv::Error& e) {
- return onValidationFailed(interest,
- "Cannot decode signature related TLVs");
- }
-
- time::system_clock::TimePoint currentTime = time::system_clock::now();
-
- LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
- if (timestampIt == m_lastTimestamp.end()) {
- if (!(currentTime - m_graceInterval <= interestTime &&
- interestTime <= currentTime + m_graceInterval))
- return onValidationFailed(interest,
- "The command is not in grace interval: " + interest->getName().toUri());
- }
- else {
- if (interestTime <= timestampIt->second)
- return onValidationFailed(interest,
- "The command is outdated: " + interest->getName().toUri());
- }
-
- // Update timestamp
- if (timestampIt == m_lastTimestamp.end()) {
- cleanOldKeys();
- m_lastTimestamp[keyName] = interestTime;
- }
- else {
- timestampIt->second = interestTime;
- }
-
- return onValidated(interest);
-}
-
-void
-ValidatorConfig::cleanOldKeys()
-{
- if (m_lastTimestamp.size() < m_maxTrackedKeys)
- return;
-
- LastTimestampMap::iterator timestampIt = m_lastTimestamp.begin();
- LastTimestampMap::iterator end = m_lastTimestamp.end();
-
- time::system_clock::TimePoint now = time::system_clock::now();
- LastTimestampMap::iterator oldestKeyIt = m_lastTimestamp.begin();
- time::system_clock::TimePoint oldestTimestamp = oldestKeyIt->second;
-
- while (timestampIt != end) {
- if (now - timestampIt->second > m_keyTimestampTtl) {
- LastTimestampMap::iterator toDelete = timestampIt;
- timestampIt++;
- m_lastTimestamp.erase(toDelete);
- continue;
- }
-
- if (timestampIt->second < oldestTimestamp) {
- oldestTimestamp = timestampIt->second;
- oldestKeyIt = timestampIt;
- }
-
- timestampIt++;
- }
-
- if (m_lastTimestamp.size() >= m_maxTrackedKeys)
- m_lastTimestamp.erase(oldestKeyIt);
-}
-
-void
-ValidatorConfig::DynamicTrustAnchorContainer::refresh()
-{
- using namespace boost::filesystem;
-
- m_certificates.clear();
-
- if (m_isDir) {
- directory_iterator end;
-
- for (directory_iterator it(m_path); it != end; it++) {
- auto idCert = io::load<v1::IdentityCertificate>(it->path().string());
-
- if (idCert != nullptr)
- m_certificates.push_back(idCert);
- }
- }
- else {
- auto idCert = io::load<v1::IdentityCertificate>(m_path.string());
-
- if (idCert != nullptr)
- m_certificates.push_back(idCert);
- }
-}
-
-template<class Packet, class OnValidated, class OnFailed>
-void
-ValidatorConfig::checkSignature(const Packet& packet,
- const Signature& signature,
- size_t nSteps,
- const OnValidated& onValidated,
- const OnFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps)
-{
- if (signature.getType() == tlv::DigestSha256) {
- DigestSha256 sigSha256(signature);
-
- if (verifySignature(packet, sigSha256))
- return onValidated(packet.shared_from_this());
- else
- return onValidationFailed(packet.shared_from_this(), "Sha256 Signature cannot be verified!");
- }
-
- try {
- switch (signature.getType()) {
- case tlv::SignatureSha256WithRsa:
- case tlv::SignatureSha256WithEcdsa: {
- if (!signature.hasKeyLocator()) {
- return onValidationFailed(packet.shared_from_this(),
- "Missing KeyLocator in SignatureInfo");
- }
- break;
- }
- default:
- return onValidationFailed(packet.shared_from_this(), "Unsupported signature type");
- }
- }
- catch (const KeyLocator::Error& e) {
- return onValidationFailed(packet.shared_from_this(),
- "Cannot decode KeyLocator in public key signature");
- }
- catch (const tlv::Error& e) {
- return onValidationFailed(packet.shared_from_this(), "Cannot decode public key signature");
- }
-
- if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name) {
- return onValidationFailed(packet.shared_from_this(), "Unsupported KeyLocator type");
- }
-
- const Name& keyLocatorName = signature.getKeyLocator().getName();
-
- shared_ptr<const v1::Certificate> trustedCert;
-
- refreshAnchors();
-
- AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
- if (m_anchors.end() == it && m_certificateCache != nullptr)
- trustedCert = m_certificateCache->getCertificate(keyLocatorName);
- else if (m_anchors.end() != it)
- trustedCert = it->second;
-
- if (trustedCert != nullptr) {
- if (verifySignature(packet, signature, trustedCert->getPublicKeyInfo()))
- return onValidated(packet.shared_from_this());
- else
- return onValidationFailed(packet.shared_from_this(), "Cannot verify signature");
- }
- else {
- if (m_stepLimit == nSteps)
- return onValidationFailed(packet.shared_from_this(), "Maximum steps of validation reached");
-
- OnDataValidated onCertValidated =
- bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
- this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
-
- OnDataValidationFailed onCertValidationFailed =
- bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
- this, _1, _2, packet.shared_from_this(), onValidationFailed);
-
- Interest certInterest(keyLocatorName);
-
- uint64_t incomingFaceId = 0;
- auto incomingFaceIdTag = packet.template getTag<lp::IncomingFaceIdTag>();
- if (incomingFaceIdTag != nullptr) {
- incomingFaceId = incomingFaceIdTag->get();
- }
- auto nextStep = make_shared<ValidationRequest>(certInterest,
- onCertValidated,
- onCertValidationFailed,
- 1, nSteps + 1,
- incomingFaceId);
-
- nextSteps.push_back(nextStep);
- return;
- }
- return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type");
-}
-
-template<class Packet, class OnValidated, class OnFailed>
-void
-ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
- const shared_ptr<const Packet>& packet,
- const OnValidated& onValidated,
- const OnFailed& onValidationFailed)
-{
- if (signCertificate->getContentType() != tlv::ContentType_Key)
- return onValidationFailed(packet,
- "Cannot retrieve signer's cert: " +
- signCertificate->getName().toUri());
-
- shared_ptr<v1::IdentityCertificate> certificate;
- try {
- certificate = make_shared<v1::IdentityCertificate>(*signCertificate);
- }
- catch (const tlv::Error&) {
- return onValidationFailed(packet,
- "Cannot decode signer's cert: " +
- signCertificate->getName().toUri());
- }
-
- if (!certificate->isTooLate() && !certificate->isTooEarly()) {
- if (m_certificateCache != nullptr)
- m_certificateCache->insertCertificate(certificate);
-
- if (verifySignature(*packet, certificate->getPublicKeyInfo()))
- return onValidated(packet);
- else
- return onValidationFailed(packet,
- "Cannot verify signature: " + packet->getName().toUri());
- }
- else {
- return onValidationFailed(packet,
- "Signing certificate " +
- signCertificate->getName().toUri() + " is no longer valid.");
- }
-}
-
-template<class Packet, class OnFailed>
-void
-ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
- const std::string& failureInfo,
- const shared_ptr<const Packet>& packet,
- const OnFailed& onValidationFailed)
-{
- onValidationFailed(packet, failureInfo);
+ m_policyConfig.load(configSection, filename);
}
} // namespace security
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
index 47d536e..bc42e52 100644
--- a/src/security/validator-config.hpp
+++ b/src/security/validator-config.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -22,51 +22,29 @@
#ifndef NDN_SECURITY_VALIDATOR_CONFIG_HPP
#define NDN_SECURITY_VALIDATOR_CONFIG_HPP
-#include "validator.hpp"
-#include "certificate-cache.hpp"
-#include "conf/rule.hpp"
-#include "conf/common.hpp"
+#include "v2/validator.hpp"
+#include "v2/validation-policy-command-interest.hpp"
+#include "v2/validation-policy-config.hpp"
namespace ndn {
namespace security {
/**
- * @brief The validator which can be set up via a configuration file.
+ * @brief Helper for validator that uses CommandInterest + Config policy and NetworkFetcher
*/
-class ValidatorConfig : public Validator
+class ValidatorConfig : public v2::Validator
{
public:
- class Error : public Validator::Error
- {
- public:
- explicit
- Error(const std::string& what)
- : Validator::Error(what)
- {
- }
- };
+ using v2::Validator::Validator;
+ using Options = v2::ValidationPolicyCommandInterest::Options;
- /**
- * @note When both certificate cache and face are not supplied, no cache will be used.
- * However, if only face is supplied, a default cache will be created and used.
- */
explicit
- ValidatorConfig(Face* face = nullptr,
- const shared_ptr<CertificateCache>& certificateCache = DEFAULT_CERTIFICATE_CACHE,
- const time::milliseconds& graceInterval = DEFAULT_GRACE_INTERVAL,
- const size_t stepLimit = 10,
- const size_t maxTrackedKeys = 1000,
- const time::system_clock::Duration& keyTimestampTtl = DEFAULT_KEY_TIMESTAMP_TTL);
+ ValidatorConfig(std::unique_ptr<v2::CertificateFetcher> fetcher, const Options& options = Options());
- /// @deprecated Use the constructor taking Face* as parameter.
explicit
- ValidatorConfig(Face& face,
- const shared_ptr<CertificateCache>& certificateCache = DEFAULT_CERTIFICATE_CACHE,
- const time::milliseconds& graceInterval = DEFAULT_GRACE_INTERVAL,
- const size_t stepLimit = 10,
- const size_t maxTrackedKeys = 1000,
- const time::system_clock::Duration& keyTimestampTtl = DEFAULT_KEY_TIMESTAMP_TTL);
+ ValidatorConfig(Face& face, const Options& options = Options());
+public: // helpers for ValidationPolicyConfig
void
load(const std::string& filename);
@@ -77,182 +55,11 @@
load(std::istream& input, const std::string& filename);
void
- load(const security::conf::ConfigSection& configSection,
+ load(const v2::validator_config::ConfigSection& configSection,
const std::string& filename);
- void
- reset();
-
- bool
- isEmpty();
-
-protected:
- void
- checkPolicy(const Data& data,
- int nSteps,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps) override;
-
- void
- checkPolicy(const Interest& interest,
- int nSteps,
- const OnInterestValidated& onValidated,
- const OnInterestValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps) override;
-
-private:
- template<class Packet, class OnValidated, class OnFailed>
- void
- checkSignature(const Packet& packet,
- const Signature& signature,
- size_t nSteps,
- const OnValidated& onValidated,
- const OnFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps);
-
- void
- checkTimestamp(const shared_ptr<const Interest>& interest,
- const Name& keyName,
- const OnInterestValidated& onValidated,
- const OnInterestValidationFailed& onValidationFailed);
-
- template<class Packet, class OnValidated, class OnFailed>
- void
- onCertValidated(const shared_ptr<const Data>& signCertificate,
- const shared_ptr<const Packet>& packet,
- const OnValidated& onValidated,
- const OnFailed& onValidationFailed);
-
- template<class Packet, class OnFailed>
- void
- onCertFailed(const shared_ptr<const Data>& signCertificate,
- const std::string& failureInfo,
- const shared_ptr<const Packet>& packet,
- const OnFailed& onValidationFailed);
-
- void
- onConfigRule(const security::conf::ConfigSection& section,
- const std::string& filename);
-
- void
- onConfigTrustAnchor(const security::conf::ConfigSection& section,
- const std::string& filename);
-
- time::nanoseconds
- getRefreshPeriod(std::string refreshString);
-
- time::nanoseconds
- getDefaultRefreshPeriod();
-
- void
- refreshAnchors();
-
- void
- cleanOldKeys();
-
- class TrustAnchorContainer
- {
- public:
- const std::list<shared_ptr<v1::IdentityCertificate>>&
- getAll() const
- {
- return m_certificates;
- }
-
- void
- add(shared_ptr<v1::IdentityCertificate> certificate)
- {
- m_certificates.push_back(certificate);
- }
-
- protected:
- std::list<shared_ptr<v1::IdentityCertificate>> m_certificates;
- };
-
- class DynamicTrustAnchorContainer : public TrustAnchorContainer
- {
- public:
- DynamicTrustAnchorContainer(const boost::filesystem::path& path, bool isDir,
- time::nanoseconds refreshPeriod)
- : m_path(path)
- , m_isDir(isDir)
- , m_refreshPeriod(refreshPeriod)
- {
- }
-
- void
- setLastRefresh(const time::system_clock::TimePoint& lastRefresh)
- {
- m_lastRefresh = lastRefresh;
- }
-
- const time::system_clock::TimePoint&
- getLastRefresh() const
- {
- return m_lastRefresh;
- }
-
- const time::nanoseconds&
- getRefreshPeriod() const
- {
- return m_refreshPeriod;
- }
-
- void
- refresh();
-
- private:
- boost::filesystem::path m_path;
- bool m_isDir;
-
- time::system_clock::TimePoint m_lastRefresh;
- time::nanoseconds m_refreshPeriod;
- };
-
- static inline bool
- compareDynamicContainer(const DynamicTrustAnchorContainer& containerA,
- const DynamicTrustAnchorContainer& containerB)
- {
- return (containerA.getLastRefresh() < containerB.getLastRefresh());
- }
-
-public:
- static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
- static const time::milliseconds DEFAULT_GRACE_INTERVAL;
- static const time::system_clock::Duration DEFAULT_KEY_TIMESTAMP_TTL;
-
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- typedef security::conf::Rule<Interest> InterestRule;
- typedef security::conf::Rule<Data> DataRule;
- typedef std::vector<shared_ptr<InterestRule>> InterestRuleList;
- typedef std::vector<shared_ptr<DataRule>> DataRuleList;
- typedef std::map<Name, shared_ptr<v1::IdentityCertificate>> AnchorList;
- typedef std::list<DynamicTrustAnchorContainer> DynamicContainers; // sorted by m_lastRefresh
- typedef std::list<shared_ptr<v1::IdentityCertificate>> CertificateList;
-
- /**
- * @brief gives whether validation should be preformed
- *
- * If false, no validation occurs, and any packet is considered validated immediately.
- */
- bool m_shouldValidate;
-
- size_t m_stepLimit;
- shared_ptr<CertificateCache> m_certificateCache;
-
- InterestRuleList m_interestRules;
- DataRuleList m_dataRules;
-
- AnchorList m_anchors;
- TrustAnchorContainer m_staticContainer;
- DynamicContainers m_dynamicContainers;
-
- time::milliseconds m_graceInterval;
- size_t m_maxTrackedKeys;
- typedef std::map<Name, time::system_clock::TimePoint> LastTimestampMap;
- LastTimestampMap m_lastTimestamp;
- const time::system_clock::Duration& m_keyTimestampTtl;
+ v2::ValidationPolicyConfig& m_policyConfig;
};
} // namespace security
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
index b924024..486cc9c 100644
--- a/tests/identity-management-fixture.cpp
+++ b/tests/identity-management-fixture.cpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -120,8 +120,7 @@
}
bool
-IdentityManagementV2Fixture::saveIdentityCertificate(const security::Identity& identity,
- const std::string& filename)
+IdentityManagementV2Fixture::saveCertificate(const security::Identity& identity, const std::string& filename)
{
try {
auto cert = identity.getDefaultKey().getDefaultCertificate();
diff --git a/tests/identity-management-fixture.hpp b/tests/identity-management-fixture.hpp
index a6b348f..82545f9 100644
--- a/tests/identity-management-fixture.hpp
+++ b/tests/identity-management-fixture.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -25,11 +25,12 @@
#include "security/v1/key-chain.hpp"
#include "security/v2/key-chain.hpp"
#include "security/signing-helpers.hpp"
-#include <vector>
#include "boost-test.hpp"
#include "test-home-fixture.hpp"
+#include <vector>
+
namespace ndn {
namespace tests {
@@ -117,7 +118,7 @@
* @return whether successful
*/
bool
- saveIdentityCertificate(const security::Identity& identity, const std::string& filename);
+ saveCertificate(const security::Identity& identity, const std::string& filename);
/**
* @brief Issue a certificate for \p subIdentityName signed by \p issuer
diff --git a/tests/unit-tests/security/conf/checker.t.cpp b/tests/unit-tests/security/conf/checker.t.cpp
deleted file mode 100644
index be2f9ea..0000000
--- a/tests/unit-tests/security/conf/checker.t.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include "security/conf/checker.hpp"
-
-#include "boost-test.hpp"
-#include "identity-management-fixture.hpp"
-
-namespace ndn {
-namespace security {
-namespace conf {
-namespace tests {
-
-using namespace ndn::tests;
-
-BOOST_AUTO_TEST_SUITE(Security)
-BOOST_AUTO_TEST_SUITE(Conf)
-BOOST_FIXTURE_TEST_SUITE(TestChecker, IdentityManagementV1Fixture)
-
-BOOST_AUTO_TEST_CASE(CustomizedCheckerTest1)
-{
- using security::conf::CustomizedChecker;
- using security::conf::KeyLocatorChecker;
- using security::conf::RelationKeyLocatorNameChecker;
-
- Name identity("/SecurityTestConfChecker/CustomizedCheckerTest1");
- addIdentity(identity, RsaKeyParams());
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name identity2("/SecurityTestConfChecker/CustomizedCheckerTest1Wrong");
- addIdentity(identity2, RsaKeyParams());
- Name certName2 = m_keyChain.getDefaultCertificateNameForIdentity(identity2);
-
- Name packetName("/SecurityTestConfChecker/CustomizedCheckerTest1/Data");
- shared_ptr<Data> data1 = make_shared<Data>(packetName);
- m_keyChain.sign(*data1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data2 = make_shared<Data>(packetName);
- m_keyChain.sign(*data2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- shared_ptr<Interest> interest1 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Interest> interest2 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- int8_t result = 0;
-
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerEqual1 =
- make_shared<RelationKeyLocatorNameChecker>(certName.getPrefix(-1),
- KeyLocatorChecker::RELATION_EQUAL);
- CustomizedChecker checker1(tlv::SignatureSha256WithRsa, keyLocatorCheckerEqual1);
-
- result = checker1.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*interest1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*interest2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerEqual2 =
- make_shared<RelationKeyLocatorNameChecker>(identity,
- KeyLocatorChecker::RELATION_EQUAL);
- CustomizedChecker checker2(tlv::SignatureSha256WithRsa, keyLocatorCheckerEqual2);
-
- result = checker2.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*interest1);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerPrefix1 =
- make_shared<RelationKeyLocatorNameChecker>(certName.getPrefix(-1),
- KeyLocatorChecker::RELATION_IS_PREFIX_OF);
- CustomizedChecker checker3(tlv::SignatureSha256WithRsa, keyLocatorCheckerPrefix1);
-
- result = checker3.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker3.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerPrefix2 =
- make_shared<RelationKeyLocatorNameChecker>(identity,
- KeyLocatorChecker::RELATION_IS_PREFIX_OF);
- CustomizedChecker checker4(tlv::SignatureSha256WithRsa, keyLocatorCheckerPrefix2);
-
- result = checker4.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker4.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerStrict1 =
- make_shared<RelationKeyLocatorNameChecker>(certName.getPrefix(-1),
- KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF);
- CustomizedChecker checker5(tlv::SignatureSha256WithRsa, keyLocatorCheckerStrict1);
-
- result = checker5.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker5.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- shared_ptr<RelationKeyLocatorNameChecker> keyLocatorCheckerStrict2 =
- make_shared<RelationKeyLocatorNameChecker>(identity,
- KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF);
- CustomizedChecker checker6(tlv::SignatureSha256WithRsa, keyLocatorCheckerStrict2);
-
- result = checker6.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker6.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-}
-
-BOOST_AUTO_TEST_CASE(CustomizedCheckerTest2)
-{
- using security::conf::CustomizedChecker;
- using security::conf::KeyLocatorChecker;
- using security::conf::RegexKeyLocatorNameChecker;
-
- Name identity("/SecurityTestConfChecker/CustomizedCheckerTest2");
- addIdentity(identity, RsaKeyParams());
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name identity2("/SecurityTestConfChecker/CustomizedCheckerTest2Wrong");
- addIdentity(identity2, RsaKeyParams());
- Name certName2 = m_keyChain.getDefaultCertificateNameForIdentity(identity2);
-
- Name packetName("/SecurityTestConfChecker/CustomizedCheckerTest2/Data");
- shared_ptr<Data> data1 = make_shared<Data>(packetName);
- m_keyChain.sign(*data1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data2 = make_shared<Data>(packetName);
- m_keyChain.sign(*data2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- shared_ptr<Interest> interest1 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Interest> interest2 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- int8_t result = 0;
-
-
- shared_ptr<RegexKeyLocatorNameChecker> keyLocatorCheckerRegex1 =
- make_shared<RegexKeyLocatorNameChecker>(
- Regex("^<SecurityTestConfChecker><CustomizedCheckerTest2>"));
- CustomizedChecker checker1(tlv::SignatureSha256WithRsa, keyLocatorCheckerRegex1);
-
- result = checker1.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*interest1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*interest2);
- BOOST_CHECK_EQUAL(result, -1);
-}
-
-BOOST_AUTO_TEST_CASE(CustomizedCheckerTest3)
-{
- using security::conf::CustomizedChecker;
- using security::conf::KeyLocatorChecker;
- using security::conf::RegexKeyLocatorNameChecker;
-
- Name identity("/SecurityTestConfChecker/CustomizedCheckerTest3");
- addIdentity(identity, EcKeyParams());
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name identity2("/SecurityTestConfChecker/CustomizedCheckerTest3Wrong");
- addIdentity(identity2, EcKeyParams());
- Name certName2 = m_keyChain.getDefaultCertificateNameForIdentity(identity2);
-
- Name packetName("/SecurityTestConfChecker/CustomizedCheckerTest3/Data");
- shared_ptr<Data> data1 = make_shared<Data>(packetName);
- m_keyChain.sign(*data1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data2 = make_shared<Data>(packetName);
- m_keyChain.sign(*data2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- shared_ptr<Interest> interest1 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Interest> interest2 = make_shared<Interest>(packetName);
- m_keyChain.sign(*interest2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- int8_t result = 0;
-
-
- shared_ptr<RegexKeyLocatorNameChecker> keyLocatorCheckerRegex1 =
- make_shared<RegexKeyLocatorNameChecker>(
- Regex("^<SecurityTestConfChecker><CustomizedCheckerTest3>"));
- CustomizedChecker checker1(tlv::SignatureSha256WithEcdsa, keyLocatorCheckerRegex1);
-
- result = checker1.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*interest1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*interest2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- CustomizedChecker checker2(tlv::SignatureSha256WithRsa, keyLocatorCheckerRegex1);
-
- result = checker2.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-}
-
-BOOST_AUTO_TEST_CASE(HierarchicalCheckerTest1)
-{
- using security::conf::HierarchicalChecker;
-
- Name identity("/SecurityTestConfChecker/HierarchicalCheckerTest1");
- addIdentity(identity, EcKeyParams());
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name identity2("/SecurityTestConfChecker/HierarchicalCheckerTest1/Data");
- addIdentity(identity2, RsaKeyParams());
- Name certName2 = m_keyChain.getDefaultCertificateNameForIdentity(identity2);
-
- Name packetName("/SecurityTestConfChecker/HierarchicalCheckerTest1/Data");
- Name packetName2("/SecurityTestConfChecker");
- Name packetName3("/SecurityTestConfChecker/HierarchicalCheckerTest1");
-
- shared_ptr<Data> data1 = make_shared<Data>(packetName);
- m_keyChain.sign(*data1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data2 = make_shared<Data>(packetName2);
- m_keyChain.sign(*data2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data3 = make_shared<Data>(packetName3);
- m_keyChain.sign(*data3,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data4 = make_shared<Data>(packetName);
- m_keyChain.sign(*data4,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- shared_ptr<Data> data5 = make_shared<Data>(packetName2);
- m_keyChain.sign(*data5,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- shared_ptr<Data> data6 = make_shared<Data>(packetName3);
- m_keyChain.sign(*data6,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- int8_t result = 0;
-
- HierarchicalChecker checker1(tlv::SignatureSha256WithEcdsa);
-
- result = checker1.check(*data1);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*data3);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker1.check(*data4);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*data5);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker1.check(*data6);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- HierarchicalChecker checker2(tlv::SignatureSha256WithRsa);
-
- result = checker2.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*data3);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*data4);
- BOOST_CHECK_EQUAL(result, 0);
-
- result = checker2.check(*data5);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*data6);
- BOOST_CHECK_EQUAL(result, -1);
-}
-
-BOOST_AUTO_TEST_CASE(FixedSignerCheckerTest1)
-{
- using security::conf::FixedSignerChecker;
-
- Name identity("/SecurityTestConfChecker/FixedSignerCheckerTest1");
- addIdentity(identity, EcKeyParams());
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
- shared_ptr<v1::IdentityCertificate> cert1 = m_keyChain.getCertificate(certName);
-
- Name identity2("/SecurityTestConfChecker/FixedSignerCheckerTest1Wrong");
- addIdentity(identity2, RsaKeyParams());
- Name certName2 = m_keyChain.getDefaultCertificateNameForIdentity(identity2);
- shared_ptr<v1::IdentityCertificate> cert2 = m_keyChain.getCertificate(certName2);
-
- Name packetName("/Test/Data");
-
- shared_ptr<Data> data1 = make_shared<Data>(packetName);
- m_keyChain.sign(*data1,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity));
-
- shared_ptr<Data> data2 = make_shared<Data>(packetName);
- m_keyChain.sign(*data2,
- security::SigningInfo(security::SigningInfo::SIGNER_TYPE_ID,
- identity2));
-
- std::vector<shared_ptr<v1::IdentityCertificate> > certSet1;
- certSet1.push_back(cert1);
-
- std::vector<shared_ptr<v1::IdentityCertificate> > certSet2;
- certSet2.push_back(cert2);
-
-
- int8_t result = 0;
-
- FixedSignerChecker checker1(tlv::SignatureSha256WithEcdsa, certSet1);
-
- result = checker1.check(*data1);
- BOOST_CHECK_EQUAL(result, 1);
-
- result = checker1.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- FixedSignerChecker checker2(tlv::SignatureSha256WithRsa, certSet1);
-
- result = checker2.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker2.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- FixedSignerChecker checker3(tlv::SignatureSha256WithEcdsa, certSet2);
-
- result = checker3.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker3.check(*data2);
- BOOST_CHECK_EQUAL(result, -1);
-
-
- FixedSignerChecker checker4(tlv::SignatureSha256WithRsa, certSet2);
-
- result = checker4.check(*data1);
- BOOST_CHECK_EQUAL(result, -1);
-
- result = checker4.check(*data2);
- BOOST_CHECK_EQUAL(result, 1);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // TestChecker
-BOOST_AUTO_TEST_SUITE_END() // Conf
-BOOST_AUTO_TEST_SUITE_END() // Security
-
-} // namespace tests
-} // namespace conf
-} // namespace security
-} // namespace ndn
diff --git a/tests/unit-tests/security/v2/validation-policy-config.t.cpp b/tests/unit-tests/security/v2/validation-policy-config.t.cpp
new file mode 100644
index 0000000..308b0fe
--- /dev/null
+++ b/tests/unit-tests/security/v2/validation-policy-config.t.cpp
@@ -0,0 +1,456 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validation-policy-config.hpp"
+#include "security/transform/base64-encode.hpp"
+#include "security/transform/buffer-source.hpp"
+#include "security/transform/stream-sink.hpp"
+#include "util/logger.hpp"
+#include "util/io.hpp"
+
+#include "boost-test.hpp"
+#include "validator-config/common.hpp"
+#include "validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(TestValidationPolicyConfig)
+
+template<typename Packet>
+class PacketName;
+
+template<>
+class PacketName<Interest>
+{
+public:
+ static std::string
+ getName()
+ {
+ return "interest";
+ }
+};
+
+template<>
+class PacketName<Data>
+{
+public:
+ static std::string
+ getName()
+ {
+ return "data";
+ }
+};
+
+template<typename PacketType>
+class ValidationPolicyConfigFixture : public HierarchicalValidatorFixture<ValidationPolicyConfig>
+{
+public:
+ ValidationPolicyConfigFixture()
+ : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "v2" / "validation-policy-config")
+ {
+ boost::filesystem::create_directories(path);
+ baseConfig = R"CONF(
+ rule
+ {
+ id test-rule-id
+ for )CONF" + PacketName<Packet>::getName() + R"CONF(
+ filter
+ {
+ type name
+ name )CONF" + identity.getName().toUri() + R"CONF(
+ relation is-prefix-of
+ }
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ }
+ )CONF";
+ }
+
+ ~ValidationPolicyConfigFixture()
+ {
+ boost::filesystem::remove_all(path);
+ }
+
+public:
+ using Packet = PacketType;
+
+ const boost::filesystem::path path;
+ std::string baseConfig;
+};
+
+template<typename PacketType>
+class LoadStringWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithFileAnchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadFileWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadFileWithFileAnchor()
+ {
+ std::string configFile = (this->path / "config.conf").string();
+ {
+ std::ofstream config(configFile.c_str());
+ config << this->baseConfig << R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF";
+ }
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->policy.load(configFile);
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadSectionWithFileAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadSectionWithFileAnchor()
+ {
+ auto section = makeSection(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type file
+ file-name "trust-anchor.ndncert"
+ }
+ )CONF");
+
+ this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ this->policy.load(section, (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+template<typename PacketType>
+class LoadStringWithBase64Anchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithBase64Anchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ std::ostringstream os;
+ using namespace ndn::security::transform;
+ const auto& cert = this->identity.getDefaultKey().getDefaultCertificate();
+ bufferSource(cert.wireEncode().wire(), cert.wireEncode().size()) >> base64Encode(false) >> streamSink(os);
+
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type base64
+ base64-string ")CONF" + os.str() + R"CONF("
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+class NoRefresh
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "";
+ }
+};
+
+class Refresh1h
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1h";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return time::hours(1);
+ }
+};
+
+class Refresh1m
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1m";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return time::minutes(1);
+ }
+};
+
+class Refresh1s
+{
+public:
+ static std::string
+ getRefreshString()
+ {
+ return "refresh 1s";
+ }
+
+ static time::milliseconds
+ getRefreshTime()
+ {
+ return time::seconds(1);
+ }
+};
+
+template<typename PacketType, typename Refresh = NoRefresh>
+class LoadStringWithDirAnchor : public ValidationPolicyConfigFixture<PacketType>
+{
+public:
+ LoadStringWithDirAnchor()
+ {
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
+
+ boost::filesystem::create_directories(this->path / "keys");
+ this->saveCertificate(this->identity, (this->path / "keys" / "identity.ndncert").string());
+
+ this->policy.load(this->baseConfig + R"CONF(
+ trust-anchor
+ {
+ type dir
+ dir keys
+ )CONF" + Refresh::getRefreshString() + R"CONF(
+ }
+ )CONF", (this->path / "test-config").string());
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, false);
+ }
+};
+
+using DataPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Data>,
+ LoadFileWithFileAnchor<Data>,
+ LoadSectionWithFileAnchor<Data>,
+ LoadStringWithBase64Anchor<Data>,
+ LoadStringWithDirAnchor<Data>,
+ LoadStringWithDirAnchor<Data, Refresh1h>,
+ LoadStringWithDirAnchor<Data, Refresh1m>,
+ LoadStringWithDirAnchor<Data, Refresh1s>
+ >;
+
+using InterestPolicies = boost::mpl::vector<LoadStringWithFileAnchor<Interest>,
+ LoadFileWithFileAnchor<Interest>,
+ LoadSectionWithFileAnchor<Interest>,
+ LoadStringWithBase64Anchor<Interest>,
+ LoadStringWithDirAnchor<Interest>,
+ LoadStringWithDirAnchor<Interest, Refresh1h>,
+ LoadStringWithDirAnchor<Interest, Refresh1m>,
+ LoadStringWithDirAnchor<Interest, Refresh1s>
+ >;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateData, Policy, DataPolicies, Policy)
+{
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 1);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
+
+ using Packet = typename Policy::Packet;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_FAILURE(packet, "Unsigned");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_FAILURE(packet, "Policy doesn't accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the policy-compliant cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateInterest, Policy, InterestPolicies, Policy)
+{
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 1);
+
+ using Packet = typename Policy::Packet;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_FAILURE(packet, "Unsigned");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_FAILURE(packet, "Policy doesn't accept Sha256Digest signature");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Should get accepted, as signed by the anchor");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as there is no matching rule for data");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as signed by the policy-violating cert");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, because subSelfSignedIdentity is not a trust anchor");
+}
+
+using Packets = boost::mpl::vector<Interest, Data>;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(TrustAnchorWildcard, Packet, Packets, ValidationPolicyConfigFixture<Packet>)
+{
+ this->policy.load(R"CONF(
+ trust-anchor
+ {
+ type any
+ }
+ )CONF", "test-config");
+
+ BOOST_CHECK_EQUAL(this->policy.m_isConfigured, true);
+ BOOST_CHECK_EQUAL(this->policy.m_shouldBypass, true);
+ BOOST_CHECK_EQUAL(this->policy.m_dataRules.size(), 0);
+ BOOST_CHECK_EQUAL(this->policy.m_interestRules.size(), 0);
+
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ Packet packet = unsignedPacket;
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingWithSha256());
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->otherIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subSelfSignedIdentity));
+ VALIDATE_SUCCESS(packet, "Policy should accept everything");
+}
+
+using ReloadedPolicies = boost::mpl::vector<Refresh1h, Refresh1m, Refresh1s>;
+
+// Somehow, didn't work without this wrapper
+template<typename ReloadPolicy>
+class ReloadPolicyFixture : public LoadStringWithDirAnchor<Data, ReloadPolicy>
+{
+public:
+};
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateReload, Reload, ReloadedPolicies, ReloadPolicyFixture<Reload>)
+{
+ using Packet = Data;
+ Packet unsignedPacket("/Security/V2/ValidatorFixture/Sub1/Sub2/Packet");
+
+ boost::filesystem::remove(this->path / "keys" / "identity.ndncert");
+ this->advanceClocks(Reload::getRefreshTime(), 3);
+
+ Packet packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->identity));
+ VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");
+
+ packet = unsignedPacket;
+ this->m_keyChain.sign(packet, signingByIdentity(this->subIdentity));
+ VALIDATE_FAILURE(packet, "Should fail, as the trust anchor should no longer exist");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v2/validator-config/checker.t.cpp b/tests/unit-tests/security/v2/validator-config/checker.t.cpp
new file mode 100644
index 0000000..12af61b
--- /dev/null
+++ b/tests/unit-tests/security/v2/validator-config/checker.t.cpp
@@ -0,0 +1,374 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/checker.hpp"
+#include "security/command-interest-signer.hpp"
+#include "security/v2/validation-policy.hpp"
+#include "security/v2/validation-state.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+#include "../validator-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+class CheckerFixture : public IdentityManagementFixture
+{
+public:
+ CheckerFixture()
+ {
+ names.push_back("/foo/bar");
+ names.push_back("/foo/bar/bar");
+ names.push_back("/foo");
+ names.push_back("/other/prefix");
+ }
+
+ Name
+ makeSignedInterestName(const Name& name)
+ {
+ return Name(name).append("SignatureInfo").append("SignatureValue");
+ }
+
+ Name
+ makeKeyLocatorName(const Name& name)
+ {
+ return Name(name).append("KEY").append("v=1");
+ }
+
+public:
+ std::vector<Name> names;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestChecker, CheckerFixture)
+
+class NameRelationEqual : public CheckerFixture
+{
+public:
+ NameRelationEqual()
+ : checker("/foo/bar", NameRelation::EQUAL)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class NameRelationIsPrefixOf : public CheckerFixture
+{
+public:
+ NameRelationIsPrefixOf()
+ : checker("/foo/bar", NameRelation::IS_PREFIX_OF)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false}};
+};
+
+class NameRelationIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ NameRelationIsStrictPrefixOf()
+ : checker("/foo/bar", NameRelation::IS_STRICT_PREFIX_OF)
+ {
+ }
+
+public:
+ NameRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false}};
+};
+
+class RegexEqual : public CheckerFixture
+{
+public:
+ RegexEqual()
+ : checker(Regex("^<foo><bar>$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class RegexIsPrefixOf : public CheckerFixture
+{
+public:
+ RegexIsPrefixOf()
+ : checker(Regex("^<foo><bar><>*$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false},
+ {true, true, false, false}};
+};
+
+class RegexIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ RegexIsStrictPrefixOf()
+ : checker(Regex("^<foo><bar><>+$"))
+ {
+ }
+
+public:
+ RegexChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false},
+ {false, true, false, false}};
+};
+
+class HyperRelationEqual : public CheckerFixture
+{
+public:
+ HyperRelationEqual()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::EQUAL)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {false, true, false, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class HyperRelationIsPrefixOf : public CheckerFixture
+{
+public:
+ HyperRelationIsPrefixOf()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::IS_PREFIX_OF)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class HyperRelationIsStrictPrefixOf : public CheckerFixture
+{
+public:
+ HyperRelationIsStrictPrefixOf()
+ : checker("^(<>+)$", "\\1", "^(<>+)<KEY><>$", "\\1", NameRelation::IS_STRICT_PREFIX_OF)
+ {
+ }
+
+public:
+ HyperRelationChecker checker;
+ std::vector<std::vector<bool>> outcomes = {{false, false, true, false},
+ {true, false, true, false},
+ {false, false, false, false},
+ {false, false, false, false}};
+};
+
+class Hierarchical : public CheckerFixture
+{
+public:
+ Hierarchical()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type hierarchical
+ sig-type rsa-sha256
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+class CustomizedNameRelation : public CheckerFixture
+{
+public:
+ CustomizedNameRelation()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ name /foo/bar
+ relation equal
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class CustomizedRegex : public CheckerFixture
+{
+public:
+ CustomizedRegex()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ regex ^<foo><bar>$
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false},
+ {true, false, false, false}};
+};
+
+class CustomizedHyperRelation : public CheckerFixture
+{
+public:
+ CustomizedHyperRelation()
+ : checkerPtr(Checker::create(makeSection(R"CONF(
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ hyper-relation
+ {
+ k-regex ^(<>+)<KEY><>$
+ k-expand \\1
+ h-relation is-prefix-of
+ p-regex ^(<>+)$
+ p-expand \\1
+ }
+ }
+ )CONF"), "test-config"))
+ , checker(*checkerPtr)
+ {
+ }
+
+public:
+ std::unique_ptr<Checker> checkerPtr;
+ Checker& checker;
+
+ std::vector<std::vector<bool>> outcomes = {{true, false, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, false, true}};
+};
+
+
+using Tests = boost::mpl::vector<NameRelationEqual, NameRelationIsPrefixOf, NameRelationIsStrictPrefixOf,
+ RegexEqual, RegexIsPrefixOf, RegexIsStrictPrefixOf,
+ HyperRelationEqual, HyperRelationIsPrefixOf, HyperRelationIsStrictPrefixOf,
+ Hierarchical,
+ CustomizedNameRelation, CustomizedRegex, CustomizedHyperRelation>;
+
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Checks, T, Tests, T)
+{
+ BOOST_ASSERT(this->outcomes.size() == this->names.size());
+ for (size_t i = 0; i < this->names.size(); ++i) {
+ BOOST_ASSERT(this->outcomes[i].size() == this->names.size());
+ for (size_t j = 0; j < this->names.size(); ++j) {
+ const Name& pktName = this->names[i];
+ Name klName = this->makeKeyLocatorName(this->names[j]);
+ bool expectedOutcome = this->outcomes[i][j];
+
+ auto dataState = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->checker.check(tlv::Data, pktName, klName, dataState), expectedOutcome);
+ BOOST_CHECK_EQUAL(boost::logic::indeterminate(dataState->getOutcome()), expectedOutcome);
+ if (boost::logic::indeterminate(dataState->getOutcome()) == !expectedOutcome) {
+ BOOST_CHECK_EQUAL(dataState->getOutcome(), !expectedOutcome);
+ }
+
+ auto interestState = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->checker.check(tlv::Interest, this->makeSignedInterestName(pktName),
+ klName, interestState), expectedOutcome);
+ BOOST_CHECK_EQUAL(boost::logic::indeterminate(interestState->getOutcome()), expectedOutcome);
+ if (boost::logic::indeterminate(interestState->getOutcome()) == !expectedOutcome) {
+ BOOST_CHECK_EQUAL(interestState->getOutcome(), !expectedOutcome);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestChecker
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/conf/common.hpp b/tests/unit-tests/security/v2/validator-config/common.hpp
similarity index 62%
copy from src/security/conf/common.hpp
copy to tests/unit-tests/security/v2/validator-config/common.hpp
index 3c79b7b..4250718 100644
--- a/src/security/conf/common.hpp
+++ b/tests/unit-tests/security/v2/validator-config/common.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2014 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,35 +17,32 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
-#ifndef NDN_SECURITY_CONF_COMMON_HPP
-#define NDN_SECURITY_CONF_COMMON_HPP
+#ifndef NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+#define NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
-#include "../../common.hpp"
-#include <string>
-#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/info_parser.hpp>
namespace ndn {
namespace security {
-namespace conf {
+namespace v2 {
+namespace validator_config {
+namespace tests {
-typedef boost::property_tree::ptree ConfigSection;
-
-class Error : public std::runtime_error
+inline ConfigSection
+makeSection(const std::string& config)
{
-public:
- explicit
- Error(const std::string& what)
- : std::runtime_error(what)
- {
- }
-};
+ std::istringstream inputStream(config);
+ ConfigSection section;
+ boost::property_tree::read_info(inputStream, section);
+ return section;
+}
-} // namespace conf
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
} // namespace security
} // namespace ndn
-#endif // NDN_SECURITY_CONF_COMMON_HPP
+#endif // NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
diff --git a/tests/unit-tests/security/v2/validator-config/filter.t.cpp b/tests/unit-tests/security/v2/validator-config/filter.t.cpp
new file mode 100644
index 0000000..054b99a
--- /dev/null
+++ b/tests/unit-tests/security/v2/validator-config/filter.t.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/filter.hpp"
+#include "security/command-interest-signer.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+class FilterFixture : public IdentityManagementFixture
+{
+public:
+ Interest
+ makeSignedInterest(const Name& name)
+ {
+ Interest interest(name);
+ m_keyChain.sign(interest);
+ return interest;
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestFilter, FilterFixture)
+
+#define CHECK_FOR_MATCHES(filter, same, longer, shorter, different) \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo/bar").getName()), same); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo/bar").getName()), same); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo/bar/bar").getName()), longer); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo/bar/bar").getName()), longer); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/foo").getName()), shorter); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/foo").getName()), shorter); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Interest, makeSignedInterest("/other/prefix").getName()), different); \
+ BOOST_CHECK_EQUAL(filter.match(tlv::Data, Data("/other/prefix").getName()), different);
+
+BOOST_AUTO_TEST_CASE(RelationName)
+{
+ RelationNameFilter f1("/foo/bar", NameRelation::EQUAL);
+ CHECK_FOR_MATCHES(f1, true, false, false, false);
+
+ RelationNameFilter f2("/foo/bar", NameRelation::IS_PREFIX_OF);
+ CHECK_FOR_MATCHES(f2, true, true, false, false);
+
+ RelationNameFilter f3("/foo/bar", NameRelation::IS_STRICT_PREFIX_OF);
+ CHECK_FOR_MATCHES(f3, false, true, false, false);
+}
+
+BOOST_AUTO_TEST_CASE(RegexName)
+{
+ RegexNameFilter f1(Regex("^<foo><bar>$"));
+ CHECK_FOR_MATCHES(f1, true, false, false, false);
+
+ RegexNameFilter f2(Regex("^<foo><bar><>*$"));
+ CHECK_FOR_MATCHES(f2, true, true, false, false);
+
+ RegexNameFilter f3(Regex("^<foo><bar><>+$"));
+ CHECK_FOR_MATCHES(f3, false, true, false, false);
+}
+
+BOOST_FIXTURE_TEST_SUITE(Create, FilterFixture)
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ BOOST_CHECK_THROW(Filter::create(makeSection(""), "test-config"), Error);
+ BOOST_CHECK_THROW(Filter::create(makeSection("type unknown"), "test-config"), Error);
+ BOOST_CHECK_THROW(Filter::create(makeSection("type name"), "test-config"), Error);
+
+ std::string config = R"CONF(
+ type name
+ not-name-or-regex stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ not-relation stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation equal
+ not-end stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar>$
+ not-end stuff
+ )CONF";
+ BOOST_CHECK_THROW(Filter::create(makeSection(config), "test-config"), Error);
+}
+
+BOOST_AUTO_TEST_CASE(NameFilter)
+{
+ std::string config = R"CONF(
+ type name
+ name /foo/bar
+ relation equal
+ )CONF";
+ auto f1 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f1), true, false, false, false);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation is-prefix-of
+ )CONF";
+ auto f2 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f2), true, true, false, false);
+
+ config = R"CONF(
+ type name
+ name /foo/bar
+ relation is-strict-prefix-of
+ )CONF";
+ auto f3 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f3), false, true, false, false);
+}
+
+BOOST_AUTO_TEST_CASE(RegexFilter)
+{
+ std::string config = R"CONF(
+ type name
+ regex ^<foo><bar>$
+ )CONF";
+ auto f1 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f1), true, false, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar><>*$
+ )CONF";
+ auto f2 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f2), true, true, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<foo><bar><>+$
+ )CONF";
+ auto f3 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f3), false, true, false, false);
+
+ config = R"CONF(
+ type name
+ regex ^<>*$
+ )CONF";
+ auto f4 = Filter::create(makeSection(config), "test-config");
+ CHECK_FOR_MATCHES((*f4), true, true, true, true);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Create
+
+BOOST_AUTO_TEST_SUITE_END() // TestFilter
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v2/validator-config/name-relation.t.cpp b/tests/unit-tests/security/v2/validator-config/name-relation.t.cpp
new file mode 100644
index 0000000..cbe7084
--- /dev/null
+++ b/tests/unit-tests/security/v2/validator-config/name-relation.t.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/name-relation.hpp"
+
+#include "boost-test.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+BOOST_AUTO_TEST_SUITE(TestNameRelation)
+
+BOOST_AUTO_TEST_CASE(ToString)
+{
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::EQUAL), "equal");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::IS_PREFIX_OF),
+ "is-prefix-of");
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(NameRelation::IS_STRICT_PREFIX_OF),
+ "is-strict-prefix-of");
+}
+
+BOOST_AUTO_TEST_CASE(FromString)
+{
+ BOOST_CHECK_EQUAL(getNameRelationFromString("equal"), NameRelation::EQUAL);
+ BOOST_CHECK_EQUAL(getNameRelationFromString("is-prefix-of"), NameRelation::IS_PREFIX_OF);
+ BOOST_CHECK_EQUAL(getNameRelationFromString("is-strict-prefix-of"), NameRelation::IS_STRICT_PREFIX_OF);
+ BOOST_CHECK_THROW(getNameRelationFromString("unknown"), validator_config::Error);
+}
+
+BOOST_AUTO_TEST_CASE(CheckRelation)
+{
+ BOOST_CHECK(checkNameRelation(NameRelation::EQUAL, "/prefix", "/prefix"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::EQUAL, "/prefix", "/prefix/other"));
+
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix", "/prefix"));
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix", "/prefix/other"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_PREFIX_OF, "/prefix/other", "/prefix"));
+
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix", "/prefix"));
+ BOOST_CHECK(checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix", "/prefix/other"));
+ BOOST_CHECK(!checkNameRelation(NameRelation::IS_STRICT_PREFIX_OF, "/prefix/other", "/prefix"));
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestNameRelation
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v2/validator-config/rule.t.cpp b/tests/unit-tests/security/v2/validator-config/rule.t.cpp
new file mode 100644
index 0000000..6c2e631
--- /dev/null
+++ b/tests/unit-tests/security/v2/validator-config/rule.t.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "security/v2/validator-config/rule.hpp"
+
+#include "boost-test.hpp"
+#include "common.hpp"
+#include "identity-management-fixture.hpp"
+#include "../validator-fixture.hpp"
+
+#include <boost/mpl/vector_c.hpp>
+
+namespace ndn {
+namespace security {
+namespace v2 {
+namespace validator_config {
+namespace tests {
+
+using namespace ndn::tests;
+using namespace ndn::security::v2::tests;
+
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_AUTO_TEST_SUITE(V2)
+BOOST_AUTO_TEST_SUITE(ValidatorConfig)
+
+template<uint32_t PktType>
+class RuleFixture : public IdentityManagementFixture
+{
+public:
+ RuleFixture()
+ : rule(ruleId, PktType)
+ , pktName("/foo/bar")
+ {
+ if (PktType == tlv::Interest) {
+ pktName = Name("/foo/bar/SigInfo/SigValue");
+ }
+ }
+
+public:
+ const std::string ruleId = "rule-id";
+ Rule rule;
+ Name pktName;
+};
+
+using PktTypes = boost::mpl::vector_c<uint32_t, tlv::Data, tlv::Interest>;
+
+BOOST_AUTO_TEST_SUITE(TestRule)
+
+BOOST_FIXTURE_TEST_CASE(Errors, RuleFixture<tlv::Data>)
+{
+ BOOST_CHECK_THROW(rule.match(tlv::Interest, this->pktName), Error);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_THROW(rule.check(tlv::Interest, this->pktName, "/foo/bar", state), Error);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Constructor, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ BOOST_CHECK_EQUAL(this->rule.getId(), this->ruleId);
+ BOOST_CHECK_EQUAL(this->rule.getPktType(), PktType::value);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(EmptyRule, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), false);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Filters, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ this->rule.addFilter(make_unique<RegexNameFilter>(Regex("^<foo><bar>$")));
+
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, "/not" + this->pktName.toUri()), false);
+
+ this->rule.addFilter(make_unique<RegexNameFilter>(Regex("^<not><foo><bar>$")));
+
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(this->rule.match(PktType::value, "/not" + this->pktName.toUri()), true);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), false);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Checkers, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
+ "^<not>?(<>+)$", "\\1",
+ NameRelation::EQUAL));
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/not/foo/bar", state), true);
+
+ this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
+ "^(<>+)$", "\\1",
+ NameRelation::EQUAL));
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(this->rule.check(PktType::value, this->pktName, "/not/foo/bar", state), false);
+}
+
+BOOST_AUTO_TEST_SUITE(Create)
+
+BOOST_AUTO_TEST_CASE(Errors)
+{
+ BOOST_CHECK_THROW(Rule::create(makeSection(""), "test-config"), Error);
+
+ std::string config = R"CONF(
+ id rule-id
+ for something
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error);
+
+ config = R"CONF(
+ id rule-id
+ for data
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error); // at least one checker required
+
+ config = R"CONF(
+ id rule-id
+ for data
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+ other stuff
+ )CONF";
+ BOOST_CHECK_THROW(Rule::create(makeSection(config), "test-config"), Error);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(FilterAndChecker, PktType, PktTypes, RuleFixture<PktType::value>)
+{
+ std::string config = std::string("") + R"CONF(
+ id rule-id
+ for )CONF" + (PktType::value == tlv::Data ? "data" : "interest") + R"CONF(
+ filter
+ {
+ type name
+ regex ^<foo><bar>$
+ }
+ checker
+ {
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ hyper-relation
+ {
+ k-regex ^(<>+)$
+ k-expand \\1
+ h-relation equal
+ p-regex ^(<>+)$
+ p-expand \\1
+ }
+ }
+ }
+ )CONF";
+ auto rule = Rule::create(makeSection(config), "test-config");
+
+ BOOST_CHECK_EQUAL(rule->match(PktType::value, this->pktName), true);
+ BOOST_CHECK_EQUAL(rule->match(PktType::value, "/not" + this->pktName.toUri()), false);
+
+ auto state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(rule->check(PktType::value, this->pktName, "/foo/bar", state), true);
+
+ state = make_shared<DummyValidationState>();
+ BOOST_CHECK_EQUAL(rule->check(PktType::value, this->pktName, "/not/foo/bar", state), false);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Create
+
+BOOST_AUTO_TEST_SUITE_END() // TestRule
+BOOST_AUTO_TEST_SUITE_END() // ValidatorConfig
+BOOST_AUTO_TEST_SUITE_END() // V2
+BOOST_AUTO_TEST_SUITE_END() // Security
+
+} // namespace tests
+} // namespace validator_config
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit-tests/security/v2/validator-fixture.hpp b/tests/unit-tests/security/v2/validator-fixture.hpp
index fb7edda..7f52048 100644
--- a/tests/unit-tests/security/v2/validator-fixture.hpp
+++ b/tests/unit-tests/security/v2/validator-fixture.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -42,6 +42,7 @@
ValidatorFixture()
: face(io, {true, true})
, validator(make_unique<ValidationPolicy>(), make_unique<CertificateFetcher>(face))
+ , policy(static_cast<ValidationPolicy&>(validator.getPolicy()))
, cache(time::days(100))
{
processInterest = [this] (const Interest& interest) {
@@ -101,6 +102,7 @@
util::DummyClientFace face;
std::function<void(const Interest& interest)> processInterest;
Validator validator;
+ ValidationPolicy& policy;
CertificateCache cache;
@@ -144,6 +146,35 @@
#define VALIDATE_SUCCESS(packet, message) this->template validate(packet, message, true, __LINE__)
#define VALIDATE_FAILURE(packet, message) this->template validate(packet, message, false, __LINE__)
+class DummyValidationState : public ValidationState
+{
+public:
+ ~DummyValidationState()
+ {
+ m_outcome = false;
+ }
+
+ void
+ fail(const ValidationError& error) override
+ {
+ // BOOST_TEST_MESSAGE(error);
+ m_outcome = false;
+ }
+
+private:
+ void
+ verifyOriginalPacket(const Certificate& trustedCert) override
+ {
+ // do nothing
+ }
+
+ void
+ bypassValidation() override
+ {
+ // do nothing
+ }
+};
+
} // namespace tests
} // namespace v2
} // namespace security
diff --git a/tests/unit-tests/security/validator-config.t.cpp b/tests/unit-tests/security/validator-config.t.cpp
index e2fbda1..37f2cff 100644
--- a/tests/unit-tests/security/validator-config.t.cpp
+++ b/tests/unit-tests/security/validator-config.t.cpp
@@ -20,18 +20,12 @@
*/
#include "security/validator-config.hpp"
-#include "security/signing-helpers.hpp"
+#include "security/v2/certificate-fetcher-offline.hpp"
#include "util/dummy-client-face.hpp"
-#include "util/io.hpp"
-#include "util/scheduler.hpp"
-#include "lp/nack.hpp"
-#include "lp/tags.hpp"
#include "boost-test.hpp"
-#include "make-interest-data.hpp"
-#include "../identity-management-time-fixture.hpp"
-
-#include <boost/logic/tribool.hpp>
+#include "identity-management-fixture.hpp"
+#include "v2/validator-config/common.hpp"
namespace ndn {
namespace security {
@@ -40,1597 +34,85 @@
using namespace ndn::tests;
BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestValidatorConfig, IdentityManagementFixture)
-// Needed to create Face instance
-class ValidatorConfigFixture : public IdentityManagementV1TimeFixture
+// This test only for API, actual tests are in ValidationPolicyConfig and corresponding CertificateFetchers
+
+BOOST_AUTO_TEST_CASE(Construct)
+{
+ util::DummyClientFace face;
+
+ ValidatorConfig v1(face);
+ BOOST_CHECK_EQUAL(v1.m_policyConfig.m_isConfigured, false);
+
+ ValidatorConfig v2(make_unique<v2::CertificateFetcherOffline>());
+ BOOST_CHECK_EQUAL(v2.m_policyConfig.m_isConfigured, false);
+}
+
+class ValidatorConfigFixture : public IdentityManagementFixture
{
public:
ValidatorConfigFixture()
- : m_v2KeyChain("pib-memory:", "tpm-memory:")
- , face(nullptr, m_v2KeyChain)
- , validator(face)
+ : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "validator-config")
+ , validator(make_unique<v2::CertificateFetcherOffline>())
{
+ boost::filesystem::create_directories(path);
+ config = R"CONF(
+ trust-anchor
+ {
+ type any
+ }
+ )CONF";
+ configFile = (this->path / "config.conf").string();
+ std::ofstream f(configFile.c_str());
+ f << config;
+ }
+
+ ~ValidatorConfigFixture()
+ {
+ boost::filesystem::remove_all(path);
}
public:
- v2::KeyChain m_v2KeyChain;
- Face face;
+ const boost::filesystem::path path;
+ std::string config;
+ std::string configFile;
ValidatorConfig validator;
};
-BOOST_FIXTURE_TEST_SUITE(TestValidatorConfig, ValidatorConfigFixture)
+BOOST_FIXTURE_TEST_SUITE(Loads, ValidatorConfigFixture)
-BOOST_AUTO_TEST_CASE(NameFilter)
+BOOST_AUTO_TEST_CASE(FromFile)
{
- Name identity("/TestValidatorConfig/NameFilter");
- identity.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity), "trust-anchor-1.cert"));
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name dataName1("/simple/equal");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- Name dataName2("/simple/different");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity)));
-
- std::string CONFIG_1 =
- "rule\n"
- "{\n"
- " id \"Simple Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /simple/equal\n"
- " relation equal\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " name ";
-
- std::string CONFIG_2 =
- "\n"
- " relation equal\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-1.cert\"\n"
- "}\n";
- const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
+ validator.load(configFile);
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+ BOOST_CHECK_THROW(validator.load(configFile), std::logic_error);
}
-BOOST_AUTO_TEST_CASE(NameFilter2)
+BOOST_AUTO_TEST_CASE(FromString)
{
- Name identity("/TestValidatorConfig/NameFilter2");
- identity.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity), "trust-anchor-2.cert"));
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name dataName1("/simple/isPrefixOf");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- Name dataName2("/simple/notPrefixOf");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity)));
-
- Name dataName3("/simple/isPrefixOf/anotherLevel");
- shared_ptr<Data> data3 = make_shared<Data>(dataName3);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data3, security::signingByIdentity(identity)));
-
- std::string CONFIG_1 =
- "rule\n"
- "{\n"
- " id \"Simple2 Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /simple/isPrefixOf\n"
- " relation is-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " name ";
-
- std::string CONFIG_2 =
- "\n"
- " relation equal\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-2.cert\"\n"
- "}\n";
- const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*data3,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
+ validator.load(config, "config-file-from-string");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+ BOOST_CHECK_THROW(validator.load(configFile), std::logic_error);
}
-BOOST_AUTO_TEST_CASE(NameFilter3)
+BOOST_AUTO_TEST_CASE(FromIstream)
{
- Name identity("/TestValidatorConfig/NameFilter3");
- identity.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity), "trust-anchor-3.cert"));
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name dataName1("/simple/isStrictPrefixOf");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- Name dataName2("/simple");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity)));
-
- Name dataName3("/simple/isStrictPrefixOf/anotherLevel");
- shared_ptr<Data> data3 = make_shared<Data>(dataName3);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data3, security::signingByIdentity(identity)));
-
- std::string CONFIG_1 =
- "rule\n"
- "{\n"
- " id \"Simple3 Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /simple/isStrictPrefixOf\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " name ";
-
- std::string CONFIG_2 =
- "\n"
- " relation equal\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-3.cert\"\n"
- "}\n";
- const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*data3,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
+ std::istringstream is(config);
+ validator.load(is, "config-file-from-istream");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+ BOOST_CHECK_THROW(validator.load(configFile), std::logic_error);
}
-BOOST_AUTO_TEST_CASE(NameFilter4)
+BOOST_AUTO_TEST_CASE(FromSection)
{
- Name identity("/TestValidatorConfig/NameFilter4");
- identity.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity), "trust-anchor-4.cert"));
- Name certName = m_keyChain.getDefaultCertificateNameForIdentity(identity);
-
- Name dataName1("/simple/regex");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- Name dataName2("/simple/regex-wrong");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity)));
-
- Name dataName3("/simple/regex/correct");
- shared_ptr<Data> data3 = make_shared<Data>(dataName3);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data3, security::signingByIdentity(identity)));
-
- std::string CONFIG_1 =
- "rule\n"
- "{\n"
- " id \"Simple3 Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " regex ^<simple><regex>\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " name ";
-
- std::string CONFIG_2 =
- "\n"
- " relation equal\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-4.cert\"\n"
- "}\n";
- const std::string CONFIG = CONFIG_1 + certName.getPrefix(-1).toUri() + CONFIG_2;
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*data3,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
+ validator.load(v2::validator_config::tests::makeSection(config), "config-file-from-section");
+ BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
+ BOOST_CHECK_THROW(validator.load(configFile), std::logic_error);
}
-BOOST_AUTO_TEST_CASE(KeyLocatorNameChecker1)
-{
- Name identity("/TestValidatorConfig/KeyLocatorNameChecker1");
- identity.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity), "trust-anchor-5.cert"));
-
- Name dataName1 = identity;
- dataName1.append("1");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- Name dataName2 = identity;
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity)));
-
- Name dataName3("/TestValidatorConfig/KeyLocatorNameChecker1");
- shared_ptr<Data> data3 = make_shared<Data>(dataName3);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data3, security::signingByIdentity(identity)));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"Simple3 Rule\"\n"
- " for data\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " hyper-relation\n"
- " {\n"
- " k-regex ^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$\n"
- " k-expand \\\\1\\\\2\n"
- " h-relation is-strict-prefix-of\n"
- " p-regex ^(<>*)$\n"
- " p-expand \\\\1\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-5.cert\"\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*data3,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-}
-
-BOOST_AUTO_TEST_CASE(FixedSignerChecker)
-{
- Name identity("/TestValidatorConfig/FixedSignerChecker");
-
- Name identity1 = identity;
- identity1.append("1").appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity1), "trust-anchor-7.cert"));
-
- Name identity2 = identity;
- identity2.append("2").appendVersion();
- addIdentity(identity2);
-
- Name dataName1 = identity;
- dataName1.append("data").appendVersion();
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity1)));
-
- Name dataName2 = identity;
- dataName2.append("data").appendVersion();
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity2)));
-
- Name interestName("/TestValidatorConfig/FixedSignerChecker/fakeSigInfo/fakeSigValue");
- shared_ptr<Interest> interest = make_shared<Interest>(interestName);
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Data Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/FixedSignerChecker\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-7.cert\"\n"
- " }\n"
- " }\n"
- "}\n"
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Interest Rule\"\n"
- " for interest\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/FixedSignerChecker\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-7.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*interest,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
-}
-
-BOOST_AUTO_TEST_CASE(MultiCheckers)
-{
- Name identity1("/TestValidatorConfig/MultiCheckers/");
- identity1.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity1), "trust-anchor-multi-1.cert"));
-
- Name identity2("/TestValidatorConfig/");
- identity2.appendVersion();
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity2), "trust-anchor-multi-2.cert"));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"Simple Rule01\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /\n"
- " relation is-prefix-of\n"
- " }\n"
- " checker\n" // checker 1, signer should have prefix /TestValidatorConfig/MultiCheckers
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/MultiCheckers/\n"
- " relation is-prefix-of\n"
- " }\n"
- " }\n"
- " checker\n" // checker 2, data should have same prefix of its signer
- " {\n"
- " type hierarchical\n"
- " sig-type rsa-sha256\n"
- " }\n"
- " checker\n" // checker 3, the signer should be identity1
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-multi-1.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-multicheckers.conf"));
-
- ValidatorConfig validator;
- validator.load(CONFIG, CONFIG_PATH.c_str());
- conf::Checker& checker0 = *validator.m_dataRules.front()->m_checkers[0];
- conf::Checker& checker1 = *validator.m_dataRules.front()->m_checkers[1];
- conf::Checker& checker2 = *validator.m_dataRules.front()->m_checkers[2];
-
- auto data1 = makeData(Name(identity1).append("Test"));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity1)));
- BOOST_CHECK_EQUAL(checker0.check(*data1), 0);
- BOOST_CHECK_EQUAL(checker1.check(*data1), 0);
- BOOST_CHECK_EQUAL(checker2.check(*data1), 1);
-
- auto data2 = makeData(Name(identity2).append("Data2"));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(identity2)));
- BOOST_CHECK_EQUAL(checker0.check(*data2), -1);
- BOOST_CHECK_EQUAL(checker1.check(*data2), 0);
- BOOST_CHECK_EQUAL(checker2.check(*data2), -1);
-
- auto data3 = makeData(Name(identity2).append("Data3"));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data3, security::signingByIdentity(identity1)));
- BOOST_CHECK_EQUAL(checker0.check(*data3), 0);
- BOOST_CHECK_EQUAL(checker1.check(*data3), -1);
- BOOST_CHECK_EQUAL(checker2.check(*data3), 1);
-
- auto data4 = makeData("/Data4");
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data4, security::signingByIdentity(identity2)));
- BOOST_CHECK_EQUAL(checker0.check(*data4), -1);
- BOOST_CHECK_EQUAL(checker1.check(*data4), -1);
- BOOST_CHECK_EQUAL(checker2.check(*data4), -1);
-
- int count = 0;
- validator.validate(*data1,
- [&] (const shared_ptr<const Data>&) {
- BOOST_CHECK(true);
- count++;
- },
- [] (const shared_ptr<const Data>&, const std::string& str) { BOOST_CHECK(false); });
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [&] (const shared_ptr<const Data>&, const std::string& str) {
- BOOST_CHECK(true);
- count++;
- });
-
- validator.validate(*data3,
- [&] (const shared_ptr<const Data>&) {
- BOOST_CHECK(true);
- count++;
- },
- [] (const shared_ptr<const Data>&, const std::string& str) { BOOST_CHECK(false); });
-
- validator.validate(*data4,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [&] (const shared_ptr<const Data>&, const std::string& str) {
- BOOST_CHECK(true);
- count++;
- });
-
- BOOST_CHECK_EQUAL(count, 4);
-}
-
-BOOST_AUTO_TEST_CASE(Reset)
-{
- Name root("/TestValidatorConfig/Reload");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(root), "trust-anchor-8.cert"));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"NRD Prefix Registration Command Rule\"\n"
- " for interest\n"
- " filter\n"
- " {\n"
- " type name\n"
- " regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]<>$\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$\n"
- " }\n"
- " }\n"
- "}\n"
- "rule\n"
- "{\n"
- " id \"Testbed Hierarchy Rule\"\n"
- " for data\n"
- " filter\n"
- " {\n"
- " type name\n"
- " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$\n"
- " }\n"
- " checker\n"
- " {\n"
- " type hierarchical\n"
- " sig-type rsa-sha256\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-8.cert\"\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
- BOOST_CHECK_EQUAL(validator.isEmpty(), false);
-
- validator.reset();
- BOOST_CHECK(validator.isEmpty());
-}
-
-BOOST_AUTO_TEST_CASE(TrustAnchorWildcard)
-{
- Name identity("/TestValidatorConfig/Wildcard");
- identity.appendVersion();
- addIdentity(identity);
-
- Name dataName1("/any/data");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(identity)));
-
- std::string CONFIG =
- "trust-anchor\n"
- "{\n"
- " type any\n"
- "}\n";
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-}
-
-BOOST_AUTO_TEST_CASE(SignedInterestTest)
-{
- Name certName = addIdentity("/TestValidatorConfig/SignedInterestTest");
- BOOST_REQUIRE(saveIdentityCertificate(certName, "trust-anchor-9.cert"));
-
- Name interestName("/TestValidatorConfig/SignedInterestTest");
- Name interestName1 = interestName;
- interestName1.append("1");
- shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
- Name interestName2 = interestName;
- interestName2.append("2");
- shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
-
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest1, security::signingByCertificate(certName)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest2, security::signingByCertificate(certName)));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Interest Rule\"\n"
- " for interest\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/SignedInterestTest\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-9.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
- advanceClocks(time::milliseconds(10));
-}
-
-BOOST_AUTO_TEST_CASE(MaxKeyTest)
-{
- Name identity("/TestValidatorConfig/MaxKeyTest");
-
- Name identity1 = identity;
- identity1.append("Key1");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity1), "trust-anchor-10-1.cert"));
-
- Name identity2 = identity;
- identity2.append("Key2");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity2), "trust-anchor-10-2.cert"));
-
- Name identity3 = identity;
- identity3.append("Key3");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity3), "trust-anchor-10-3.cert"));
-
-
- Name interestName("/TestValidatorConfig/MaxKeyTest");
- Name interestName1 = interestName;
- interestName1.append("1");
- shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
- Name interestName2 = interestName;
- interestName2.append("2");
- shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
- Name interestName3 = interestName;
- interestName3.append("3");
- shared_ptr<Interest> interest3 = make_shared<Interest>(interestName3);
-
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest1, security::signingByIdentity(identity1)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest2, security::signingByIdentity(identity2)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest3, security::signingByIdentity(identity3)));
- advanceClocks(time::milliseconds(10));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Interest Rule\"\n"
- " for interest\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/MaxKeyTest\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-1.cert\"\n"
- " }\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-2.cert\"\n"
- " }\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-3.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- ValidatorConfig validator(face,
- ValidatorConfig::DEFAULT_CERTIFICATE_CACHE,
- ValidatorConfig::DEFAULT_GRACE_INTERVAL,
- 10,
- 2, // Two keys can be tracked
- time::seconds(1)); // TTL is set to 1 sec
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest3,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- // Should succeed because identity1's key has been cleaned up due to space limit.
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-}
-
-BOOST_AUTO_TEST_CASE(MaxKeyTest2)
-{
- Name identity("/TestValidatorConfig/MaxKeyTest");
-
- Name identity1 = identity;
- identity1.append("Key1");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity1), "trust-anchor-10-1.cert"));
-
- Name identity2 = identity;
- identity2.append("Key2");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity2), "trust-anchor-10-2.cert"));
-
- Name identity3 = identity;
- identity3.append("Key3");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity3), "trust-anchor-10-3.cert"));
-
- Name identity4 = identity;
- identity4.append("Key4");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(identity4), "trust-anchor-10-4.cert"));
-
-
- Name interestName("/TestValidatorConfig/MaxKeyTest");
- Name interestName1 = interestName;
- interestName1.append("1");
- shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
- Name interestName2 = interestName;
- interestName2.append("2");
- shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
- Name interestName3 = interestName;
- interestName3.append("3");
- shared_ptr<Interest> interest3 = make_shared<Interest>(interestName3);
- Name interestName4 = interestName;
- interestName4.append("4");
- shared_ptr<Interest> interest4 = make_shared<Interest>(interestName4);
-
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest1, security::signingByIdentity(identity1)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest2, security::signingByIdentity(identity2)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest3, security::signingByIdentity(identity3)));
- advanceClocks(time::milliseconds(10));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest4, security::signingByIdentity(identity4)));
- advanceClocks(time::milliseconds(10));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Interest Rule\"\n"
- " for interest\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/MaxKeyTest\n"
- " relation is-strict-prefix-of\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type rsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-1.cert\"\n"
- " }\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-2.cert\"\n"
- " }\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-3.cert\"\n"
- " }\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-10-4.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- ValidatorConfig validator(face,
- ValidatorConfig::DEFAULT_CERTIFICATE_CACHE,
- ValidatorConfig::DEFAULT_GRACE_INTERVAL,
- 10,
- 3, // Three keys can be tracked
- time::seconds(1)); // TTL is set to 1 sec
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest3,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest3,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
-
- advanceClocks(time::seconds(2));
-
- validator.validate(*interest4,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- // Should succeed because identity1 and identity2's key has been cleaned up due to ttl limit.
- validator.validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-
- validator.validate(*interest3,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10));
-}
-
-BOOST_AUTO_TEST_CASE(FixedSignerChecker2)
-{
- Name rsaIdentity("/TestValidatorConfig/FixedSignerChecker2/Rsa");
- addIdentity(rsaIdentity, RsaKeyParams());
-
- Name ecIdentity("/TestValidatorConfig/FixedSignerChecker2/Ec");
- auto identity = addIdentity(ecIdentity, EcKeyParams());
- BOOST_REQUIRE(saveIdentityCertificate(identity, "trust-anchor-11.cert"));
-
- Name dataName("/TestValidatorConfig/FixedSignerChecker2");
- shared_ptr<Data> dataRsa = make_shared<Data>(dataName);
- m_keyChain.sign(*dataRsa, security::signingByIdentity(rsaIdentity));
- shared_ptr<Data> dataEc = make_shared<Data>(dataName);
- m_keyChain.sign(*dataEc, security::signingByIdentity(ecIdentity));
-
- shared_ptr<Interest> interestRsa = make_shared<Interest>(dataName);
- m_keyChain.sign(*interestRsa, security::signingByIdentity(rsaIdentity));
- shared_ptr<Interest> interestEc = make_shared<Interest>(dataName);
- m_keyChain.sign(*interestEc, security::signingByIdentity(ecIdentity));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Data Rule\"\n"
- " for data\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/FixedSignerChecker2\n"
- " relation equal\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type ecdsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-11.cert\"\n"
- " }\n"
- " }\n"
- "}\n"
- "rule\n"
- "{\n"
- " id \"FixedSignerChecker Interest Rule\"\n"
- " for interest\n"
- " filter"
- " {\n"
- " type name\n"
- " name /TestValidatorConfig/FixedSignerChecker2\n"
- " relation equal\n"
- " }\n"
- " checker\n"
- " {\n"
- " type fixed-signer\n"
- " sig-type ecdsa-sha256\n"
- " signer\n"
- " {\n"
- " type file\n"
- " file-name \"trust-anchor-11.cert\"\n"
- " }\n"
- " }\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- validator.validate(*dataEc,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*dataRsa,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- validator.validate(*interestEc,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
-
- validator.validate(*interestRsa,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
-}
-
-
-struct FacesFixture : public ValidatorConfigFixture
-{
- FacesFixture()
- : face1(io, m_v2KeyChain, {true, true})
- , face2(io, m_v2KeyChain, {true, true})
- , readInterestOffset1(0)
- , readDataOffset1(0)
- , readInterestOffset2(0)
- , readDataOffset2(0)
- {
- }
-
- bool
- passPacket()
- {
- bool hasPassed = false;
-
- checkFace(face1.sentInterests, readInterestOffset1, face2, hasPassed);
- checkFace(face1.sentData, readDataOffset1, face2, hasPassed);
- checkFace(face2.sentInterests, readInterestOffset2, face1, hasPassed);
- checkFace(face2.sentData, readDataOffset2, face1, hasPassed);
-
- return hasPassed;
- }
-
- template<typename Packet>
- void
- checkFace(std::vector<Packet>& receivedPackets,
- size_t& readPacketOffset,
- util::DummyClientFace& receiver,
- bool& hasPassed)
- {
- while (receivedPackets.size() > readPacketOffset) {
- receiver.receive(receivedPackets[readPacketOffset]);
- readPacketOffset++;
- hasPassed = true;
- }
- }
-
-public:
- util::DummyClientFace face1;
- util::DummyClientFace face2;
-
- size_t readInterestOffset1;
- size_t readDataOffset1;
- size_t readInterestOffset2;
- size_t readDataOffset2;
-};
-
-BOOST_FIXTURE_TEST_CASE(HierarchicalChecker, FacesFixture)
-{
- std::vector<v1::CertificateSubjectDescription> subjectDescription;
-
- Name root("/TestValidatorConfig");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(root), "trust-anchor-6.cert"));
-
-
- Name sld("/TestValidatorConfig/HierarchicalChecker");
- addIdentity(sld);
- advanceClocks(time::milliseconds(100));
- Name sldKeyName = m_keyChain.generateRsaKeyPairAsDefault(sld, true);
- shared_ptr<v1::IdentityCertificate> sldCert =
- m_keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
- root,
- time::system_clock::now(),
- time::system_clock::now() + time::days(7300),
- subjectDescription);
- m_keyChain.sign(*sldCert, security::signingByIdentity(root));
- m_keyChain.addCertificateAsIdentityDefault(*sldCert);
-
- Name nld("/TestValidatorConfig/HierarchicalChecker/NextLevel");
- addIdentity(nld);
- advanceClocks(time::milliseconds(100));
- Name nldKeyName = m_keyChain.generateRsaKeyPairAsDefault(nld, true);
- shared_ptr<v1::IdentityCertificate> nldCert =
- m_keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
- sld,
- time::system_clock::now(),
- time::system_clock::now() + time::days(7300),
- subjectDescription);
- m_keyChain.sign(*nldCert, security::signingByIdentity(sld));
- m_keyChain.addCertificateAsIdentityDefault(*nldCert);
-
- face1.setInterestFilter(sldCert->getName().getPrefix(-1),
- [&] (const InterestFilter&, const Interest&) { face1.put(*sldCert); },
- RegisterPrefixSuccessCallback(),
- [] (const Name&, const std::string&) {});
-
- face1.setInterestFilter(nldCert->getName().getPrefix(-1),
- [&] (const InterestFilter&, const Interest&) { face1.put(*nldCert); },
- RegisterPrefixSuccessCallback(),
- [] (const Name&, const std::string&) {});
-
- Name dataName1 = nld;
- dataName1.append("data1");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(nld)));
-
- Name dataName2("/ConfValidatorTest");
- dataName2.append("data1");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(nld)));
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"Simple3 Rule\"\n"
- " for data\n"
- " checker\n"
- " {\n"
- " type hierarchical\n"
- " sig-type rsa-sha256\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-6.cert\"\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- auto validator = make_shared<ValidatorConfig>(&face2);
- validator->load(CONFIG, CONFIG_PATH.c_str());
-
- advanceClocks(time::milliseconds(2), 100);
- validator->validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-
- validator->validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-}
-
-BOOST_FIXTURE_TEST_CASE(Nrd, FacesFixture)
-{
- advanceClocks(time::nanoseconds(1));
-
- std::vector<v1::CertificateSubjectDescription> subjectDescription;
-
- Name root("/TestValidatorConfig");
- BOOST_REQUIRE(saveIdentityCertificate(addIdentity(root), "trust-anchor-8.cert"));
-
- Name sld("/TestValidatorConfig/Nrd-1");
- addIdentity(sld);
- advanceClocks(time::milliseconds(100));
- Name sldKeyName = m_keyChain.generateRsaKeyPairAsDefault(sld, true);
- shared_ptr<v1::IdentityCertificate> sldCert =
- m_keyChain.prepareUnsignedIdentityCertificate(sldKeyName,
- root,
- time::system_clock::now(),
- time::system_clock::now() + time::days(7300),
- subjectDescription);
- m_keyChain.sign(*sldCert, security::signingByIdentity(root));
- m_keyChain.addCertificateAsIdentityDefault(*sldCert);
-
- Name nld("/TestValidatorConfig/Nrd-1/Nrd-2");
- addIdentity(nld);
- advanceClocks(time::milliseconds(100));
- Name nldKeyName = m_keyChain.generateRsaKeyPairAsDefault(nld, true);
- shared_ptr<v1::IdentityCertificate> nldCert =
- m_keyChain.prepareUnsignedIdentityCertificate(nldKeyName,
- sld,
- time::system_clock::now(),
- time::system_clock::now() + time::days(7300),
- subjectDescription);
- m_keyChain.sign(*nldCert, security::signingByIdentity(sld));
- m_keyChain.addCertificateAsIdentityDefault(*nldCert);
-
- face1.setInterestFilter(sldCert->getName().getPrefix(-1),
- [&] (const InterestFilter&, const Interest&) { face1.put(*sldCert); },
- RegisterPrefixSuccessCallback(),
- [] (const Name&, const std::string&) {});
-
- face1.setInterestFilter(nldCert->getName().getPrefix(-1),
- [&] (const InterestFilter&, const Interest&) { face1.put(*nldCert); },
- RegisterPrefixSuccessCallback(),
- [] (const Name&, const std::string&) {});
-
- advanceClocks(time::milliseconds(10));
- Name interestName1("/localhost/nrd/register/option");
- shared_ptr<Interest> interest1 = make_shared<Interest>(interestName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest1, security::signingByIdentity(nld)));
-
- advanceClocks(time::milliseconds(10));
- Name interestName2("/localhost/nrd/non-register");
- shared_ptr<Interest> interest2 = make_shared<Interest>(interestName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest2, security::signingByIdentity(nld)));
-
- advanceClocks(time::milliseconds(10));
- Name interestName3("/localhost/nrd/register/option");
- shared_ptr<Interest> interest3 = make_shared<Interest>(interestName3);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest3, security::signingByIdentity(root)));
-
- advanceClocks(time::milliseconds(10));
- Name interestName4("/localhost/nrd/register/option/timestamp/nonce/fakeSigInfo/fakeSigValue");
- shared_ptr<Interest> interest4 = make_shared<Interest>(interestName4);
-
- const std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"NRD Prefix Registration Command Rule\"\n"
- " for interest\n"
- " filter\n"
- " {\n"
- " type name\n"
- " regex ^<localhost><nrd>[<register><unregister><advertise><withdraw>]<>$\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$\n"
- " }\n"
- " }\n"
- "}\n"
- "rule\n"
- "{\n"
- " id \"Testbed Hierarchy Rule\"\n"
- " for data\n"
- " filter\n"
- " {\n"
- " type name\n"
- " regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$\n"
- " }\n"
- " checker\n"
- " {\n"
- " type hierarchical\n"
- " sig-type rsa-sha256\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type file\n"
- " file-name \"trust-anchor-8.cert\"\n"
- "}\n";
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- auto validator = make_shared<ValidatorConfig>(&face2);
- validator->load(CONFIG, CONFIG_PATH.c_str());
-
- advanceClocks(time::milliseconds(2), 100);
-
- // should succeed
- validator->validate(*interest1,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-
- // should fail
- validator->validate(*interest2,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-
- // should succeed
- validator->validate(*interest3,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(false); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-
- // should fail
- validator->validate(*interest4,
- [] (const shared_ptr<const Interest>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Interest>&, const std::string&) { BOOST_CHECK(true); });
-
- do {
- advanceClocks(time::milliseconds(2), 10);
- } while (passPacket());
-}
-
-struct DirTestFixture : public ValidatorConfigFixture
-{
- DirTestFixture()
- : validator(&face, ValidatorConfig::DEFAULT_CERTIFICATE_CACHE,
- ValidatorConfig::DEFAULT_GRACE_INTERVAL, 0)
- {
- certDirPath = (boost::filesystem::current_path() / std::string("test-cert-dir"));
- boost::filesystem::create_directory(certDirPath);
-
- firstCertPath = (boost::filesystem::current_path() /
- std::string("test-cert-dir") /
- std::string("trust-anchor-1.cert"));
-
- secondCertPath = (boost::filesystem::current_path() /
- std::string("test-cert-dir") /
- std::string("trust-anchor-2.cert"));
-
- firstIdentity = Name("/TestValidatorConfig/Dir/First");
- addIdentity(firstIdentity);
- Name firstCertName = m_keyChain.getDefaultCertificateNameForIdentity(firstIdentity);
- firstCert = m_keyChain.getCertificate(firstCertName);
- io::save(*firstCert, firstCertPath.string());
-
- secondIdentity = Name("/TestValidatorConfig/Dir/Second");
- addIdentity(secondIdentity);
- Name secondCertName = m_keyChain.getDefaultCertificateNameForIdentity(secondIdentity);
- secondCert = m_keyChain.getCertificate(secondCertName);
- }
-
- ~DirTestFixture()
- {
- boost::filesystem::remove_all(certDirPath);
- }
-
-public:
- boost::filesystem::path certDirPath;
- boost::filesystem::path firstCertPath;
- boost::filesystem::path secondCertPath;
-
- Name firstIdentity;
- Name secondIdentity;
-
- shared_ptr<v1::IdentityCertificate> firstCert;
- shared_ptr<v1::IdentityCertificate> secondCert;
-
- ValidatorConfig validator;
-};
-
-BOOST_FIXTURE_TEST_CASE(TrustAnchorDir, DirTestFixture)
-{
- advanceClocks(time::milliseconds(10));
-
- Name dataName1("/any/data/1");
- shared_ptr<Data> data1 = make_shared<Data>(dataName1);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data1, security::signingByIdentity(firstIdentity)));
-
- Name dataName2("/any/data/2");
- shared_ptr<Data> data2 = make_shared<Data>(dataName2);
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*data2, security::signingByIdentity(secondIdentity)));
-
- std::string CONFIG =
- "rule\n"
- "{\n"
- " id \"Any Rule\"\n"
- " for data\n"
- " filter\n"
- " {\n"
- " type name\n"
- " regex ^<>*$\n"
- " }\n"
- " checker\n"
- " {\n"
- " type customized\n"
- " sig-type rsa-sha256\n"
- " key-locator\n"
- " {\n"
- " type name\n"
- " regex ^<>*$\n"
- " }\n"
- " }\n"
- "}\n"
- "trust-anchor\n"
- "{\n"
- " type dir\n"
- " dir test-cert-dir\n"
- " refresh 1s\n"
- "}\n";
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-nfd.conf"));
-
- validator.load(CONFIG, CONFIG_PATH.c_str());
-
- advanceClocks(time::milliseconds(10), 20);
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10), 20);
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(false); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(true); });
- advanceClocks(time::milliseconds(10), 20);
-
- io::save(*secondCert, secondCertPath.string());
- advanceClocks(time::milliseconds(10), 200);
-
- validator.validate(*data1,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10), 20);
-
- validator.validate(*data2,
- [] (const shared_ptr<const Data>&) { BOOST_CHECK(true); },
- [] (const shared_ptr<const Data>&, const std::string&) { BOOST_CHECK(false); });
- advanceClocks(time::milliseconds(10), 20);
-}
-
-class DirectCertFetchFixture : public ValidatorConfigFixture
-{
-public:
- DirectCertFetchFixture()
- : clientFace(io, m_v2KeyChain, {true, true})
- , validationResult(boost::logic::indeterminate)
- {
- auto certName = addIdentity(ca);
- saveIdentityCertificate(certName, "trust-anchor-1.cert");
- addSubCertificate(user, ca);
-
- userCertName = m_keyChain.getDefaultCertificateNameForIdentity(user);
- userCert = m_keyChain.getCertificate(userCertName);
- }
-
-protected:
- void
- runTest(const std::function<void(const Interest&, const Interest&)> respond)
- {
- optional<Interest> directInterest;
- optional<Interest> infrastructureInterest;
- clientFace.onSendInterest.connect([&] (const Interest& interest) {
- const Name& interestName = interest.getName();
- if (interestName == userCert->getName().getPrefix(-1)) {
- auto nextHopFaceIdTag = interest.getTag<lp::NextHopFaceIdTag>();
- if (nextHopFaceIdTag != nullptr) {
- BOOST_CHECK(!directInterest);
- directInterest = interest;
- }
- else {
- BOOST_CHECK(!infrastructureInterest);
- infrastructureInterest = interest;
- }
- if (static_cast<bool>(directInterest) && static_cast<bool>(infrastructureInterest)) {
- io.post([directInterest, infrastructureInterest, respond] {
- respond(directInterest.value(), infrastructureInterest.value());
- });
- directInterest = nullopt;
- infrastructureInterest = nullopt;
- }
- }
- });
-
- const boost::filesystem::path CONFIG_PATH =
- (boost::filesystem::current_path() / std::string("unit-test-direct.conf"));
- ValidatorConfig validator(&clientFace);
- validator.load(CONFIG, CONFIG_PATH.c_str());
- validator.setDirectCertFetchEnabled(true);
-
- shared_ptr<Interest> interest = make_shared<Interest>(interestName);
- interest->setTag(make_shared<lp::IncomingFaceIdTag>(123));
- BOOST_CHECK_NO_THROW(m_keyChain.sign(*interest, security::signingByIdentity(user)));
-
- validator.validate(*interest,
- [&] (const shared_ptr<const Interest>&) {
- BOOST_CHECK(boost::logic::indeterminate(validationResult));
- validationResult = true;
- },
- [&] (const shared_ptr<const Interest>&, const std::string& s) {
- BOOST_CHECK(boost::logic::indeterminate(validationResult));
- validationResult = false;
- });
-
- advanceClocks(time::milliseconds(200), 60);
-
- BOOST_CHECK(!boost::logic::indeterminate(validationResult));
- }
-
-public:
- util::DummyClientFace clientFace;
- const Name ca = Name("/DirectCertFetch");
- const Name user = Name("/DirectCertFetch/user");
- const Name interestName = Name("/DirectCertFetch/user/tag-interest");
- const std::string CONFIG = R"_TEXT_(
- rule
- {
- id "RuleForInterest"
- for interest
- checker
- {
- type hierarchical
- sig-type rsa-sha256
- }
- }
- rule
- {
- id "RuleForData"
- for data
- filter
- {
- type name
- regex ^<>*$
- }
- checker
- {
- type customized
- sig-type rsa-sha256
- key-locator
- {
- type name
- regex ^<>*$
- }
- }
- }
- trust-anchor
- {
- type file
- file-name "trust-anchor-1.cert"
- }
- )_TEXT_";
- boost::logic::tribool validationResult;
- Name userCertName;
- shared_ptr<v1::IdentityCertificate> userCert;
-};
-
-BOOST_FIXTURE_TEST_SUITE(DirectCertFetch, DirectCertFetchFixture)
-
-BOOST_AUTO_TEST_CASE(CertFetchSuccess)
-{
- runTest([this] (const Interest& directInterest, const Interest& infrastructureInterest) {
- this->clientFace.receive(*userCert);
- });
-
- BOOST_CHECK_EQUAL(validationResult, true);
-}
-
-BOOST_AUTO_TEST_CASE(CertFetchTimeout)
-{
- // In this test case, certificate request would time out
- runTest([this] (const Interest& directInterest, const Interest& infrastructureInterest) { });
-
- BOOST_CHECK_EQUAL(validationResult, false);
-}
-
-BOOST_AUTO_TEST_CASE(CertFetchNack)
-{
- runTest([this] (const Interest& directInterest, const Interest& infrastructureInterest) {
- lp::Nack nackInfrastructureInterest(infrastructureInterest);
- nackInfrastructureInterest.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
- this->clientFace.receive(nackInfrastructureInterest);
- });
-
- BOOST_CHECK_EQUAL(validationResult, false);
-}
+BOOST_AUTO_TEST_SUITE_END() // Loads
-BOOST_AUTO_TEST_SUITE_END() // DirectCertFetch
BOOST_AUTO_TEST_SUITE_END() // TestValidatorConfig
BOOST_AUTO_TEST_SUITE_END() // Security
diff --git a/tests/unit-tests/util/placeholders.t.cpp b/tests/unit-tests/util/placeholders.t.cpp
index 032b088..64c1dbf 100644
--- a/tests/unit-tests/util/placeholders.t.cpp
+++ b/tests/unit-tests/util/placeholders.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2015 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -24,9 +24,9 @@
// interest.hpp includes common.hpp; common.hpp shouldn't be used from external program
#include "interest.hpp"
-// validator-config.hpp indirectly includes <boost/property_tree/ptree.hpp>
+// util/config-file.hpp indirectly includes <boost/property_tree/ptree.hpp>
// which in turn imports Boost placeholders
-#include "security/validator-config.hpp"
+#include "util/config-file.hpp"
// It's intentional to write "using namespace",
// to simulate an external program linked against ndn-cxx.