1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-29 01:12:24 +08:00

namesys: differentiate between validation errors

License: MIT
Signed-off-by: Dirk McCormick <dirkmdev@gmail.com>
This commit is contained in:
Dirk McCormick
2018-01-31 00:37:39 -05:00
parent e980e68f86
commit dbedee5940
4 changed files with 78 additions and 6 deletions

View File

@ -2,6 +2,7 @@ package namesys
import ( import (
"context" "context"
"fmt"
"testing" "testing"
"time" "time"
@ -21,7 +22,62 @@ import (
ci "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto" ci "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
) )
func TestValidation(t *testing.T) { func testValidatorCase(t *testing.T, priv ci.PrivKey, kbook pstore.KeyBook, ns string, key string, val []byte, eol time.Time, exp error) {
validChecker := NewIpnsRecordValidator(kbook)
p := path.Path("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")
entry, err := CreateRoutingEntryData(priv, p, 1, eol)
if err != nil {
t.Fatal(err)
}
data := val
if data == nil {
data, err = proto.Marshal(entry)
if err != nil {
t.Fatal(err)
}
}
rec := &record.ValidationRecord{
Namespace: ns,
Key: key,
Value: data,
}
err = validChecker.Func(rec)
if err != exp {
params := fmt.Sprintf("namespace: %s\nkey: %s\neol: %s\n", ns, key, eol)
if exp == nil {
t.Fatalf("Unexpected error %s for params %s", err, params)
} else if err == nil {
t.Fatalf("Expected error %s but there was no error for params %s", exp, params)
} else {
t.Fatalf("Expected error %s but got %s for params %s", exp, err, params)
}
}
}
func TestValidator(t *testing.T) {
ts := time.Now()
priv, id, _, _ := genKeys(t)
priv2, id2, _, _ := genKeys(t)
kbook := pstore.NewPeerstore()
kbook.AddPubKey(id, priv.GetPublic())
emptyKbook := pstore.NewPeerstore()
testValidatorCase(t, priv, kbook, "ipns", string(id), nil, ts.Add(time.Hour), nil)
testValidatorCase(t, priv, kbook, "ipns", string(id), nil, ts.Add(time.Hour*-1), ErrExpiredRecord)
testValidatorCase(t, priv, kbook, "ipns", string(id), []byte("bad data"), ts.Add(time.Hour), ErrBadRecord)
testValidatorCase(t, priv, kbook, "ipns", "bad key", nil, ts.Add(time.Hour), ErrKeyFormat)
testValidatorCase(t, priv, emptyKbook, "ipns", string(id), nil, ts.Add(time.Hour), ErrPublicKeyNotFound)
testValidatorCase(t, priv2, kbook, "ipns", string(id2), nil, ts.Add(time.Hour), ErrPublicKeyNotFound)
testValidatorCase(t, priv2, kbook, "ipns", string(id), nil, ts.Add(time.Hour), ErrSignature)
testValidatorCase(t, priv, kbook, "", string(id), nil, ts.Add(time.Hour), ErrInvalidPath)
testValidatorCase(t, priv, kbook, "wrong", string(id), nil, ts.Add(time.Hour), ErrInvalidPath)
}
func TestResolverValidation(t *testing.T) {
ctx := context.Background() ctx := context.Background()
rid := testutil.RandIdentityOrFatal(t) rid := testutil.RandIdentityOrFatal(t)
dstore := dssync.MutexWrap(ds.NewMapDatastore()) dstore := dssync.MutexWrap(ds.NewMapDatastore())

View File

@ -147,7 +147,9 @@ func (r *routingResolver) resolveOnce(ctx context.Context, name string) (path.Pa
return "", err return "", err
} }
// use the routing system to get the name. // Use the routing system to get the name.
// Note that the DHT will call the ipns validator when retrieving
// the value, which in turn verifies the ipns record signature
_, ipnsKey := IpnsKeysForID(pid) _, ipnsKey := IpnsKeysForID(pid)
val, err := r.routing.GetValue(ctx, ipnsKey) val, err := r.routing.GetValue(ctx, ipnsKey)
if err != nil { if err != nil {

View File

@ -42,11 +42,13 @@ func selectRecord(recs []*pb.IpnsEntry, vals [][]byte) (int, error) {
} else if r.GetSequence() == bestSeq { } else if r.GetSequence() == bestSeq {
rt, err := u.ParseRFC3339(string(r.GetValidity())) rt, err := u.ParseRFC3339(string(r.GetValidity()))
if err != nil { if err != nil {
log.Errorf("failed to parse ipns record EOL %s", r.GetValidity())
continue continue
} }
bestt, err := u.ParseRFC3339(string(recs[besti].GetValidity())) bestt, err := u.ParseRFC3339(string(recs[besti].GetValidity()))
if err != nil { if err != nil {
log.Errorf("failed to parse ipns record EOL %s", recs[besti].GetValidity())
continue continue
} }

View File

@ -29,6 +29,18 @@ var ErrInvalidPath = errors.New("record path invalid")
// signature verification // signature verification
var ErrSignature = errors.New("record signature verification failed") var ErrSignature = errors.New("record signature verification failed")
// ErrBadRecord should be returned when an ipns record cannot be unmarshalled
var ErrBadRecord = errors.New("record could not be unmarshalled")
// ErrKeyFormat should be returned when an ipns record key is
// incorrectly formatted (not a peer ID)
var ErrKeyFormat = errors.New("record key could not be parsed into peer ID")
// ErrPublicKeyNotFound should be returned when the public key
// corresponding to the ipns record path cannot be retrieved
// from the peer store
var ErrPublicKeyNotFound = errors.New("public key not found in peer store")
// NewIpnsRecordValidator returns a ValidChecker for IPNS records // NewIpnsRecordValidator returns a ValidChecker for IPNS records
// The validator function will get a public key from the KeyBook // The validator function will get a public key from the KeyBook
// to verify the record's signature // to verify the record's signature
@ -44,19 +56,19 @@ func NewIpnsRecordValidator(kbook pstore.KeyBook) *record.ValidChecker {
entry := new(pb.IpnsEntry) entry := new(pb.IpnsEntry)
err := proto.Unmarshal(r.Value, entry) err := proto.Unmarshal(r.Value, entry)
if err != nil { if err != nil {
return err return ErrBadRecord
} }
// Get the public key defined by the ipns path // Get the public key defined by the ipns path
pid, err := peer.IDFromString(r.Key) pid, err := peer.IDFromString(r.Key)
if err != nil { if err != nil {
log.Debugf("failed to parse ipns record key %s into public key hash", r.Key) log.Debugf("failed to parse ipns record key %s into peer ID", r.Key)
return ErrSignature return ErrKeyFormat
} }
pubk := kbook.PubKey(pid) pubk := kbook.PubKey(pid)
if pubk == nil { if pubk == nil {
log.Debugf("public key with hash %s not found in peer store", pid) log.Debugf("public key with hash %s not found in peer store", pid)
return ErrSignature return ErrPublicKeyNotFound
} }
// Check the ipns record signature with the public key // Check the ipns record signature with the public key