blob: e2318e2a1281a916a88167e78731bfe5ba84f4d1 [file] [log] [blame]
Asim Shankarae8d4c52014-10-08 13:03:31 -07001package security
Ankur100eb272014-09-15 16:48:12 -07002
3import (
Ankur1615a7d2014-10-09 11:58:02 -07004 "bytes"
Ankur100eb272014-09-15 16:48:12 -07005 "errors"
Ankur1615a7d2014-10-09 11:58:02 -07006 "fmt"
Asim Shankarf11b1bc2014-11-12 17:18:45 -08007 "sort"
Ankur100eb272014-09-15 16:48:12 -07008 "sync"
9
Jiri Simsa764efb72014-12-25 20:57:03 -080010 "v.io/core/veyron/security/serialization"
Ankur100eb272014-09-15 16:48:12 -070011
Jiri Simsa764efb72014-12-25 20:57:03 -080012 "v.io/core/veyron2/security"
Ankur100eb272014-09-15 16:48:12 -070013)
14
Ankur100eb272014-09-15 16:48:12 -070015// blessingRoots implements security.BlessingRoots.
16type blessingRoots struct {
gauthamt1e313bc2014-11-10 15:45:56 -080017 persistedData SerializerReaderWriter
18 signer serialization.Signer
19 mu sync.RWMutex
20 store map[string][]security.BlessingPattern // GUARDED_BY(mu)
Ankur100eb272014-09-15 16:48:12 -070021}
22
23func storeMapKey(root security.PublicKey) (string, error) {
24 rootBytes, err := root.MarshalBinary()
25 if err != nil {
26 return "", err
27 }
Ankur1615a7d2014-10-09 11:58:02 -070028 return string(rootBytes), nil
Ankur100eb272014-09-15 16:48:12 -070029}
30
31func (br *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
32 key, err := storeMapKey(root)
33 if err != nil {
34 return err
35 }
36
37 br.mu.Lock()
38 defer br.mu.Unlock()
39 patterns := br.store[key]
40 for _, p := range patterns {
41 if p == pattern {
42 return nil
43 }
44 }
45 br.store[key] = append(patterns, pattern)
46
47 if err := br.save(); err != nil {
48 br.store[key] = patterns[:len(patterns)-1]
49 return err
50 }
51 return nil
52}
53
54func (br *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
55 key, err := storeMapKey(root)
56 if err != nil {
57 return err
58 }
59
60 br.mu.RLock()
61 defer br.mu.RUnlock()
62 for _, p := range br.store[key] {
63 if p.MatchedBy(blessing) {
64 return nil
65 }
66 }
67 return errors.New("PublicKey is not a recognized root for this blessing")
68}
69
Ankur1615a7d2014-10-09 11:58:02 -070070// DebugString return a human-readable string encoding of the roots
71// DebugString encodes all roots into a string in the following
72// format
73//
74// Public key : Pattern
Asim Shankarf11b1bc2014-11-12 17:18:45 -080075// <public key> : <patterns>
Ankur1615a7d2014-10-09 11:58:02 -070076// ...
Asim Shankarf11b1bc2014-11-12 17:18:45 -080077// <public key> : <patterns>
Ankur1615a7d2014-10-09 11:58:02 -070078func (br *blessingRoots) DebugString() string {
79 const format = "%-47s : %s\n"
80 b := bytes.NewBufferString(fmt.Sprintf(format, "Public key", "Pattern"))
Asim Shankarf11b1bc2014-11-12 17:18:45 -080081 var s rootSorter
82 for keyBytes, patterns := range br.store {
Ankur1615a7d2014-10-09 11:58:02 -070083 key, err := security.UnmarshalPublicKey([]byte(keyBytes))
84 if err != nil {
85 return fmt.Sprintf("failed to decode public key: %v", err)
86 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -080087 s = append(s, &root{key, fmt.Sprintf("%v", patterns)})
88 }
89 sort.Sort(s)
90 for _, r := range s {
91 b.WriteString(fmt.Sprintf(format, r.key, r.patterns))
Ankur1615a7d2014-10-09 11:58:02 -070092 }
93 return b.String()
94}
95
Asim Shankarf11b1bc2014-11-12 17:18:45 -080096type root struct {
97 key security.PublicKey
98 patterns string
99}
100
101type rootSorter []*root
102
103func (s rootSorter) Len() int { return len(s) }
104func (s rootSorter) Less(i, j int) bool { return s[i].patterns < s[j].patterns }
105func (s rootSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
106
Ankur100eb272014-09-15 16:48:12 -0700107func (br *blessingRoots) save() error {
gauthamt1e313bc2014-11-10 15:45:56 -0800108 if (br.signer == nil) && (br.persistedData == nil) {
Ankur100eb272014-09-15 16:48:12 -0700109 return nil
110 }
gauthamt1e313bc2014-11-10 15:45:56 -0800111 data, signature, err := br.persistedData.Writers()
112 if err != nil {
113 return err
114 }
115 return encodeAndStore(br.store, data, signature, br.signer)
Ankur100eb272014-09-15 16:48:12 -0700116}
117
Ankur7c890592014-10-02 11:36:28 -0700118// newInMemoryBlessingRoots returns an in-memory security.BlessingRoots.
Ankur100eb272014-09-15 16:48:12 -0700119//
120// The returned BlessingRoots is initialized with an empty set of keys.
Ankur7c890592014-10-02 11:36:28 -0700121func newInMemoryBlessingRoots() security.BlessingRoots {
Ankur100eb272014-09-15 16:48:12 -0700122 return &blessingRoots{
123 store: make(map[string][]security.BlessingPattern),
124 }
125}
126
gauthamt1e313bc2014-11-10 15:45:56 -0800127// newPersistingBlessingRoots returns a security.BlessingRoots for a principal
128// that is initialized with the persisted data. The returned security.BlessingRoots
129// also persists any updates to its state.
130func newPersistingBlessingRoots(persistedData SerializerReaderWriter, signer serialization.Signer) (security.BlessingRoots, error) {
131 if persistedData == nil || signer == nil {
132 return nil, errors.New("persisted data or signer is not specified")
Ankur100eb272014-09-15 16:48:12 -0700133 }
134 br := &blessingRoots{
gauthamt1e313bc2014-11-10 15:45:56 -0800135 store: make(map[string][]security.BlessingPattern),
136 persistedData: persistedData,
137 signer: signer,
Ankur100eb272014-09-15 16:48:12 -0700138 }
gauthamt1e313bc2014-11-10 15:45:56 -0800139 data, signature, err := br.persistedData.Readers()
140 if err != nil {
Ankur100eb272014-09-15 16:48:12 -0700141 return nil, err
142 }
gauthamt1e313bc2014-11-10 15:45:56 -0800143 if (data != nil) && (signature != nil) {
144 if err := decodeFromStorage(&br.store, data, signature, br.signer.PublicKey()); err != nil {
145 return nil, err
146 }
147 }
Ankur100eb272014-09-15 16:48:12 -0700148 return br, nil
149}