blob: be3449b129ac884d3d8c3cc337f847a86d1e95f6 [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
Ankur1615a7d2014-10-09 11:58:02 -0700138// DebugString return a human-readable string encoding of the store
139// in the following format
140// Default blessing : <Default blessing of the store>
141//
142// Peer pattern : Blessings
143// <pattern> : <blessings>
144// ...
145// <pattern> : <blessings>
gauthamt1e313bc2014-11-10 15:45:56 -0800146func (bs *blessingStore) DebugString() string {
Ankur1615a7d2014-10-09 11:58:02 -0700147 const format = "%-30s : %s\n"
Ankuree0aa812014-11-14 10:56:52 -0800148 b := bytes.NewBufferString(fmt.Sprintf("Default blessings: %v\n", bs.state.Default.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700149
150 b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
Cosmos Nicolaou3bdf6372014-12-10 09:53:52 -0800151
152 sorted := make([]string, 0, len(bs.state.Store))
153 for k, _ := range bs.state.Store {
154 sorted = append(sorted, string(k))
155 }
156 sort.Strings(sorted)
157 for _, pattern := range sorted {
158 wb := bs.state.Store[security.BlessingPattern(pattern)]
Ankuree0aa812014-11-14 10:56:52 -0800159 b.WriteString(fmt.Sprintf(format, pattern, wb.Blessings()))
Ankur1615a7d2014-10-09 11:58:02 -0700160 }
161 return b.String()
162}
163
gauthamt1e313bc2014-11-10 15:45:56 -0800164func (bs *blessingStore) save() error {
Ankuree0aa812014-11-14 10:56:52 -0800165 if (bs.signer == nil) && (bs.serializer == nil) {
Ankur100eb272014-09-15 16:48:12 -0700166 return nil
167 }
Ankuree0aa812014-11-14 10:56:52 -0800168 data, signature, err := bs.serializer.Writers()
gauthamt1e313bc2014-11-10 15:45:56 -0800169 if err != nil {
170 return err
171 }
172 return encodeAndStore(bs.state, data, signature, bs.signer)
Ankur100eb272014-09-15 16:48:12 -0700173}
174
Ankur7c890592014-10-02 11:36:28 -0700175// newInMemoryBlessingStore returns an in-memory security.BlessingStore for a
Ankur100eb272014-09-15 16:48:12 -0700176// principal with the provided PublicKey.
177//
178// The returned BlessingStore is initialized with an empty set of blessings.
Ankur7c890592014-10-02 11:36:28 -0700179func newInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
Ankur100eb272014-09-15 16:48:12 -0700180 return &blessingStore{
181 publicKey: publicKey,
Ankuree0aa812014-11-14 10:56:52 -0800182 state: state{Store: make(map[security.BlessingPattern]*blessings)},
Ankur100eb272014-09-15 16:48:12 -0700183 }
184}
185
Ankur27c56fd2014-11-17 19:30:34 -0800186// TODO(ataly, ashankar): Get rid of this struct once we have switched all credentials
187// directories to the new serialization format.
188type oldState struct {
189 Store map[security.BlessingPattern]security.WireBlessings
190 Default security.WireBlessings
191}
192
193// TODO(ataly, ashankar): Get rid of this method once we have switched all
194// credentials directories to the new serialization format.
195func (bs *blessingStore) tryOldFormat() bool {
196 var empty security.WireBlessings
197 if len(bs.state.Store) == 0 {
198 return bs.state.Default == nil || reflect.DeepEqual(bs.state.Default.Value, empty)
199 }
200 for _, wb := range bs.state.Store {
201 if len(wb.Value.CertificateChains) == 0 {
202 return true
203 }
204 }
205 return false
206}
207
Ankur57483012014-11-19 13:17:37 -0800208func (bs *blessingStore) verifyState() error {
209 verifyBlessings := func(wb *blessings, key security.PublicKey) error {
210 if err := wb.Verify(); err != nil {
211 return err
212 }
213 if b := wb.Blessings(); b != nil && !reflect.DeepEqual(b.PublicKey(), key) {
214 return fmt.Errorf("read Blessings: %v that are not for provided PublicKey: %v", b, key)
215 }
216 return nil
217 }
218 for _, wb := range bs.state.Store {
219 if err := verifyBlessings(wb, bs.publicKey); err != nil {
220 return err
221 }
222 }
223 if bs.state.Default != nil {
224 if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
225 return err
226 }
227 }
228 return nil
229}
230
Ankur27c56fd2014-11-17 19:30:34 -0800231// TODO(ataly, ashankar): Get rid of this method once we have switched all
232// credentials directories to the new serialization format.
233func (bs *blessingStore) deserializeOld() error {
234 data, signature, err := bs.serializer.Readers()
235 if err != nil {
236 return err
237 }
238 if data == nil && signature == nil {
239 return nil
240 }
241 var old oldState
242 if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
243 return err
244 }
245 for p, wire := range old.Store {
246 bs.state.Store[p] = &blessings{Value: wire}
247 }
248 bs.state.Default = &blessings{Value: old.Default}
Ankur57483012014-11-19 13:17:37 -0800249
250 if err := bs.verifyState(); err != nil {
251 return err
252 }
253 // Save the blessingstore in the new serialization format. This will ensure
254 // that all credentials directories in the old format will switch to the new
255 // format.
256 if err := bs.save(); err != nil {
257 return err
258 }
Ankur27c56fd2014-11-17 19:30:34 -0800259 return nil
260}
261
262func (bs *blessingStore) deserialize() error {
263 data, signature, err := bs.serializer.Readers()
264 if err != nil {
265 return err
266 }
267 if data == nil && signature == nil {
268 return nil
269 }
270 if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
Ankur57483012014-11-19 13:17:37 -0800271 return bs.verifyState()
Ankur27c56fd2014-11-17 19:30:34 -0800272 }
273 if err := bs.deserializeOld(); err != nil {
274 return err
275 }
276 return nil
277}
278
Ankur7c890592014-10-02 11:36:28 -0700279// newPersistingBlessingStore returns a security.BlessingStore for a principal
gauthamt1e313bc2014-11-10 15:45:56 -0800280// that is initialized with the persisted data. The returned security.BlessingStore
281// also persists any updates to its state.
Ankuree0aa812014-11-14 10:56:52 -0800282func newPersistingBlessingStore(serializer SerializerReaderWriter, signer serialization.Signer) (security.BlessingStore, error) {
Ankuree0aa812014-11-14 10:56:52 -0800283 if serializer == nil || signer == nil {
gauthamt1e313bc2014-11-10 15:45:56 -0800284 return nil, errors.New("persisted data or signer is not specified")
Ankur100eb272014-09-15 16:48:12 -0700285 }
gauthamt1e313bc2014-11-10 15:45:56 -0800286 bs := &blessingStore{
Ankuree0aa812014-11-14 10:56:52 -0800287 publicKey: signer.PublicKey(),
288 state: state{Store: make(map[security.BlessingPattern]*blessings)},
289 serializer: serializer,
290 signer: signer,
Ankur100eb272014-09-15 16:48:12 -0700291 }
Ankur27c56fd2014-11-17 19:30:34 -0800292 if err := bs.deserialize(); err != nil {
Ankur100eb272014-09-15 16:48:12 -0700293 return nil, err
294 }
gauthamt1e313bc2014-11-10 15:45:56 -0800295 return bs, nil
Ankur100eb272014-09-15 16:48:12 -0700296}