blob: 905c0874a3f540ba529428836567ebf9405759ca [file] [log] [blame]
Validator Configuration File Format
===================================
You can set up a ``Validator`` via a configuration file. Next, we will
show you how to write a configuration file.
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.
::
rule
{
id "Simple Rule"
for data
filter
{
type name
name /localhost/example
relation is-prefix-of
}
checker
{
type customized
sig-type rsa-sha256
key-locator
{
type name
name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
relation equal
}
}
}
rule
{
id "Testbed Validation Rule"
for data
checker
{
type hierarchical
sig-type rsa-sha256
}
}
trust-anchor
{
type file
file-name "testbed-trust-anchor.cert"
}
- \ **ATTENTION: The order of rules MATTERS!**\
A rule can be broken into two parts:
- The first part is to qualify packets to which the rule can be
applied;
- 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.
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.
Rules in general
----------------
A rule has four types of properties: **id**, **for**, **filter**, and
**checker**.
The property **id** 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.
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.
- \ **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 treated as a valid packet. A rule must have at least
one **checker** property, a packet is treated as invalid if it cannot
pass none of the 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.
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
::
filter
{
type name
name /localhost/example
relation equal
}
shall only capture a packet with the exact name "/localhost/example".
And a filter
::
filter
{
type name
name /localhost/example
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
::
filter
{
type name
name /localhost/example
relation is-strict-prefix-of
}
shall capture a packet with name "/localhost/example/data", but cannot
catch a packet with name "/localhost/example".
The second way is to specify an [[Regex\|NDN Regular Expression]] that
can match the packet. In this case, only one property **regex** is
required. For example, a filter
::
filter
{
type name
regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
}
shall capture all the identity 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 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.
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.
::
checker
{
type customized
sig-type ...
key-locator
{
...
}
}
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 **key-locator** which 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**:
::
key-locator
{
type name
...
}
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:
::
checker
{
type customized
sig-type rsa-sha256
key-locator
{
type name
name /ndn/edu/ucla/KEY/yingdi/ksk-1234/ID-CERT
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".
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
For example, a checker:
::
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 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
}
}
}
Hierarchical Checker
~~~~~~~~~~~~~~~~~~~~
As implied by its name, hierarchical checker requires that the packet
name must be under the namespace of the packet signer. A hierarchical
checker:
::
checker
{
type hierarchical
sig-type rsa-sha256
}
is equivalent to a customized checker:
::
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
}
}
}
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
{
type file
file-name "trusted-signer.cert"
}
trust-anchor
{
type base64
base64-string "Bv0DGwdG...amHFvHIMDw=="
}
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 ``/usr/local/etc/ndn/keys``.
::
trust-anchor
{
type dir
file-name /usr/local/etc/ndn/keys
}
If certificates under the directory might be changed during runtime, you can
set a refresh period, such as
::
trust-anchor
{
type dir
file-name /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 in config file,
packet validation will be turned off.
- **ATTENTION: This type of trust anchor is dangerous.
You should used it only when you want to disable packet validation temporarily
(e.g, debugging code, building a demo).**
::
trust-anchor
{
type any
}
Example Configuration For NLSR
------------------------------
The trust model of NLSR is semi-hierarchical. An example certificate
signing hierarchy is:
::
root
|
+--------------+---------------+
site1 site2
| |
+---------+---------+ +
operator1 operator2 operator3
| | |
+-----+-----+ +----+-----+ +-----+-----+--------+
router1 router2 router3 router4 router5 router6 router7
| | | | | | |
+ + + + + + +
NLSR NSLR NSLR NSLR NSLR NSLR NSLR
However, entities name may not follow the signing hierarchy, for
example:
+------------+-------------------------------------------------------------------------------------+
| Entity | Identity name and examples |
+============+=====================================================================================+
| root | ``/<network>`` |
| | |
| | Identity example: ``/ndn`` |
| | |
| | Certificate name example: ``/ndn/KEY/ksk-1/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| site | ``/<network>/<site>`` |
| | |
| | Identity example: ``/ndn/edu/ucla`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/KEY/ksk-2/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| operator | ``/<network>/<site>/%C1.O.N./<operator-id>`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.N./op1`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.N./op1/KEY/ksk-3/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| router | ``/<network>/<site>/%C1.O.R./<router-id>`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/KEY/ksk-4/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| NLSR | ``/<network>/<site>/%C1.O.R./<router-id>/NLSR`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/KEY/ksk-5/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
Assume that a typical NLSR data name is
``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/LSA/LSType.1/%01``. Then, the exception
of naming hierarchy is "operator-router". So we can write a
configuration file with three rules. The first one is a customized rule
that capture the normal NLSR data. The second one is a customized rule
that handles the exception case of the hierarchy (operator->router). And
the last one is a hierarchical rule that handles the normal cases of the
hierarchy.
We put the NLSR data rule to the first place, because NLSR data packets
are the most frequently checked. The hierarchical exception rule is put
to the second, because it is more specific than the last one.
And here is the configuration file:
::
rule
{
id "NSLR LSA Rule"
for data
filter
{
type name
regex ^[^<NLSR><LSA>]*<NLSR><LSA>
}
checker
{
type customized
sig-type rsa-sha256
key-locator
{
type name
hyper-relation
{
k-regex ^([^<KEY>]*)<KEY><ksk-.*><ID-CERT>$
k-expand \\1
h-relation equal
p-regex ^([^<NLSR><LSA>]*)<NLSR><LSA><LSType\.\d><>$
p-expand \\1
}
}
}
}
rule
{
id "NSLR Hierarchy Exception Rule"
for data
filter
{
type name
regex ^[^<KEY><%C1.O.R.>]*<%C1.O.R.><><KEY><ksk-.*><ID-CERT><>$
}
checker
{
type customized
sig-type rsa-sha256
key-locator
{
type name
hyper-relation
{
k-regex ^([^<KEY><%C1.O.N.>]*)<%C1.O.N.><><KEY><ksk-.*><ID-CERT>$
k-expand \\1
h-relation equal
p-regex ^([^<KEY><%C1.O.R.>]*)<%C1.O.R.><><KEY><ksk-.*><ID-CERT><>$
p-expand \\1
}
}
}
}
rule
{
id "NSLR Hierarchical 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"
}
Example Configuration For NRD
-----------------------------
Assume NRD allows any valid testbed certificate to register prefix, the
configuration file could be written as:
::
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"
}