blob: 1adfbe29777fa185840c4e3cb28841083de594f3 [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"
6 "fmt"
7 "reflect"
Ankur100eb272014-09-15 16:48:12 -07008 "sync"
9
Jiri Simsa519c5072014-09-17 21:37:57 -070010 "veyron.io/veyron/veyron/security/serialization"
Ankur100eb272014-09-15 16:48:12 -070011
Jiri Simsa519c5072014-09-17 21:37:57 -070012 "veyron.io/veyron/veyron2/security"
13 "veyron.io/veyron/veyron2/vlog"
Ankur100eb272014-09-15 16:48:12 -070014)
15
Ankur100eb272014-09-15 16:48:12 -070016var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
17
Ankuree0aa812014-11-14 10:56:52 -080018type blessings struct {
19 Value security.WireBlessings
20 unmarshaled security.Blessings
21}
22
23func (w *blessings) Blessings() security.Blessings {
24 if w == nil {
25 return nil
26 }
27 return w.unmarshaled
28}
29
30func (w *blessings) Verify() error {
31 var err error
32 if w.unmarshaled == nil {
33 w.unmarshaled, err = security.NewBlessings(w.Value)
34 }
35 return err
36}
37
38func newWireBlessings(b security.Blessings) *blessings {
39 return &blessings{Value: security.MarshalBlessings(b), unmarshaled: b}
40}
41
42type state struct {
Asim Shankar48bf0e62014-10-03 16:27:05 -070043 // Store maps BlessingPatterns to the Blessings object that is to be shared
44 // with peers which present blessings of their own that match the pattern.
45 //
46 // All blessings bind to the same public key.
Ankuree0aa812014-11-14 10:56:52 -080047 Store map[security.BlessingPattern]*blessings
Ankur100eb272014-09-15 16:48:12 -070048 // Default is the default Blessings to be shared with peers for which
49 // no other information is available to select blessings.
Ankuree0aa812014-11-14 10:56:52 -080050 Default *blessings
Ankur100eb272014-09-15 16:48:12 -070051}
52
53// blessingStore implements security.BlessingStore.
54type blessingStore struct {
Ankuree0aa812014-11-14 10:56:52 -080055 publicKey security.PublicKey
56 serializer SerializerReaderWriter
57 signer serialization.Signer
58 mu sync.RWMutex
59 state state // GUARDED_BY(mu)
Ankur100eb272014-09-15 16:48:12 -070060}
61
gauthamt1e313bc2014-11-10 15:45:56 -080062func (bs *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
Ankur9e8500a2014-09-17 12:05:32 -070063 if !forPeers.IsValid() {
Asim Shankar48bf0e62014-10-03 16:27:05 -070064 return nil, fmt.Errorf("%q is an invalid BlessingPattern", forPeers)
Ankur100eb272014-09-15 16:48:12 -070065 }
gauthamt1e313bc2014-11-10 15:45:56 -080066 if blessings != nil && !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
Asim Shankar48bf0e62014-10-03 16:27:05 -070067 return nil, errStoreAddMismatch
68 }
gauthamt1e313bc2014-11-10 15:45:56 -080069 bs.mu.Lock()
70 defer bs.mu.Unlock()
71 old, hadold := bs.state.Store[forPeers]
Asim Shankar48bf0e62014-10-03 16:27:05 -070072 if blessings != nil {
Ankuree0aa812014-11-14 10:56:52 -080073 bs.state.Store[forPeers] = newWireBlessings(blessings)
Ankur100eb272014-09-15 16:48:12 -070074 } else {
gauthamt1e313bc2014-11-10 15:45:56 -080075 delete(bs.state.Store, forPeers)
Ankur100eb272014-09-15 16:48:12 -070076 }
gauthamt1e313bc2014-11-10 15:45:56 -080077 if err := bs.save(); err != nil {
Asim Shankar48bf0e62014-10-03 16:27:05 -070078 if hadold {
gauthamt1e313bc2014-11-10 15:45:56 -080079 bs.state.Store[forPeers] = old
Ankur100eb272014-09-15 16:48:12 -070080 } else {
gauthamt1e313bc2014-11-10 15:45:56 -080081 delete(bs.state.Store, forPeers)
Ankur100eb272014-09-15 16:48:12 -070082 }
Asim Shankar48bf0e62014-10-03 16:27:05 -070083 return nil, err
Ankur100eb272014-09-15 16:48:12 -070084 }
Ankuree0aa812014-11-14 10:56:52 -080085 return old.Blessings(), nil
Ankur100eb272014-09-15 16:48:12 -070086}
87
gauthamt1e313bc2014-11-10 15:45:56 -080088func (bs *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
89 bs.mu.RLock()
90 defer bs.mu.RUnlock()
Ankur100eb272014-09-15 16:48:12 -070091
Asim Shankar48bf0e62014-10-03 16:27:05 -070092 var ret security.Blessings
Ankuree0aa812014-11-14 10:56:52 -080093 for pattern, wb := range bs.state.Store {
Asim Shankar48bf0e62014-10-03 16:27:05 -070094 if pattern.MatchedBy(peerBlessings...) {
Ankuree0aa812014-11-14 10:56:52 -080095 b := wb.Blessings()
96 if union, err := security.UnionOfBlessings(ret, b); err != nil {
97 vlog.Errorf("UnionOfBlessings(%v, %v) failed: %v, dropping the latter from BlessingStore.ForPeers(%v)", ret, b, err, peerBlessings)
Asim Shankar48bf0e62014-10-03 16:27:05 -070098 } else {
99 ret = union
Ankur100eb272014-09-15 16:48:12 -0700100 }
101 }
102 }
Asim Shankar48bf0e62014-10-03 16:27:05 -0700103 return ret
Ankur100eb272014-09-15 16:48:12 -0700104}
105
gauthamt1e313bc2014-11-10 15:45:56 -0800106func (bs *blessingStore) Default() security.Blessings {
107 bs.mu.RLock()
108 defer bs.mu.RUnlock()
109 if bs.state.Default != nil {
Ankuree0aa812014-11-14 10:56:52 -0800110 return bs.state.Default.Blessings()
Ankur100eb272014-09-15 16:48:12 -0700111 }
gauthamt1e313bc2014-11-10 15:45:56 -0800112 return bs.ForPeer()
Ankur100eb272014-09-15 16:48:12 -0700113}
114
gauthamt1e313bc2014-11-10 15:45:56 -0800115func (bs *blessingStore) SetDefault(blessings security.Blessings) error {
116 bs.mu.Lock()
117 defer bs.mu.Unlock()
118 if !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
Ankur100eb272014-09-15 16:48:12 -0700119 return errStoreAddMismatch
120 }
gauthamt1e313bc2014-11-10 15:45:56 -0800121 oldDefault := bs.state.Default
Ankuree0aa812014-11-14 10:56:52 -0800122 bs.state.Default = newWireBlessings(blessings)
gauthamt1e313bc2014-11-10 15:45:56 -0800123 if err := bs.save(); err != nil {
124 bs.state.Default = oldDefault
Ankur100eb272014-09-15 16:48:12 -0700125 }
126 return nil
127}
128
gauthamt1e313bc2014-11-10 15:45:56 -0800129func (bs *blessingStore) PublicKey() security.PublicKey {
130 return bs.publicKey
Ankur100eb272014-09-15 16:48:12 -0700131}
132
gauthamt1e313bc2014-11-10 15:45:56 -0800133func (bs *blessingStore) String() string {
134 return fmt.Sprintf("{state: %v, publicKey: %v}", bs.state, bs.publicKey)
Ankur100eb272014-09-15 16:48:12 -0700135}
136
Ankur1615a7d2014-10-09 11:58:02 -0700137// DebugString return a human-readable string encoding of the store
138// in the following format
139// Default blessing : <Default blessing of the store>
140//
141// Peer pattern : Blessings
142// <pattern> : <blessings>
143// ...
144// <pattern> : <blessings>
gauthamt1e313bc2014-11-10 15:45:56 -0800145func (bs *blessingStore) DebugString() string {
Ankur1615a7d2014-10-09 11:58:02 -0700146 const format = "%-30s : %s\n"
Ankuree0aa812014-11-14 10:56:52 -0800147 b := bytes.NewBufferString(fmt.Sprintf("Default blessings: %v\n", bs.state.Default.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700148
149 b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
Ankuree0aa812014-11-14 10:56:52 -0800150 for pattern, wb := range bs.state.Store {
151 b.WriteString(fmt.Sprintf(format, pattern, wb.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700152 }
153 return b.String()
154}
155
gauthamt1e313bc2014-11-10 15:45:56 -0800156func (bs *blessingStore) save() error {
Ankuree0aa812014-11-14 10:56:52 -0800157 if (bs.signer == nil) && (bs.serializer == nil) {
Ankur100eb272014-09-15 16:48:12 -0700158 return nil
159 }
Ankuree0aa812014-11-14 10:56:52 -0800160 data, signature, err := bs.serializer.Writers()
gauthamt1e313bc2014-11-10 15:45:56 -0800161 if err != nil {
162 return err
163 }
164 return encodeAndStore(bs.state, data, signature, bs.signer)
Ankur100eb272014-09-15 16:48:12 -0700165}
166
Ankur7c890592014-10-02 11:36:28 -0700167// newInMemoryBlessingStore returns an in-memory security.BlessingStore for a
Ankur100eb272014-09-15 16:48:12 -0700168// principal with the provided PublicKey.
169//
170// The returned BlessingStore is initialized with an empty set of blessings.
Ankur7c890592014-10-02 11:36:28 -0700171func newInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
Ankur100eb272014-09-15 16:48:12 -0700172 return &blessingStore{
173 publicKey: publicKey,
Ankuree0aa812014-11-14 10:56:52 -0800174 state: state{Store: make(map[security.BlessingPattern]*blessings)},
Ankur100eb272014-09-15 16:48:12 -0700175 }
176}
177
Ankur27c56fd2014-11-17 19:30:34 -0800178// TODO(ataly, ashankar): Get rid of this struct once we have switched all credentials
179// directories to the new serialization format.
180type oldState struct {
181 Store map[security.BlessingPattern]security.WireBlessings
182 Default security.WireBlessings
183}
184
185// TODO(ataly, ashankar): Get rid of this method once we have switched all
186// credentials directories to the new serialization format.
187func (bs *blessingStore) tryOldFormat() bool {
188 var empty security.WireBlessings
189 if len(bs.state.Store) == 0 {
190 return bs.state.Default == nil || reflect.DeepEqual(bs.state.Default.Value, empty)
191 }
192 for _, wb := range bs.state.Store {
193 if len(wb.Value.CertificateChains) == 0 {
194 return true
195 }
196 }
197 return false
198}
199
Ankur57483012014-11-19 13:17:37 -0800200func (bs *blessingStore) verifyState() error {
201 verifyBlessings := func(wb *blessings, key security.PublicKey) error {
202 if err := wb.Verify(); err != nil {
203 return err
204 }
205 if b := wb.Blessings(); b != nil && !reflect.DeepEqual(b.PublicKey(), key) {
206 return fmt.Errorf("read Blessings: %v that are not for provided PublicKey: %v", b, key)
207 }
208 return nil
209 }
210 for _, wb := range bs.state.Store {
211 if err := verifyBlessings(wb, bs.publicKey); err != nil {
212 return err
213 }
214 }
215 if bs.state.Default != nil {
216 if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
217 return err
218 }
219 }
220 return nil
221}
222
Ankur27c56fd2014-11-17 19:30:34 -0800223// TODO(ataly, ashankar): Get rid of this method once we have switched all
224// credentials directories to the new serialization format.
225func (bs *blessingStore) deserializeOld() error {
226 data, signature, err := bs.serializer.Readers()
227 if err != nil {
228 return err
229 }
230 if data == nil && signature == nil {
231 return nil
232 }
233 var old oldState
234 if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
235 return err
236 }
237 for p, wire := range old.Store {
238 bs.state.Store[p] = &blessings{Value: wire}
239 }
240 bs.state.Default = &blessings{Value: old.Default}
Ankur57483012014-11-19 13:17:37 -0800241
242 if err := bs.verifyState(); err != nil {
243 return err
244 }
245 // Save the blessingstore in the new serialization format. This will ensure
246 // that all credentials directories in the old format will switch to the new
247 // format.
248 if err := bs.save(); err != nil {
249 return err
250 }
Ankur27c56fd2014-11-17 19:30:34 -0800251 return nil
252}
253
254func (bs *blessingStore) deserialize() error {
255 data, signature, err := bs.serializer.Readers()
256 if err != nil {
257 return err
258 }
259 if data == nil && signature == nil {
260 return nil
261 }
262 if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
Ankur57483012014-11-19 13:17:37 -0800263 return bs.verifyState()
Ankur27c56fd2014-11-17 19:30:34 -0800264 }
265 if err := bs.deserializeOld(); err != nil {
266 return err
267 }
268 return nil
269}
270
Ankur7c890592014-10-02 11:36:28 -0700271// newPersistingBlessingStore returns a security.BlessingStore for a principal
gauthamt1e313bc2014-11-10 15:45:56 -0800272// that is initialized with the persisted data. The returned security.BlessingStore
273// also persists any updates to its state.
Ankuree0aa812014-11-14 10:56:52 -0800274func newPersistingBlessingStore(serializer SerializerReaderWriter, signer serialization.Signer) (security.BlessingStore, error) {
Ankuree0aa812014-11-14 10:56:52 -0800275 if serializer == nil || signer == nil {
gauthamt1e313bc2014-11-10 15:45:56 -0800276 return nil, errors.New("persisted data or signer is not specified")
Ankur100eb272014-09-15 16:48:12 -0700277 }
gauthamt1e313bc2014-11-10 15:45:56 -0800278 bs := &blessingStore{
Ankuree0aa812014-11-14 10:56:52 -0800279 publicKey: signer.PublicKey(),
280 state: state{Store: make(map[security.BlessingPattern]*blessings)},
281 serializer: serializer,
282 signer: signer,
Ankur100eb272014-09-15 16:48:12 -0700283 }
Ankur27c56fd2014-11-17 19:30:34 -0800284 if err := bs.deserialize(); err != nil {
Ankur100eb272014-09-15 16:48:12 -0700285 return nil, err
286 }
gauthamt1e313bc2014-11-10 15:45:56 -0800287 return bs, nil
Ankur100eb272014-09-15 16:48:12 -0700288}