Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various components ... #135

Open
wants to merge 64 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2413b82
repo: scaffolding
pulsejet Feb 27, 2025
26f8339
repo: basic non-snapshot
pulsejet Feb 27, 2025
c4517c2
repo: refactor register error log
pulsejet Feb 27, 2025
2da3b63
svs: fix alo quit
pulsejet Feb 27, 2025
d7450e4
repo: disable route inheritance
pulsejet Feb 27, 2025
9a53bdd
repo: fetch snap
pulsejet Mar 1, 2025
1949e2d
store: implement badger
pulsejet Mar 1, 2025
496f51a
store: remove bolt
pulsejet Mar 1, 2025
c88d686
stoe: eliminate version
pulsejet Mar 1, 2025
83835e9
std: update storejs
pulsejet Mar 1, 2025
27229bd
repo: add store log
pulsejet Mar 1, 2025
d2f1c8a
Merge branch 'repo' of https://github.com/named-data/ndnd into repo
pulsejet Mar 1, 2025
d991e8a
dv: support local cost
pulsejet Mar 1, 2025
4e62540
dv: revert hash change
pulsejet Mar 1, 2025
018501b
std: fix repo gitignore
pulsejet Mar 1, 2025
6856a98
fw: exclude non-routes from fib
pulsejet Mar 1, 2025
4593843
svs: change naming convention (break dv)
pulsejet Mar 1, 2025
9b3998d
svs: fix examples
pulsejet Mar 1, 2025
2864f4c
dv: fix for new svs
pulsejet Mar 1, 2025
b7ea527
e2e: force nfdc with nfd
pulsejet Mar 1, 2025
7a58cb2
svs: minor example modernize
pulsejet Mar 1, 2025
4f6d009
repo: join group command
pulsejet Mar 2, 2025
35366ad
repo: reduce suppression time
pulsejet Mar 2, 2025
9a788f4
std: client announce API
pulsejet Mar 2, 2025
37fa1ca
std: move examples and tools to announce API
pulsejet Mar 2, 2025
2f6490c
std: send svs si on face up
pulsejet Mar 2, 2025
49229dd
repo: expose announcement
pulsejet Mar 2, 2025
14b3ab6
std: modernize lvs
pulsejet Mar 4, 2025
3f98391
Merge branch 'repo' of https://github.com/named-data/ndnd into repo
pulsejet Mar 4, 2025
b40a0f9
std: refactor storage
pulsejet Mar 4, 2025
6a696b8
std: fix face hook race
pulsejet Mar 4, 2025
49531e5
std: fix svs examples docs
pulsejet Mar 7, 2025
b242bf5
std: add test case for non-sig field
pulsejet Mar 7, 2025
4d2fde3
codegen: make encoder length public
pulsejet Mar 7, 2025
dc2847a
codegen: preserve imports
pulsejet Mar 7, 2025
c52f4fa
std: move svs defns
pulsejet Mar 7, 2025
4984180
std: split spec definitions
pulsejet Mar 7, 2025
e6614a5
dv: fix withdraw reply
pulsejet Mar 7, 2025
1c11f8c
std: implement cross-schema
pulsejet Mar 7, 2025
fa78a91
std: cross schema extra checks
pulsejet Mar 7, 2025
77fd6f9
tools: add expose flag to pingserver
pulsejet Mar 10, 2025
cae7769
fw: implement best route retransmission
pulsejet Mar 10, 2025
a5fd35a
repo: fix types
pulsejet Mar 10, 2025
84e4055
repo: implement BlobFetch
pulsejet Mar 10, 2025
04a1044
cross: append segment component
pulsejet Mar 10, 2025
52f265d
cross: optionally store schema
pulsejet Mar 10, 2025
b8bfa40
repo: blob fetch direct store
pulsejet Mar 11, 2025
7790169
repo: increase logging verbosity
pulsejet Mar 11, 2025
016bb0e
cross: add freshness
pulsejet Mar 11, 2025
8de564b
sec: add marshal utility
pulsejet Mar 11, 2025
770584f
cmd: log improvement
pulsejet Mar 11, 2025
e31604a
Merge branch 'main' into repo
pulsejet Mar 12, 2025
1ab4e8d
all: cert fetch forwarding hint
pulsejet Mar 13, 2025
c19fa82
svs: fix boot time
pulsejet Mar 13, 2025
8737dc6
svs: refactor alo
pulsejet Mar 13, 2025
5be2ac3
Merge branch 'repo' of https://github.com/named-data/ndnd into repo
pulsejet Mar 13, 2025
27a7b6a
svs-alo: add multicast prefix option
pulsejet Mar 13, 2025
2b89b1e
repo: support multicast prefix
pulsejet Mar 13, 2025
ec1f3ec
repo: fix mcast announcement
pulsejet Mar 13, 2025
505b5a5
client: prevent deadlock
pulsejet Mar 13, 2025
637ff3a
repo: fetch certs
pulsejet Mar 13, 2025
1b4fc3c
ndncert: fix validity
pulsejet Mar 13, 2025
6b10227
std: make UseDataNameFwHint fine grained
pulsejet Mar 14, 2025
537d6cb
svs: add seq no api
pulsejet Mar 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/gondn_tlv_gen
/gondn_tlv_gen.exe
coverage.out
/db-*/

# Go wasm files
wasm_exec.js
Expand Down
18 changes: 18 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
dv "github.com/named-data/ndnd/dv/cmd"
fw "github.com/named-data/ndnd/fw/cmd"
"github.com/named-data/ndnd/repo"
"github.com/named-data/ndnd/std/utils"
"github.com/named-data/ndnd/tools"
"github.com/named-data/ndnd/tools/dvc"
Expand Down Expand Up @@ -38,6 +39,7 @@ func init() {
CmdNDNd.AddCommand(cmdFw())
CmdNDNd.AddCommand(cmdDv())
CmdNDNd.AddCommand(cmdDaemon)
CmdNDNd.AddCommand(cmdRepo())

CmdNDNd.AddGroup(&cobra.Group{ID: "sec", Title: "Security Tools"})
CmdNDNd.AddCommand(sec.CmdSec())
Expand Down Expand Up @@ -99,3 +101,19 @@ Reference:

return cmdDv
}

func cmdRepo() *cobra.Command {
cmdRepo := &cobra.Command{
Use: "repo",
Short: "NDN Data Repository",
Long: `Named Data Networking Data Repository`,
GroupID: "daemons",
}

cmdRepo.AddGroup(&cobra.Group{ID: "run", Title: "NDN Data Repository Daemon"})
repo.CmdRepo.Use = "run CONFIG-FILE"
repo.CmdRepo.Short = "Start the NDN Data Repository Daemon"
cmdRepo.AddCommand(repo.CmdRepo)

return cmdRepo
}
131 changes: 131 additions & 0 deletions docs/cross-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Cross-Namespace Verification Schema

This is the specification for the `CrossSchema` field in NDN Data.
The `CrossSchema` field is used to verify that a given key is allowed to sign a Data in a different namespace.

## TLV Specification

```abnf
CrossSchema = CROSS-SCHEMA-TYPE TLV-LENGTH Data

; Content of the Data in the CrossSchema field
CrossSchemaContent = *SimpleSchemaRule
*PrefixSchemaRule

SimpleSchemaRule = SIMPLE-SCHEMA-RULE-TYPE TLV-LENGTH
NamePrefix
KeyLocator

PrefixSchemaRule = PREFIX-SCHEMA-RULE-TYPE TLV-LENGTH
NamePrefix

NamePrefix = Name

CROSS-SCHEMA-TYPE = 600
SIMPLE-SCHEMA-RULE-TYPE = 620
PREFIX-SCHEMA-RULE-TYPE = 622
```

## Usage of `CrossSchema`

When an application wants to invite a user `U` in a different namespace to produce data under its namespace, it produces a `CrossSchema` Data and makes it available to `U`. The `CrossSchema` Data contains a list of rules that specify which keys are allowed to sign Data under the namespace of the application.

When `U` wants to sign a Data under the namespace of the application, it includes the `CrossSchema` Data in the Data packet. The verifier first verifies the `CrossSchema` itself, then uses the rules to verify the original Data.

### Example

Suppose the initiator `I` of an application instance has the prefix `/ucla.edu/`.
The application instance uses the prefix `/ucla.edu/wksp/`.

`I` is bootstrapped with the certificates:

1. `/ucla.edu/KEY/kid/iss/ver` signed by a chain ending in the trust anchor.
2. `/ucla.edu/wksp/KEY/kid/iss/ver` signed by `/ucla.edu/KEY/kid/iss/ver`.

`I` now wants to invite `/arizona.edu/alice` to produce data under the prefix `/ucla.edu/wksp/arizona.edu/alice/`. `I` creates the following `CrossSchema` Data:

```ini
Name = /ucla.edu/wksp/32=INVITE/arizona.edu/alice/v=1741157654
Content = SimpleSchemaRule {
NamePrefix = /ucla.edu/wksp/arizona.edu/alice/
KeyLocator = /arizona.edu/alice/KEY
}
KeyLocator = /ucla.edu/wksp/KEY/kid/iss/ver
```

Alice is now bootstrapped with the certificate `/arizona.edu/alice/KEY/kid/iss/ver` signed by a chain ending in the trust anchor.

Alice generates a new key and certificate to produce data under the invite prefix:

```ini
Name = /ucla.edu/wksp/arizona.edu/alice/KEY/kid/iss/ver
Content = <pubkey>
KeyLocator = /arizona.edu/alice/KEY/kid/iss/ver
CrossSchema = <data-of> /ucla.edu/wksp/32=INVITE/arizona.edu/alice/v=1741157654
```

Now Alice can generate data under the prefix

```ini
Name = /ucla.edu/wksp/arizona.edu/alice/t=1741157214/seq=1/seg=0
Content = <data>
Signature = <signature>
KeyLocator = /ucla.edu/wksp/arizona.edu/alice/KEY/kid/iss/ver
```

On receiving this data, the verifier takes the following steps:

1. Verify the signature of the data.
1. Use trust schmea to check if the KeyLocator certificate is allowed to sign the data.
1. Fetch the certificate (`/ucla.edu/wksp/arizona.edu/alice/KEY/kid/iss/ver`)
1. Verify the signature on the certificate.
1. Use trust schema to check if the certificate is allowed to sign the data (`no`).
1. At this point, the verifier notes that the certificate has a `CrossSchema` field.
1. Fetch the KeyLocator certificate of the `CrossSchema` Data and verify the chain.
1. Apply each rule in the `CrossSchema` Data to the original Data, and use trust schema to check if the certificate is allowed to sign the data (`yes`).
1. Verify the `CrossSchema` Data signature. Apply the trust schema to the original data name and the `CrossSchema` Data name.
1. Verify the rest of the chain.
1. The data is accepted.

## Specified Rules

The following rules are specified in the `CrossSchema` Data:

### SimpleSchemaRule

A SimpleSchemaRule specifies that a key is allowed to sign Data under a specific prefix.

For example, the following rule specifies that the key `/arizona.edu/alice/KEY` is allowed to sign Data under the prefix `/ucla.edu/wksp/arizona.edu/alice/`:

```ini
Content = SimpleSchemaRule {
NamePrefix = /ucla.edu/wksp/arizona.edu/alice/
KeyLocator = /arizona.edu/alice/KEY
}
```

When verifying the application Data, the verifier:

1. Checks if `NamePrefix` is a prefix of the Data name. If yes, continue; otherwise, reject.
2. Checks if `KeyLocator` is a prefix of the KeyLocator in the Data. If yes, accept; otherwise, reject.

### PrefixSchemaRule

A PrefixSchemaRule specifies that any key is allowed to sign data when prepended with the given prefix.

For example, consider the following rule:

```ini
Content = PrefixSchemaRule {
NamePrefix = /ucla.edu/wksp/open/
}
```

1. `/arizona.edu/alice/KEY` is allowed to sign Data under the prefix `/ucla.edu/wksp/open/arizona.edu/alice/`.
1. `/memphis.edu/bob/KEY` is allowed to sign Data under the prefix `/ucla.edu/wksp/open/memphis.edu/bob/`.
1. `/wustl.edu/carol/sub/KEY` is allowed to sign Data under the prefix `/ucla.edu/wksp/open/wustl.edu/carol/sub/`.

During verification, the verifier:

1. Checks if `NamePrefix` is a prefix of the Data name. If yes, continue; otherwise, reject.
1. Checks if the `KeyName` appears after `NamePrefix` in the Data name. If yes, accept; otherwise, reject.
25 changes: 17 additions & 8 deletions dv/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ This page describes the protocol specification of NDN Distance Vector Routing (n
## 2. Format and Naming

```
Advertisement Sync (active) = /localhop/<network>/32=DV/32=ADS/32=ACT
Advertisement Sync (passive) = /localhop/<network>/32=DV/32=ADS/32=PSV
Advertisement Broadcast Interest = /localhop/<network>/32=DV/32=ADS/32=ACT
Advertisement Broadcast Interest = /localhop/<network>/32=DV/32=ADS/32=PSV
Advertisement Broadcast Data = /localhop/<router>/32=DV/32=ADV/32=SYNC
Advertisement Data = /localhop/<router>/32=DV/32=ADV/t=<boot>/v=<seq>
Prefix Sync group = /<network>/32=DV/32=PFS
Prefix Data = /<router>/32=DV/32=PFX/t=<boot>/seq=<seq>/v=0
Prefix Snapshot = /<router>/32=DV/32=PFX/t=<boot>/32=SNAP/v=<seq>
Prefix Group SVS = /<network>/32=DV/32=PFS/32=svs
Prefix Data = /<network>/32=DV/32=PFS/<router>/t=<boot>/seq=<seq>/v=0
Prefix Snapshot = /<network>/32=DV/32=PFS/<router>/t=<boot>/32=SNAP/v=<seq>

<router> = router's unique name in the network
<network> = globally unique network prefix
Expand Down Expand Up @@ -105,16 +106,16 @@ Notes:
1. If the advertisement changes, the router increments the sequence number for the *Advertisement Sync* group.
1. Neighbor is considered dead if no update is received for the `RouterDeadInterval` period.

### Advertisement Sync
### Advertisement Broadcast

ndn-dv uses a local variant of SVS v2 for advertisement synchronization
ndn-dv uses a local variant of SVS v3 for advertisement broadcast. The name of the Interest and encapsulated Data (in ApplicationParameters) are provided in the format and naming section.

1. Each router maintains a local sequence number that is incremented when the advertisement changes.
1. Sync Interests are encoded identical to SVS, but the state vector ONLY contains the router's own sequence number.
1. Sync Interests are propagated only one hop, using `localhop` and a `HopLimit` of 2.
1. On receiving a Sync Interest, the router updates the sequence number for the sending neighbor.
1. However, the outgoing state vector does not change, and always only contains the router itself.
1. The incoming face of a Advertisement Sync Interest is used to set up data routes to neighbors.
1. The incoming face of a Advertisement Broadcast Interest is used to set up data routes to neighbors.

To allow for asymmetric face configurations, two types of Sync Interests are used:

Expand Down Expand Up @@ -178,3 +179,11 @@ The FIB is configured based on the RIB state and the global prefix table.

1. When a prefix destination has multiple exit routers, the router chooses the exit
router that it can reach with the lowest cost.

### Security

The LightVerSec policy for ndn-dv is described in [config/schema.trust](./config/schema.trust).

All routers must have a unique name configured in the network, and a global common network name. ndn-dv data is signed using the router's key, which in turn is signed by the network key (trust anchor).

When fetching certificates, the name of the data being verified MUST be attached as a forwarding hint to all certificate Interests in the chain.
33 changes: 10 additions & 23 deletions dv/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import (
mgmt "github.com/named-data/ndnd/std/ndn/mgmt_2022"
)

// CostInfinity is the maximum cost to a router.
const CostInfinity = uint64(16)

// CostPfxInfinity is the maximum cost to a name prefix.
const CostPfxInfinity = uint64(0xFFFFFFFF)

// NlsrOrigin is the origin to use for local registration.
const NlsrOrigin = uint64(mgmt.RouteOriginNLSR)

var MulticastStrategy = enc.LOCALHOST.
Expand Down Expand Up @@ -48,12 +54,8 @@ type Config struct {
advSyncPassivePfxN enc.Name
// Advertisement Data Prefix
advDataPfxN enc.Name
// Universal router data prefix
routerDataPfxN enc.Name
// Prefix Table Sync Prefix
pfxSyncPfxN enc.Name
// Prefix Table Data Prefix
pfxDataPfxN enc.Name
pfxSyncGroupPfxN enc.Name
// NLSR readvertise prefix
mgmtPrefix enc.Name
// Trust anchor names
Expand Down Expand Up @@ -149,17 +151,10 @@ func (c *Config) Parse() (err error) {
Append(enc.NewKeywordComponent("ADV"))

// Prefix table sync prefix
c.pfxSyncPfxN = c.networkNameN.
c.pfxSyncGroupPfxN = c.networkNameN.
Append(enc.NewKeywordComponent("DV")).
Append(enc.NewKeywordComponent("PFS"))

// Router data prefix including prefix data and certificates
c.routerDataPfxN = c.routerNameN.
Append(enc.NewKeywordComponent("DV"))
c.pfxDataPfxN = c.routerNameN.
Append(enc.NewKeywordComponent("DV")).
Append(enc.NewKeywordComponent("PFX"))

// Local prefixes to NFD
c.mgmtPrefix = enc.LOCALHOST.
Append(enc.NewGenericComponent("nlsr"))
Expand Down Expand Up @@ -191,16 +186,8 @@ func (c *Config) AdvertisementDataPrefix() enc.Name {
return c.advDataPfxN
}

func (c *Config) RouterDataPrefix() enc.Name {
return c.routerDataPfxN
}

func (c *Config) PrefixTableSyncPrefix() enc.Name {
return c.pfxSyncPfxN
}

func (c *Config) PrefixTableDataPrefix() enc.Name {
return c.pfxDataPfxN
func (c *Config) PrefixTableGroupPrefix() enc.Name {
return c.pfxSyncGroupPfxN
}

func (c *Config) MgmtPrefix() enc.Name {
Expand Down
Binary file modified dv/config/schema.tlv
Binary file not shown.
12 changes: 5 additions & 7 deletions dv/config/schema.trust
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
// Router name from config
#router: #network/router

// Advertisement Sync
#adv_svs: /"localhop"/#network/"32=DV"/"32=ADS"/type & { type: "32=ACT"|"32=PSV" } <= #router_cert
// Advertisement data
#adv_data: /"localhop"/#router/"32=DV"/"32=ADV"/_ <= #router_cert
// Advertisement data and broadcast
#advertisement_data: /"localhop"/#router/"32=DV"/"32=ADV"/_ <= #router_cert

// Prefix table Sync
#pfx_svs: #network/"32=DV"/"32=PFS" <= #router_cert
// Prefix table Sync group
#prefix_table: #network/"32=DV"/"32=PFS"
// Prefix table data
#pfx_data: #router/#pfx_svs/_/_ <= #router_cert
#prefix_table_data: #prefix_table/#router/_/_ <= #router_cert

// Certificate definitions
#network_cert: #network/#KEY
Expand Down
20 changes: 10 additions & 10 deletions dv/dv/advert_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/named-data/ndnd/std/ndn"
spec "github.com/named-data/ndnd/std/ndn/spec_2022"
spec_svs "github.com/named-data/ndnd/std/ndn/svs/v3"
"github.com/named-data/ndnd/std/object"
"github.com/named-data/ndnd/std/object/storage"
"github.com/named-data/ndnd/std/types/optional"
"github.com/named-data/ndnd/std/utils"
)
Expand All @@ -23,7 +23,7 @@ type advertModule struct {
// advertisement sequence number for self
seq uint64
// object directory for advertisement data
objDir *object.MemoryFifoDir
objDir *storage.MemoryFifoDir
}

func (a *advertModule) String() string {
Expand All @@ -46,10 +46,7 @@ func (a *advertModule) sendSyncInterest() (err error) {
return err
}

func (a *advertModule) sendSyncInterestImpl(prefix enc.Name) (err error) {
// SVS v3 Sync Data
syncName := prefix.Append(enc.NewVersionComponent(3))

func (a *advertModule) sendSyncInterestImpl(syncName enc.Name) (err error) {
// State Vector for our group
sv := &spec_svs.SvsData{
StateVector: &spec_svs.StateVector{
Expand All @@ -64,16 +61,18 @@ func (a *advertModule) sendSyncInterestImpl(prefix enc.Name) (err error) {
}

// Sign the Sync Data
signer := a.dv.client.SuggestSigner(syncName)
dataName := a.dv.config.AdvertisementDataPrefix().
Append(enc.NewKeywordComponent("SYNC"))
signer := a.dv.client.SuggestSigner(dataName)
if signer == nil {
return fmt.Errorf("no signer found for %s", syncName)
return fmt.Errorf("no signer found for %s", dataName)
}

// Make Data packet
dataCfg := &ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
}
data, err := a.dv.engine.Spec().MakeData(syncName, dataCfg, sv.Encode(), signer)
data, err := a.dv.engine.Spec().MakeData(dataName, dataCfg, sv.Encode(), signer)
if err != nil {
log.Error(nil, "Failed make data", "err", err)
return
Expand Down Expand Up @@ -126,7 +125,8 @@ func (a *advertModule) OnSyncInterest(args ndn.InterestHandlerArgs, active bool)
CertNextHop: args.IncomingFaceId,
Callback: func(valid bool, err error) {
if !valid || err != nil {
log.Warn(a, "Failed to validate signature", "name", data.Name(), "valid", valid, "err", err)
log.Warn(a, "Failed to validate advert broadcast",
"name", data.Name(), "valid", valid, "err", err)
return
}

Expand Down
Loading
Loading