Project

General

Profile

Feature #2237

Remote prefix registration: fetch certificates from requester

Added by Alex Afanasyev over 5 years ago. Updated 8 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
RIB
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:
3.00 h

Description

The certificate signing a remote registration command may be available only at the machine issuing the command.

This creates a chicken-and-egg problem: to verify command NFD-RIB needs to fetch the cert, to fetch the cert the prefix should be already registered.

To solve this problem: NFD-RIB's validator should send two Interests at the same time, first one to the requester (using NextHopFaceId) and second one to the infrastructure (without NextHopFaceId).


Related issues

Blocked by ndn-cxx - Task #3289: Validator RefactoringClosedAlex Afanasyev10/26/2015

Actions
#1

Updated by Junxiao Shi over 5 years ago

  • Subject changed from Remote prefix registration: certificate fetching issue to Remote prefix registration: fetch certificates from requester
  • Description updated (diff)

client-control strategy should be set precisely for certificate Name, instead of the prefix being registered. Otherwise, ongoing traffic toward another laptop who registered the same prefix would be disrupted.

It's better not to start this Task until #1941 closes, to avoid potential code conflicts.

#2

Updated by Junxiao Shi over 5 years ago

  • Blocks Feature #2201: Remote prefix registration test scenario added
#3

Updated by Junxiao Shi over 5 years ago

There is a security problem if certificates Interests are sent to the requester only:

  1. suppose Alice owns identity ndn:/example/alice, which is trusted by the gateway router
  2. Alice signs a certificate ndn:/example/alice/KEY/chat/nrd/ksk-1418232105/ID-CERT/%FD%01, in order to register prefix ndn:/example/alice/chat
  3. the key ndn:/example/alice/KEY/chat/nrd/ksk-1418232105 is compromised
  4. Alice revokes the certificate from step 2, and publishes the revocation at a always-on, globally routable repository
  5. Eve sends a remote prefix registration command of prefix ndn:/example/alice/chat using ndn:/example/alice/KEY/chat/nrd/ksk-1418232105/ID-CERT/%FD%01
  6. Eve would answer Interests for the certificate, but won't answer Interests for the revocation
  7. when the gateway router fetches the certificate, those Interests are sent to Eve only, thus the gateway is unable to discover that the certificate has been revoked

To fix this problem: gateway router can fetch the certificate from the requester, but should also fetch the revocation separately without specifying NextHopFaceId.

#4

Updated by Junxiao Shi over 5 years ago

  • Blocks deleted (Feature #2201: Remote prefix registration test scenario)
#5

Updated by Junxiao Shi over 5 years ago

  • Tracker changed from Task to Feature
  • Target version deleted (v0.3)

20150119 conference call decides that in short term, we could keep nfd-autoreg so that certificates can be fetched through Routes installed by autoreg.
Thus, this Feature isn't critical.

In long term, nfd-autoreg should be disabled, because after the owner of /example/site/user goes offline, Interests under this prefix would be forwarded to other laptops which don't need them.

#6

Updated by Junxiao Shi almost 5 years ago

  • Assignee set to Haitao Zhang
  • Target version set to v0.4
  • Estimated time set to 3.00 h
#7

Updated by Alex Afanasyev over 4 years ago

  • Target version changed from v0.4 to v0.5
#8

Updated by Junxiao Shi over 3 years ago

nfd-autoreg for site prefixes has been disabled in #3568, with the understanding that every certificate must be reachable.

However, it's clearly desirable for an end host to be able to publish its own sub-certificate, rather than relying on a "parent authority", which might be offline, to publish them.
So it's time to revisit this proposal.

I notice two problems in fetching certificates from requester.

First, the requester must have a full certificate chain.
NFD-RIB on the router cannot distinguish whether a certificate should come from the requester or from the infrastructure, and it would send all certificate retrieval Interest to the requester.
There isn't an existing tool for easily collecting the full certificate chain, although publishing certificates is supported by ndn-pib.

Second, this mechanism opens a door for cache poisoning.
A malicious user can send a prefix registration command claimed to be signed by a certificate with victim's name, and then return invalid Data for the certificate retrieval Interest.

To fix those problems, NextHopFaceId should be used only if there isn't already a matching RIB entry for the certificate name, and the certificate retrieved with NextHopFaceId should not be cached (this needs forwarding changes).

#9

Updated by Junxiao Shi over 3 years ago

  • Assignee deleted (Haitao Zhang)

20160913 call discussed note-8 first problem.
Solution is: the validator can send out two Interests, first one to the requester (using NextHopFaceId) and second one to the infrastructure (without NextHopFaceId), at the same time, so that the certificate (or bundle) can be retrieved from either source.

#10

Updated by Junxiao Shi over 3 years ago

  • Description updated (diff)

During 20161004 call, Junxiao's opinion is that this needs to wait after #3289 in order to avoid conflicts. However, only people more familiar with Validator can make a decision.

#11

Updated by Junxiao Shi over 3 years ago

  • Assignee set to Zhiyi Zhang
  • Target version changed from v0.5 to v0.6

20161006 call decides to assign this to Zhiyi.

#12

Updated by Zhiyi Zhang over 3 years ago

I have not been into quite detail of NFD, so don't know much about what is going on there.

  • Do you have some suggestions to help me get into that part quickly?
  • Also should the change be made in the NFD or NDN-cxx? (Alex suggests the implementation can be in ndn-cxx for now)
#13

Updated by Junxiao Shi over 3 years ago

Should the change be made in the NFD or ndn-cxx?

This would involve a Validator subclass which is in ndn-cxx, and the usage of such validator which is in NFD.

Changing or extending the existing ValidatorConfig may not be the best idea. Something similar to nfd::CommandAuthenticator is an alternative.

#14

Updated by Zhiyi Zhang over 3 years ago

Based on the talk with Junxiao on Friday afternoon, here I have some unsolved implementation details :

  • Should we just add a sub class of validator for NFD to support the feature or we can do update to existing validator so that we can add the feature by adding a simple item in the config file. For the latter one, we can add a parameter in Config Validator's API which has a default value so we don't need to change the existing code.
  • Should we finish the validator refactor first or finish 2237 first.
  • If we decide to finish 2237 first, I can finish if after the NDN retreat, which is on the first week of Nov. I think this should take at least two weeks.
#15

Updated by Junxiao Shi over 3 years ago

Should we just add a sub class of validator for NFD to support the feature or we can do update to existing validator so that we can add the feature by adding a simple item in the config file. For the latter one, we can add a parameter in Config Validator's API which has a default value so we don't need to change the existing code.

My suggestion is to reuse the existing Validator and ValidatorConfig, rather than creating a new Validator subclass.
Note: the design below assumes the Validator API before #3289; I don't know the API after refactoring.

API

class Validator
{
public:
  /** \brief cause the validator to send directed Interests for certificate retrievals
   *
   *  The validator retrieves signing certificates by expressing Interests.
   *  Normally, the Interests are forwarded according to NFD's FIB.
   *
   *  When directed Interests feature is enabled, the validator can attempt to retrieve certificates from the source of the packet under validation.
   *  Specifically, when the Interest/Data passed to \p validate is tagged with IncomingFaceId, the validator expresses each certificate retrieval Interest twice, the first is a directed Interest tagged with NextHopFaceId toward the incoming face, and the second is a normal Interest without NextHopFaceId tag.
   *  This allows the validator to retrieve certificates from either the incoming face, without requiring FIB entries, or the infrastructure, following FIB entries
   */
  void
  enableDirectedInterest();
};

Calling code example

auto validator = make_unique<ValidatorConfig>(&face);
validator->enableDirectedInterest();

Rationale of making changes on Validator base class as opposed to ValidatorConfig: certificate retrieval is implemented in Validator::afterCheckPolicy function rather than ValidatorConfig.

Rationale of adding a method as opposed to a constructor parameter: ValidatorConfig already have six constructor parameters; having too many constructor parameters decreases code readability, while calling a method is more expressive. Also, the feature is implemented in Validator base class, and adding a method allows calling code of any Validator subclass to utilize this feature.

#16

Updated by Alex Afanasyev over 3 years ago

I'm not sure changing the base class of Validator is a good idea. "Directed" fetching is really a very special use case that applies to NFD's prefix registration. Are there any other use cases when a validator would be used in this way?

#17

Updated by Junxiao Shi over 3 years ago

Reply to note-16:

The procedure of expressing Interests to fetch certificates is hard-coded in Validator base class. Therefore, some changes in the base class is unavoidable.
On the other hand, expressing two Interests simultaneously, and more importantly being able to take the first incoming Data but ignore the second result (instead of reporting an error when an Interest times out or gets Nacked) would bring considerable complexity into Validator, which is an argument against putting it into the base class.

#18

Updated by Zhiyi Zhang over 3 years ago

Expressing two interests simultaneously would bring complexity: suppose one interest got nack back and the other fetch the certificate back. It is hard for validator to wait for all the results and then make a decision.

From my perspective, the feature may be implemented in this way: Adding a function to the Nack Callback and Timeout Callback, which means two interests are not simultaneously but one after one.
The process may be like:

  1. Validator first tries to fetch certificate from infrastructure.
  2. If it fetches a certificate, go on the validation.
  3. If it gets Nack or Timeout, the validator will try to fetch cert from requester. In this case, we can over write the base class's virtual functions: onNack() and onTimeout() in the subclass.
#19

Updated by Junxiao Shi over 3 years ago

The alternate proposed in note-18 (send one Interest to infrastructure, wait for timeout or Nack, and resend to requester) was discussed in 20160913 call and has been expressly rejected because it increases command execution latency. Thus, this shall proceed with note-9 solution regardless of implementation complexity.

#20

Updated by Junxiao Shi over 3 years ago

Expressing two interests simultaneously would bring complexity: suppose one interest got nack back and the other fetch the certificate back. It is hard for validator to wait for all the results and then make a decision.

20161108 call believes this statement does not sufficiently describe why note-9 solution is difficult to implement. Can you elaborate?

#21

Updated by Zhiyi Zhang over 3 years ago

  • Status changed from New to In Progress
#22

Updated by Zhiyi Zhang over 3 years ago

  • Status changed from In Progress to Code review
#23

Updated by Zhiyi Zhang over 3 years ago

DummyClientFace cannot handle Interest Tag: I send an interest through DummyClientFace but the tag is missing in the onInterest callback.

#24

Updated by Junxiao Shi over 3 years ago

Reply to note-23:

Please post a snippet to reproduce the problem.

#25

Updated by Zhiyi Zhang over 3 years ago

In the test for ValidatorConf, I generated an interest packet with NextHopFaceIdTag, and express it using DummyClientFace. After invoking DummyClientFace.recieve(), the onInterest callback was called, however in the onInterest callback, there was no NextHopFaceIdTag nor IncomingFaceIdTag in the interest packet from parameter. The pseudo code is like:

DummyClientFace face;
face.setFilter(prefix, [&](const Interest& interest) {
                                          auto tag1 = interest.getTag<NextHopFaceIdTag>();
                                          BOOST_CHECK(tag1 == nullptr);
                                          auto tag2 = interest.getTag< IncomingFaceIdTag >();
                                          BOOST_CHECK(tag2 == nullptr);
                                          } , registerSuccessCallback)
Interest i;
i.setTag<NextHopFaceIdTag>(123);
face.express(i, other parameters);
advanceIOServiceTime();

In the onInterest callback, there is no tag in interest.

#26

Updated by Zhiyi Zhang over 3 years ago

Still the problem : where to implement the feature, in the base Validator or the ValidatorConf.

One thing is if we put the new feature in base class, anyone who wants to define a new validator from the base class needs to support this feature in the their code. On the other hand if we put the feature in the child class, every child class who wants to support the feature needs to implement the feature separately.

My design is to implement the feature in base class and add a new function, then every child class can invoke a function before adding ValidationRequest to nextSteps and then it can support the new feature.

#27

Updated by Junxiao Shi over 3 years ago

https://gerrit.named-data.net/3319 patchset21 has a problematic design:

class Validator
{
private:
  /**
   * ValidationRequest Interest Name => status code.
   *
   * Only used for Direct Cert Fetch.
   * Direct Cert Fetch will send two interests, one of which has a NextHopFaceIdTag.
   *   status code = 0 indicates there is timeout nor nack for the two interests.
   *   status code = 1 indicates one interest got a final timeout or nack.
   *   status code = 2 indicates both interests got a final timeout or nack.
   *
   * The map entry will be removed when any interest fetch a data back.
   */
  std::map<Name, uint8_t> m_directCertFetchStatus;
};

In case of Nacks from both requester and infrastructure, this design would cause every validation request to be kept until Interest timeout rather than Nack arrival.

  • Direct cert fetch sends two Interests with same name to NFD. The first directInterest is tagged with NextHopFaceId, and the second infrastructureInterest does not have this tag. They must have different Nonces, or otherwise NFD would drop the second Interest.
  • When both request and infrastructure return Nacks, NFD would return only one Nack to the application (validator). This Nack carries the last Nonce coming from the application, which would be infrastructureInterest's Nonce.
  • When ndn-cxx Face receives a Nack, it invokes the callback on the PendingInterest record with exactly same Interest packet, which means NackCallback of infrastructureInterest would be invoked, but NackCallback of directInterest would not be invoked.

The solution to this problem lies within ndn-cxx Face rather than validator. Specifically, Face::Impl::nackPendingInterests should invoke NackCallback on all PendingInterest records with matching name+Selectors+Link, and should not require the Nonce to be same.

After applying the above solution, validator may simply pass one set of callbacks, which will be invoked regardless of which Interest gets answered (it's indistinguishable in the application).

face.expressInterest(directFetchInterest,
  handleCertData,
  handleCertFetchNack,
  handleCertFetchTimeout);
face.expressInterest(infrastructureInterest,
  nullptr,
  nullptr,
  nullptr);

A major flaw of having m_directCertFetchStatus is that it can lead to concurrency problem:

  1. (time=0s) interest1 signed by certA is presented for validation; validator expresses two Interests to fetch certA
  2. (time=3s) interest2 signed by certA is presented for validation; validator expresses two Interests to fetch certA, which have same name as the two Interests from step1
  3. (time=4s) the two Interests from step1 times out, which increments m_directCertFetchStatus[certA] to 2; validator fails interest1 validation and erases m_directCertFetchStatus[certA]
  4. now it's unclear whether m_directCertFetchStatus[certA] refers to the certificate retrieval for interest1 or interest2 validation
#28

Updated by Zhiyi Zhang over 3 years ago

So for next step, I should change the face logic first or someone else do the change?

#29

Updated by Alex Afanasyev over 3 years ago

  • Status changed from Code review to Closed
  • % Done changed from 0 to 100
#30

Updated by Alex Afanasyev over 3 years ago

  • Project changed from NFD to ndn-cxx
  • Category deleted (RIB)
  • Target version deleted (v0.6)
#31

Updated by Junxiao Shi over 3 years ago

  • Project changed from ndn-cxx to NFD
  • Category set to RIB
  • Status changed from Closed to Feedback
  • Target version set to v0.6
  • % Done changed from 100 to 60

https://gerrit.named-data.net/3319 allows ValidatorConfig to retrieve certificate from requester. This feature must be explicitly enabled.
Thus, a Change in NFD-RIB is needed to enable that feature, which is also the goal of this issue.

#32

Updated by Zhiyi Zhang over 3 years ago

  • Blocked by Task #3289: Validator Refactoring added
#33

Updated by Davide Pesavento over 2 years ago

  • Target version changed from v0.6 to v0.7
#37

Updated by Davide Pesavento 8 months ago

  • Status changed from Feedback to Closed
  • % Done changed from 60 to 100

Also available in: Atom PDF