blob: 0451a5d3997c23537c46d795aa06c9451b63144e [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains utility functions and types for tests for the security package.
package security
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"reflect"
"strings"
"testing"
"v.io/v23/context"
"v.io/v23/uniqueid"
"v.io/v23/vdl"
"v.io/v23/vom"
)
type markedRoot struct {
root []byte
pattern BlessingPattern
}
type roots struct {
data []markedRoot
}
func (r *roots) Add(root []byte, pattern BlessingPattern) error {
if !pattern.IsValid() {
return fmt.Errorf("pattern %q is invalid", pattern)
}
r.data = append(r.data, markedRoot{root, pattern})
return nil
}
func (r *roots) Recognized(root []byte, blessing string) error {
for _, mr := range r.data {
if bytes.Equal(root, mr.root) && mr.pattern.MatchedBy(blessing) {
return nil
}
}
key, err := UnmarshalPublicKey(root)
if err != nil {
return err
}
return NewErrUnrecognizedRoot(nil, key.String(), nil)
}
func (r *roots) Dump() map[BlessingPattern][]PublicKey {
ret := make(map[BlessingPattern][]PublicKey)
for _, mr := range r.data {
key, err := UnmarshalPublicKey(mr.root)
if err != nil {
ret[mr.pattern] = append(ret[mr.pattern], key)
}
}
return ret
}
func (*roots) DebugString() string {
return "BlessingRoots implementation for testing purposes only"
}
func newCaveat(c Caveat, err error) Caveat {
if err != nil {
panic(err)
}
return c
}
// Caveat that validates iff Call.Suffix matches the string.
//
// Since at the time of this writing, it was not clear that we want to make caveats on
// suffixes generally available, this type is implemented in this test file.
// If there is a general need for such a caveat, it should be defined similar to
// other caveats (like methodCaveat) in caveat.vdl and removed from this test file.
var suffixCaveat = CaveatDescriptor{
Id: uniqueid.Id{0xce, 0xc4, 0xd0, 0x98, 0x94, 0x53, 0x90, 0xdb, 0x15, 0x7c, 0xa8, 0x10, 0xae, 0x62, 0x80, 0x0},
ParamType: vdl.TypeOf(string("")),
}
func newSuffixCaveat(suffix string) Caveat { return newCaveat(NewCaveat(suffixCaveat, suffix)) }
func newECDSASigner(t testing.TB, curve elliptic.Curve) Signer {
key, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
t.Fatalf("Failed to generate ECDSA key: %v", err)
}
return NewInMemoryECDSASigner(key)
}
func newPrincipal(t testing.TB) Principal {
p, err := CreatePrincipal(newECDSASigner(t, elliptic.P256()), nil, &roots{})
if err != nil {
t.Fatalf("CreatePrincipal failed: %v", err)
}
return p
}
func blessSelf(t *testing.T, p Principal, name string, caveats ...Caveat) Blessings {
b, err := p.BlessSelf(name, caveats...)
if err != nil {
t.Fatal(err)
}
return b
}
func addToRoots(t *testing.T, p Principal, b Blessings) {
if err := AddToRoots(p, b); err != nil {
t.Fatal(err)
}
}
func equalBlessings(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func checkBlessings(b Blessings, c CallParams, want ...string) error {
// Validate the integrity of the bits.
var decoded Blessings
if err := roundTrip(b, &decoded); err != nil {
return err
}
if !reflect.DeepEqual(decoded, b) {
return fmt.Errorf("reflect.DeepEqual of %#v and %#v failed after roundtripping", decoded, b)
}
// And now check them under the right call
c.RemoteBlessings = b
ctx, cancel := context.RootContext()
defer cancel()
got, _ := RemoteBlessingNames(ctx, NewCall(&c))
if !equalBlessings(got, want) {
return fmt.Errorf("Got blessings %v, want %v", got, want)
}
return nil
}
func matchesError(got error, want string) error {
if (got == nil) && len(want) == 0 {
return nil
}
if got == nil {
return fmt.Errorf("Got nil error, wanted to match %q", want)
}
if !strings.Contains(got.Error(), want) {
return fmt.Errorf("Got error %q, wanted to match %q", got, want)
}
return nil
}
func roundTrip(in, out interface{}) error {
data, err := vom.Encode(in)
if err != nil {
return err
}
return vom.Decode(data, out)
}
func init() {
RegisterCaveatValidator(suffixCaveat, func(ctx *context.T, call Call, suffix string) error {
if suffix != call.Suffix() {
return fmt.Errorf("suffixCaveat not met")
}
return nil
})
}