David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package mounttablelib |
| 6 | |
| 7 | import ( |
| 8 | "encoding/json" |
| 9 | "io" |
| 10 | "os" |
David Why Use Two When One Will Do Presotto | e3e932c | 2015-05-15 14:59:46 -0700 | [diff] [blame] | 11 | "sort" |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 12 | "strconv" |
| 13 | "strings" |
| 14 | |
| 15 | "v.io/v23/context" |
David Why Use Two When One Will Do Presotto | 67b7071 | 2015-06-02 13:13:58 -0700 | [diff] [blame] | 16 | "v.io/v23/conventions" |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 17 | "v.io/v23/security" |
| 18 | "v.io/v23/security/access" |
| 19 | "v.io/v23/services/mounttable" |
| 20 | "v.io/v23/verror" |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 21 | ) |
| 22 | |
David Why Use Two When One Will Do Presotto | c74ac70 | 2015-05-07 15:33:52 -0700 | [diff] [blame] | 23 | // Blessings can't include a comma so we use them in made up user ids. The following distinctions are |
| 24 | // made so that we can account for them differently. |
| 25 | const localUser = ",LOCAL," // a client that has our public key but no blessing from which we can extract a user name |
| 26 | const blessedUser = ",BLESSED," // a client with blessings we trust but from which we can't extract a user name |
| 27 | const unknownUser = ",UNKNOWN," // a client which presents no blessing we trust |
| 28 | |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 29 | // VersionedPermissions associates a Version with a Permissions |
| 30 | type VersionedPermissions struct { |
| 31 | V int32 |
| 32 | P access.Permissions |
| 33 | } |
| 34 | |
| 35 | func NewVersionedPermissions() *VersionedPermissions { |
| 36 | return &VersionedPermissions{P: make(access.Permissions)} |
| 37 | } |
| 38 | |
| 39 | // Set sets the Permissions iff Version matches the current Version. If the set happens, the Version is advanced. |
| 40 | // If b is nil, this creates a new VersionedPermissions. |
| 41 | func (b *VersionedPermissions) Set(ctx *context.T, verstr string, perm access.Permissions) (*VersionedPermissions, error) { |
| 42 | if b == nil { |
| 43 | b = new(VersionedPermissions) |
| 44 | } |
| 45 | if len(verstr) > 0 { |
| 46 | gen, err := strconv.ParseInt(verstr, 10, 32) |
| 47 | if err != nil { |
| 48 | return b, verror.NewErrBadVersion(ctx) |
| 49 | } |
| 50 | if gen >= 0 && int32(gen) != b.V { |
| 51 | return b, verror.NewErrBadVersion(ctx) |
| 52 | } |
| 53 | } |
| 54 | b.P = perm |
David Why Use Two When One Will Do Presotto | c74ac70 | 2015-05-07 15:33:52 -0700 | [diff] [blame] | 55 | // Increment with possible wrap. |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 56 | b.V++ |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 57 | if b.V < 0 { |
| 58 | b.V = 0 |
| 59 | } |
| 60 | return b, nil |
| 61 | } |
| 62 | |
| 63 | // Get returns the current Version and Permissions. |
| 64 | func (b *VersionedPermissions) Get() (string, access.Permissions) { |
| 65 | if b == nil { |
| 66 | return "", nil |
| 67 | } |
| 68 | return strconv.FormatInt(int64(b.V), 10), b.P |
| 69 | } |
| 70 | |
| 71 | // AccessListForTag returns the current access list for the given tag. |
| 72 | func (b *VersionedPermissions) AccessListForTag(tag string) (access.AccessList, bool) { |
| 73 | al, exists := b.P[tag] |
| 74 | return al, exists |
| 75 | } |
| 76 | |
| 77 | // Copy copies the receiver. |
| 78 | func (b *VersionedPermissions) Copy() *VersionedPermissions { |
| 79 | nt := new(VersionedPermissions) |
| 80 | nt.P = b.P.Copy() |
| 81 | nt.V = b.V |
| 82 | return nt |
| 83 | } |
| 84 | |
| 85 | // Add adds the blessing pattern to the tag in the reciever. |
| 86 | func (b *VersionedPermissions) Add(pattern security.BlessingPattern, tag string) { |
| 87 | b.P.Add(pattern, tag) |
| 88 | } |
| 89 | |
| 90 | // parsePermFile reads a file and parses the contained permissions. |
Cosmos Nicolaou | 19a50f6 | 2015-06-20 09:15:40 -0700 | [diff] [blame] | 91 | func (mt *mountTable) parsePermFile(ctx *context.T, path string) error { |
| 92 | ctx.VI(2).Infof("parsePermFile(%s)", path) |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 93 | if path == "" { |
| 94 | return nil |
| 95 | } |
| 96 | // A map from node name to permissions. |
| 97 | var pm map[string]access.Permissions |
| 98 | f, err := os.Open(path) |
| 99 | if err != nil { |
| 100 | return err |
| 101 | } |
| 102 | defer f.Close() |
| 103 | decoder := json.NewDecoder(f) |
| 104 | for { |
| 105 | if err = decoder.Decode(&pm); err != nil { |
| 106 | if err == io.EOF { |
| 107 | break |
| 108 | } |
| 109 | return err |
| 110 | } |
David Why Use Two When One Will Do Presotto | 30f7a11 | 2015-08-17 09:39:33 -0700 | [diff] [blame] | 111 | cc := &callContext{ctx: ctx, |
| 112 | creatorSet: true, |
| 113 | create: true, |
| 114 | ignorePerms: true, |
| 115 | ignoreLimits: true, |
| 116 | } |
David Why Use Two When One Will Do Presotto | e3e932c | 2015-05-15 14:59:46 -0700 | [diff] [blame] | 117 | // Sort the map shortest key first. That way configs for nodes higher up in the |
| 118 | // name tree happen first ensuring that lower nodes correctly inherit permissions. |
| 119 | var keys []string |
| 120 | for name := range pm { |
| 121 | keys = append(keys, name) |
| 122 | } |
| 123 | sort.Strings(keys) |
| 124 | for _, name := range keys { |
| 125 | perms := pm[name] |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 126 | var elems []string |
| 127 | isPattern := false |
| 128 | |
| 129 | // The configuration file allows patterns and also will cause the superuser to |
| 130 | // be set to the root's administrator. |
| 131 | if len(name) == 0 { |
| 132 | // If the config file has is an Admin tag on the root AccessList, the |
| 133 | // list of Admin users is the equivalent of a super user for |
| 134 | // the whole table. Later SetPermissions do not update the set |
| 135 | // of super users. |
| 136 | if bp, exists := perms[string(mounttable.Admin)]; exists { |
| 137 | mt.superUsers = bp |
| 138 | } |
| 139 | } else { |
| 140 | // AccessList templates terminate with a %% element. These are very |
| 141 | // constrained matches, i.e., the trailing element of the name |
| 142 | // is copied into every %% in the AccessList. |
| 143 | elems = strings.Split(name, "/") |
| 144 | if elems[len(elems)-1] == templateVar { |
| 145 | isPattern = true |
| 146 | elems = elems[:len(elems)-1] |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | // Create name and add the Permissions map to it. |
David Why Use Two When One Will Do Presotto | 30f7a11 | 2015-08-17 09:39:33 -0700 | [diff] [blame] | 151 | cc.creator = mt.pickCreator(ctx, nil) |
| 152 | n, err := mt.findNode(cc, elems, nil, nil) |
David Why Use Two When One Will Do Presotto | e0a71c7 | 2015-08-10 10:31:54 -0700 | [diff] [blame] | 153 | if err != nil { |
| 154 | ctx.Errorf("skipping node for %v; error: %v", elems, err) |
| 155 | } |
| 156 | if n == nil { |
| 157 | continue |
| 158 | } |
| 159 | if err == nil { |
Cosmos Nicolaou | 19a50f6 | 2015-06-20 09:15:40 -0700 | [diff] [blame] | 160 | ctx.VI(2).Infof("added perms %v to %s", perms, name) |
David Why Use Two When One Will Do Presotto | ba9593f | 2015-04-22 12:29:26 -0700 | [diff] [blame] | 161 | if isPattern { |
| 162 | n.permsTemplate = perms |
| 163 | } else { |
| 164 | n.vPerms, _ = n.vPerms.Set(nil, "", perms) |
| 165 | n.explicitPermissions = true |
| 166 | } |
| 167 | } |
| 168 | n.parent.Unlock() |
| 169 | n.Unlock() |
| 170 | } |
| 171 | } |
| 172 | return nil |
| 173 | } |
David Why Use Two When One Will Do Presotto | c74ac70 | 2015-05-07 15:33:52 -0700 | [diff] [blame] | 174 | |
David Why Use Two When One Will Do Presotto | 67b7071 | 2015-06-02 13:13:58 -0700 | [diff] [blame] | 175 | // pickCreator returns a string matching the blessing of the user performing the creation. |
David Why Use Two When One Will Do Presotto | c74ac70 | 2015-05-07 15:33:52 -0700 | [diff] [blame] | 176 | func (mt *mountTable) pickCreator(ctx *context.T, call security.Call) string { |
David Why Use Two When One Will Do Presotto | 67b7071 | 2015-06-02 13:13:58 -0700 | [diff] [blame] | 177 | ids := conventions.GetClientUserIds(ctx, call) |
| 178 | // Replace the slashes with something else or we'll confuse the stats package. |
| 179 | return strings.Replace(ids[0], "/", "\\", 0) |
David Why Use Two When One Will Do Presotto | c74ac70 | 2015-05-07 15:33:52 -0700 | [diff] [blame] | 180 | } |