blob: fd004e6165c63cc82525a2561d7e20b5e5dadf41 [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"
Cosmos Nicolaou3bdf6372014-12-10 09:53:52 -08008 "sort"
Ankur100eb272014-09-15 16:48:12 -07009 "sync"
10
Jiri Simsa519c5072014-09-17 21:37:57 -070011 "veyron.io/veyron/veyron/security/serialization"
Ankur100eb272014-09-15 16:48:12 -070012
Jiri Simsa519c5072014-09-17 21:37:57 -070013 "veyron.io/veyron/veyron2/security"
14 "veyron.io/veyron/veyron2/vlog"
Ankur100eb272014-09-15 16:48:12 -070015)
16
Ankur100eb272014-09-15 16:48:12 -070017var errStoreAddMismatch = errors.New("blessing's public key does not match store's public key")
18
Ankuree0aa812014-11-14 10:56:52 -080019type blessings struct {
20 Value security.WireBlessings
21 unmarshaled security.Blessings
22}
23
24func (w *blessings) Blessings() security.Blessings {
25 if w == nil {
26 return nil
27 }
28 return w.unmarshaled
29}
30
31func (w *blessings) Verify() error {
32 var err error
33 if w.unmarshaled == nil {
34 w.unmarshaled, err = security.NewBlessings(w.Value)
35 }
36 return err
37}
38
39func newWireBlessings(b security.Blessings) *blessings {
40 return &blessings{Value: security.MarshalBlessings(b), unmarshaled: b}
41}
42
43type state struct {
Asim Shankar48bf0e62014-10-03 16:27:05 -070044 // Store maps BlessingPatterns to the Blessings object that is to be shared
45 // with peers which present blessings of their own that match the pattern.
46 //
47 // All blessings bind to the same public key.
Ankuree0aa812014-11-14 10:56:52 -080048 Store map[security.BlessingPattern]*blessings
Ankur100eb272014-09-15 16:48:12 -070049 // Default is the default Blessings to be shared with peers for which
50 // no other information is available to select blessings.
Ankuree0aa812014-11-14 10:56:52 -080051 Default *blessings
Ankur100eb272014-09-15 16:48:12 -070052}
53
54// blessingStore implements security.BlessingStore.
55type blessingStore struct {
Ankuree0aa812014-11-14 10:56:52 -080056 publicKey security.PublicKey
57 serializer SerializerReaderWriter
58 signer serialization.Signer
59 mu sync.RWMutex
60 state state // GUARDED_BY(mu)
Ankur100eb272014-09-15 16:48:12 -070061}
62
gauthamt1e313bc2014-11-10 15:45:56 -080063func (bs *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
Ankur9e8500a2014-09-17 12:05:32 -070064 if !forPeers.IsValid() {
Asim Shankar48bf0e62014-10-03 16:27:05 -070065 return nil, fmt.Errorf("%q is an invalid BlessingPattern", forPeers)
Ankur100eb272014-09-15 16:48:12 -070066 }
gauthamt1e313bc2014-11-10 15:45:56 -080067 if blessings != nil && !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
Asim Shankar48bf0e62014-10-03 16:27:05 -070068 return nil, errStoreAddMismatch
69 }
gauthamt1e313bc2014-11-10 15:45:56 -080070 bs.mu.Lock()
71 defer bs.mu.Unlock()
72 old, hadold := bs.state.Store[forPeers]
Asim Shankar48bf0e62014-10-03 16:27:05 -070073 if blessings != nil {
Ankuree0aa812014-11-14 10:56:52 -080074 bs.state.Store[forPeers] = newWireBlessings(blessings)
Ankur100eb272014-09-15 16:48:12 -070075 } else {
gauthamt1e313bc2014-11-10 15:45:56 -080076 delete(bs.state.Store, forPeers)
Ankur100eb272014-09-15 16:48:12 -070077 }
gauthamt1e313bc2014-11-10 15:45:56 -080078 if err := bs.save(); err != nil {
Asim Shankar48bf0e62014-10-03 16:27:05 -070079 if hadold {
gauthamt1e313bc2014-11-10 15:45:56 -080080 bs.state.Store[forPeers] = old
Ankur100eb272014-09-15 16:48:12 -070081 } else {
gauthamt1e313bc2014-11-10 15:45:56 -080082 delete(bs.state.Store, forPeers)
Ankur100eb272014-09-15 16:48:12 -070083 }
Asim Shankar48bf0e62014-10-03 16:27:05 -070084 return nil, err
Ankur100eb272014-09-15 16:48:12 -070085 }
Ankuree0aa812014-11-14 10:56:52 -080086 return old.Blessings(), nil
Ankur100eb272014-09-15 16:48:12 -070087}
88
gauthamt1e313bc2014-11-10 15:45:56 -080089func (bs *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
90 bs.mu.RLock()
91 defer bs.mu.RUnlock()
Ankur100eb272014-09-15 16:48:12 -070092
Asim Shankar48bf0e62014-10-03 16:27:05 -070093 var ret security.Blessings
Ankuree0aa812014-11-14 10:56:52 -080094 for pattern, wb := range bs.state.Store {
Asim Shankar48bf0e62014-10-03 16:27:05 -070095 if pattern.MatchedBy(peerBlessings...) {
Ankuree0aa812014-11-14 10:56:52 -080096 b := wb.Blessings()
97 if union, err := security.UnionOfBlessings(ret, b); err != nil {
98 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 -070099 } else {
100 ret = union
Ankur100eb272014-09-15 16:48:12 -0700101 }
102 }
103 }
Asim Shankar48bf0e62014-10-03 16:27:05 -0700104 return ret
Ankur100eb272014-09-15 16:48:12 -0700105}
106
gauthamt1e313bc2014-11-10 15:45:56 -0800107func (bs *blessingStore) Default() security.Blessings {
108 bs.mu.RLock()
109 defer bs.mu.RUnlock()
110 if bs.state.Default != nil {
Ankuree0aa812014-11-14 10:56:52 -0800111 return bs.state.Default.Blessings()
Ankur100eb272014-09-15 16:48:12 -0700112 }
gauthamt1e313bc2014-11-10 15:45:56 -0800113 return bs.ForPeer()
Ankur100eb272014-09-15 16:48:12 -0700114}
115
gauthamt1e313bc2014-11-10 15:45:56 -0800116func (bs *blessingStore) SetDefault(blessings security.Blessings) error {
117 bs.mu.Lock()
118 defer bs.mu.Unlock()
119 if !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
Ankur100eb272014-09-15 16:48:12 -0700120 return errStoreAddMismatch
121 }
gauthamt1e313bc2014-11-10 15:45:56 -0800122 oldDefault := bs.state.Default
Ankuree0aa812014-11-14 10:56:52 -0800123 bs.state.Default = newWireBlessings(blessings)
gauthamt1e313bc2014-11-10 15:45:56 -0800124 if err := bs.save(); err != nil {
125 bs.state.Default = oldDefault
Ankur100eb272014-09-15 16:48:12 -0700126 }
127 return nil
128}
129
gauthamt1e313bc2014-11-10 15:45:56 -0800130func (bs *blessingStore) PublicKey() security.PublicKey {
131 return bs.publicKey
Ankur100eb272014-09-15 16:48:12 -0700132}
133
gauthamt1e313bc2014-11-10 15:45:56 -0800134func (bs *blessingStore) String() string {
135 return fmt.Sprintf("{state: %v, publicKey: %v}", bs.state, bs.publicKey)
Ankur100eb272014-09-15 16:48:12 -0700136}
137
gauthamtf8263932014-12-16 10:59:09 -0800138func (bs *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
139 m := make(map[security.BlessingPattern]security.Blessings)
140 for pattern, wb := range bs.state.Store {
141 m[pattern] = wb.Blessings()
142 }
143 return m
144}
145
Ankur1615a7d2014-10-09 11:58:02 -0700146// DebugString return a human-readable string encoding of the store
147// in the following format
148// Default blessing : <Default blessing of the store>
149//
150// Peer pattern : Blessings
151// <pattern> : <blessings>
152// ...
153// <pattern> : <blessings>
gauthamt1e313bc2014-11-10 15:45:56 -0800154func (bs *blessingStore) DebugString() string {
Ankur1615a7d2014-10-09 11:58:02 -0700155 const format = "%-30s : %s\n"
Ankuree0aa812014-11-14 10:56:52 -0800156 b := bytes.NewBufferString(fmt.Sprintf("Default blessings: %v\n", bs.state.Default.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700157
158 b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
Cosmos Nicolaou3bdf6372014-12-10 09:53:52 -0800159
160 sorted := make([]string, 0, len(bs.state.Store))
161 for k, _ := range bs.state.Store {
162 sorted = append(sorted, string(k))
163 }
164 sort.Strings(sorted)
165 for _, pattern := range sorted {
166 wb := bs.state.Store[security.BlessingPattern(pattern)]
Ankuree0aa812014-11-14 10:56:52 -0800167 b.WriteString(fmt.Sprintf(format, pattern, wb.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700168 }
169 return b.String()
170}
171
gauthamt1e313bc2014-11-10 15:45:56 -0800172func (bs *blessingStore) save() error {
Ankuree0aa812014-11-14 10:56:52 -0800173 if (bs.signer == nil) && (bs.serializer == nil) {
Ankur100eb272014-09-15 16:48:12 -0700174 return nil
175 }
Ankuree0aa812014-11-14 10:56:52 -0800176 data, signature, err := bs.serializer.Writers()
gauthamt1e313bc2014-11-10 15:45:56 -0800177 if err != nil {
178 return err
179 }
180 return encodeAndStore(bs.state, data, signature, bs.signer)
Ankur100eb272014-09-15 16:48:12 -0700181}
182
Ankur7c890592014-10-02 11:36:28 -0700183// newInMemoryBlessingStore returns an in-memory security.BlessingStore for a
Ankur100eb272014-09-15 16:48:12 -0700184// principal with the provided PublicKey.
185//
186// The returned BlessingStore is initialized with an empty set of blessings.
Ankur7c890592014-10-02 11:36:28 -0700187func newInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
Ankur100eb272014-09-15 16:48:12 -0700188 return &blessingStore{
189 publicKey: publicKey,
Ankuree0aa812014-11-14 10:56:52 -0800190 state: state{Store: make(map[security.BlessingPattern]*blessings)},
Ankur100eb272014-09-15 16:48:12 -0700191 }
192}
193
Ankur27c56fd2014-11-17 19:30:34 -0800194// TODO(ataly, ashankar): Get rid of this struct once we have switched all credentials
195// directories to the new serialization format.
196type oldState struct {
197 Store map[security.BlessingPattern]security.WireBlessings
198 Default security.WireBlessings
199}
200
201// TODO(ataly, ashankar): Get rid of this method once we have switched all
202// credentials directories to the new serialization format.
203func (bs *blessingStore) tryOldFormat() bool {
204 var empty security.WireBlessings
205 if len(bs.state.Store) == 0 {
206 return bs.state.Default == nil || reflect.DeepEqual(bs.state.Default.Value, empty)
207 }
208 for _, wb := range bs.state.Store {
209 if len(wb.Value.CertificateChains) == 0 {
210 return true
211 }
212 }
213 return false
214}
215
Ankur57483012014-11-19 13:17:37 -0800216func (bs *blessingStore) verifyState() error {
217 verifyBlessings := func(wb *blessings, key security.PublicKey) error {
218 if err := wb.Verify(); err != nil {
219 return err
220 }
221 if b := wb.Blessings(); b != nil && !reflect.DeepEqual(b.PublicKey(), key) {
222 return fmt.Errorf("read Blessings: %v that are not for provided PublicKey: %v", b, key)
223 }
224 return nil
225 }
226 for _, wb := range bs.state.Store {
227 if err := verifyBlessings(wb, bs.publicKey); err != nil {
228 return err
229 }
230 }
231 if bs.state.Default != nil {
232 if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
233 return err
234 }
235 }
236 return nil
237}
238
Ankur27c56fd2014-11-17 19:30:34 -0800239// TODO(ataly, ashankar): Get rid of this method once we have switched all
240// credentials directories to the new serialization format.
241func (bs *blessingStore) deserializeOld() error {
242 data, signature, err := bs.serializer.Readers()
243 if err != nil {
244 return err
245 }
246 if data == nil && signature == nil {
247 return nil
248 }
249 var old oldState
250 if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
251 return err
252 }
253 for p, wire := range old.Store {
254 bs.state.Store[p] = &blessings{Value: wire}
255 }
256 bs.state.Default = &blessings{Value: old.Default}
Ankur57483012014-11-19 13:17:37 -0800257
258 if err := bs.verifyState(); err != nil {
259 return err
260 }
261 // Save the blessingstore in the new serialization format. This will ensure
262 // that all credentials directories in the old format will switch to the new
263 // format.
264 if err := bs.save(); err != nil {
265 return err
266 }
Ankur27c56fd2014-11-17 19:30:34 -0800267 return nil
268}
269
270func (bs *blessingStore) deserialize() error {
271 data, signature, err := bs.serializer.Readers()
272 if err != nil {
273 return err
274 }
275 if data == nil && signature == nil {
276 return nil
277 }
278 if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
Ankur57483012014-11-19 13:17:37 -0800279 return bs.verifyState()
Ankur27c56fd2014-11-17 19:30:34 -0800280 }
281 if err := bs.deserializeOld(); err != nil {
282 return err
283 }
284 return nil
285}
286
Ankur7c890592014-10-02 11:36:28 -0700287// newPersistingBlessingStore returns a security.BlessingStore for a principal
gauthamt1e313bc2014-11-10 15:45:56 -0800288// that is initialized with the persisted data. The returned security.BlessingStore
289// also persists any updates to its state.
Ankuree0aa812014-11-14 10:56:52 -0800290func newPersistingBlessingStore(serializer SerializerReaderWriter, signer serialization.Signer) (security.BlessingStore, error) {
Ankuree0aa812014-11-14 10:56:52 -0800291 if serializer == nil || signer == nil {
gauthamt1e313bc2014-11-10 15:45:56 -0800292 return nil, errors.New("persisted data or signer is not specified")
Ankur100eb272014-09-15 16:48:12 -0700293 }
gauthamt1e313bc2014-11-10 15:45:56 -0800294 bs := &blessingStore{
Ankuree0aa812014-11-14 10:56:52 -0800295 publicKey: signer.PublicKey(),
296 state: state{Store: make(map[security.BlessingPattern]*blessings)},
297 serializer: serializer,
298 signer: signer,
Ankur100eb272014-09-15 16:48:12 -0700299 }
Ankur27c56fd2014-11-17 19:30:34 -0800300 if err := bs.deserialize(); err != nil {
Ankur100eb272014-09-15 16:48:12 -0700301 return nil, err
302 }
gauthamt1e313bc2014-11-10 15:45:56 -0800303 return bs, nil
Ankur100eb272014-09-15 16:48:12 -0700304}