blob: bb2debdbc7fb46d40f59847f2943e4b09dade40a [file] [log] [blame]
Ankurcf6a89f2014-10-06 18:33:03 -07001package main
2
3import (
4 "bytes"
Asim Shankarf11b1bc2014-11-12 17:18:45 -08005 "crypto/rand"
6 "crypto/subtle"
Asim Shankarb3a82ba2014-10-29 11:41:27 -07007 "encoding/base64"
Ankurcf6a89f2014-10-06 18:33:03 -07008 "errors"
9 "fmt"
10 "io"
11 "os"
12 "os/user"
13 "time"
14
Jiri Simsa764efb72014-12-25 20:57:03 -080015 profile "v.io/core/veyron/profiles/static"
16 vsecurity "v.io/core/veyron/security"
17 "v.io/core/veyron/services/identity"
18 "v.io/core/veyron2"
Matt Rosencrantz89445a42015-01-05 13:32:37 -080019 "v.io/core/veyron2/context"
Jiri Simsa764efb72014-12-25 20:57:03 -080020 "v.io/core/veyron2/ipc"
Jiri Simsa764efb72014-12-25 20:57:03 -080021 "v.io/core/veyron2/rt"
22 "v.io/core/veyron2/security"
Todd Wang3425a902015-01-21 18:43:59 -080023 "v.io/core/veyron2/vom"
Todd Wang478fcf92014-12-26 12:37:37 -080024 "v.io/lib/cmdline"
Ankurcf6a89f2014-10-06 18:33:03 -070025)
26
27var (
28 // Flags for the "blessself" command
Asim Shankar66c52f92014-10-15 23:39:10 -070029 flagBlessSelfFor time.Duration
Ankurcf6a89f2014-10-06 18:33:03 -070030
Asim Shankar66c52f92014-10-15 23:39:10 -070031 // Flags for the "bless" command
Asim Shankarf11b1bc2014-11-12 17:18:45 -080032 flagBlessFor time.Duration
33 flagBlessWith string
34 flagBlessRemoteKey string
35 flagBlessRemoteToken string
Asim Shankar66c52f92014-10-15 23:39:10 -070036
Ankur77c32ac2014-12-18 14:18:19 -080037 // Flags for the "fork" command
38 flagForkFor time.Duration
39 flagForkWith string
40
Asim Shankar66c52f92014-10-15 23:39:10 -070041 // Flags for the "seekblessings" command
42 flagSeekBlessingsFrom string
43 flagSeekBlessingsSetDefault bool
44 flagSeekBlessingsForPeer string
Suharsh Sivakumara76dba62014-12-22 16:00:34 -080045 flagSeekBlessingsBrowser bool
Asim Shankar66c52f92014-10-15 23:39:10 -070046
47 // Flags common to many commands
Ankurc24ff422014-12-16 17:59:26 -080048 flagAddToRoots bool
49 flagCreateOverwrite bool
Ankur1d46f552014-10-09 12:13:31 -070050
Ankure548f392014-12-08 18:42:41 -080051 // Flags for the "recvblessings" command
52 flagRecvBlessingsSetDefault bool
53 flagRecvBlessingsForPeer string
54
Ankur1615a7d2014-10-09 11:58:02 -070055 cmdDump = &cmdline.Command{
56 Name: "dump",
57 Short: "Dump out information about the principal",
58 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070059Prints out information about the principal specified by the environment
Asim Shankar1789b8a2014-10-31 17:31:41 -070060that this tool is running in.
Ankur1615a7d2014-10-09 11:58:02 -070061`,
62 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantz574d5e12014-11-26 10:01:37 -080063 runtime, err := rt.New()
64 if err != nil {
65 panic(err)
66 }
67 defer runtime.Cleanup()
68
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -080069 p := veyron2.GetPrincipal(runtime.NewContext())
Ankur1615a7d2014-10-09 11:58:02 -070070 fmt.Printf("Public key : %v\n", p.PublicKey())
Ankur1615a7d2014-10-09 11:58:02 -070071 fmt.Println("---------------- BlessingStore ----------------")
72 fmt.Printf("%v", p.BlessingStore().DebugString())
Ankur1615a7d2014-10-09 11:58:02 -070073 fmt.Println("---------------- BlessingRoots ----------------")
74 fmt.Printf("%v", p.Roots().DebugString())
75 return nil
76 },
77 }
78
Asim Shankar66c52f92014-10-15 23:39:10 -070079 cmdDumpBlessings = &cmdline.Command{
80 Name: "dumpblessings",
81 Short: "Dump out information about the provided blessings",
Ankurcf6a89f2014-10-06 18:33:03 -070082 Long: `
Asim Shankar66c52f92014-10-15 23:39:10 -070083Prints out information about the blessings (typically obtained from this tool)
Ankurcf6a89f2014-10-06 18:33:03 -070084encoded in the provided file.
85`,
86 ArgsName: "<file>",
87 ArgsLong: `
Asim Shankar66c52f92014-10-15 23:39:10 -070088<file> is the path to a file containing blessings typically obtained from
Ankurcf6a89f2014-10-06 18:33:03 -070089this tool. - is used for STDIN.
90`,
91 Run: func(cmd *cmdline.Command, args []string) error {
92 if len(args) != 1 {
93 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
94 }
95 blessings, err := decodeBlessings(args[0])
96 if err != nil {
97 return fmt.Errorf("failed to decode provided blessings: %v", err)
98 }
Asim Shankar66c52f92014-10-15 23:39:10 -070099 wire := security.MarshalBlessings(blessings)
100 fmt.Printf("Blessings : %v\n", blessings)
101 fmt.Printf("PublicKey : %v\n", blessings.PublicKey())
Asim Shankardf88a2e2014-10-21 17:20:28 -0700102 fmt.Printf("Certificate chains : %d\n", len(wire.CertificateChains))
Asim Shankar66c52f92014-10-15 23:39:10 -0700103 for idx, chain := range wire.CertificateChains {
Asim Shankardf88a2e2014-10-21 17:20:28 -0700104 fmt.Printf("Chain #%d (%d certificates). Root certificate public key: %v\n", idx, len(chain), rootkey(chain))
105 for certidx, cert := range chain {
106 fmt.Printf(" Certificate #%d: %v with ", certidx, cert.Extension)
107 switch n := len(cert.Caveats); n {
108 case 1:
109 fmt.Printf("1 caveat")
110 default:
111 fmt.Printf("%d caveats", n)
112 }
113 fmt.Println("")
114 for cavidx, cav := range cert.Caveats {
115 fmt.Printf(" (%d) %v\n", cavidx, &cav)
116 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700117 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700118 }
Ankurcf6a89f2014-10-06 18:33:03 -0700119 return nil
120 },
121 }
122
123 cmdBlessSelf = &cmdline.Command{
124 Name: "blessself",
125 Short: "Generate a self-signed blessing",
126 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700127Returns a blessing with name <name> and self-signed by the principal specified
128by the environment that this tool is running in. Optionally, the blessing can
129be restricted with an expiry caveat specified using the --for flag.
Ankurcf6a89f2014-10-06 18:33:03 -0700130`,
131 ArgsName: "[<name>]",
132 ArgsLong: `
133<name> is the name used to create the self-signed blessing. If not
134specified, a name will be generated based on the hostname of the
135machine and the name of the user running this command.
136`,
137 Run: func(cmd *cmdline.Command, args []string) error {
Ankurcf6a89f2014-10-06 18:33:03 -0700138 var name string
139 switch len(args) {
140 case 0:
141 name = defaultBlessingName()
142 case 1:
143 name = args[0]
144 default:
145 return fmt.Errorf("requires at most one argument, provided %d", len(args))
146 }
147
148 var caveats []security.Caveat
Asim Shankar66c52f92014-10-15 23:39:10 -0700149 if flagBlessSelfFor != 0 {
150 cav, err := security.ExpiryCaveat(time.Now().Add(flagBlessSelfFor))
Ankurcf6a89f2014-10-06 18:33:03 -0700151 if err != nil {
Ankur8d304122014-10-07 10:43:43 -0700152 return fmt.Errorf("failed to create expiration Caveat: %v", err)
Ankurcf6a89f2014-10-06 18:33:03 -0700153 }
154 caveats = append(caveats, cav)
155 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800156
157 runtime, err := rt.New()
158 if err != nil {
159 panic(err)
160 }
161 defer runtime.Cleanup()
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800162 principal := veyron2.GetPrincipal(runtime.NewContext())
163 blessing, err := principal.BlessSelf(name, caveats...)
Ankurcf6a89f2014-10-06 18:33:03 -0700164 if err != nil {
165 return fmt.Errorf("failed to create self-signed blessing for name %q: %v", name, err)
166 }
167
168 return dumpBlessings(blessing)
169 },
170 }
171
Asim Shankar66c52f92014-10-15 23:39:10 -0700172 cmdBless = &cmdline.Command{
173 Name: "bless",
174 Short: "Bless another principal",
175 Long: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800176Bless another principal.
Asim Shankar66c52f92014-10-15 23:39:10 -0700177
Ankurc24ff422014-12-16 17:59:26 -0800178The blesser is obtained from the runtime this tool is using. The blessing that
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800179will be extended is the default one from the blesser's store, or specified by
180the --with flag. Caveats on the blessing are controlled via the --for flag.
Asim Shankar66c52f92014-10-15 23:39:10 -0700181
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800182For example, let's say a principal "alice" wants to bless another principal "bob"
183as "alice/friend", the invocation would be:
184 VEYRON_CREDENTIALS=<path to alice> principal bless <path to bob> friend
185and this will dump the blessing to STDOUT.
186
187With the --remote_key and --remote_token flags, this command can be used to
188bless a principal on a remote machine as well. In this case, the blessing is
189not dumped to STDOUT but sent to the remote end. Use 'principal help
190recvblessings' for more details on that.
191`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700192 ArgsName: "<principal to bless> <extension>",
193 ArgsLong: `
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800194<principal to bless> represents the principal to be blessed (i.e., whose public
195key will be provided with a name). This can be either:
196(a) The directory containing credentials for that principal,
197OR
198(b) The filename (- for STDIN) containing any other blessings of that
199 principal,
200OR
201(c) The object name produced by the 'recvblessings' command of this tool
202 running on behalf of another principal (if the --remote_key and
203 --remote_token flags are specified).
Asim Shankar66c52f92014-10-15 23:39:10 -0700204
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800205<extension> is the string extension that will be applied to create the
206blessing.
Asim Shankar66c52f92014-10-15 23:39:10 -0700207 `,
208 Run: func(cmd *cmdline.Command, args []string) error {
209 if len(args) != 2 {
210 return fmt.Errorf("require exactly two arguments, provided %d", len(args))
211 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800212
213 runtime, err := rt.New()
214 if err != nil {
215 panic(err)
216 }
217 defer runtime.Cleanup()
218
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800219 p := veyron2.GetPrincipal(runtime.NewContext())
Asim Shankar66c52f92014-10-15 23:39:10 -0700220
221 var with security.Blessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800222 var caveats []security.Caveat
Asim Shankar66c52f92014-10-15 23:39:10 -0700223 if len(flagBlessWith) > 0 {
224 if with, err = decodeBlessings(flagBlessWith); err != nil {
225 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
226 }
227 } else {
228 with = p.BlessingStore().Default()
229 }
230
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800231 if c, err := security.ExpiryCaveat(time.Now().Add(flagBlessFor)); err != nil {
232 return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
233 } else {
234 caveats = append(caveats, c)
235 }
236 // TODO(ashankar,ataly,suharshs): Work out how to add additional caveats, like maybe
237 // revocation, method etc.
Asim Shankar66c52f92014-10-15 23:39:10 -0700238 tobless, extension := args[0], args[1]
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800239 if (len(flagBlessRemoteKey) == 0) != (len(flagBlessRemoteToken) == 0) {
240 return fmt.Errorf("either both --remote_key and --remote_token should be set, or neither should")
241 }
242 if len(flagBlessRemoteKey) > 0 {
243 // Send blessings to a "server" started by a "recvblessings" command
244 granter := &granter{p, with, extension, caveats, flagBlessRemoteKey}
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800245 return sendBlessings(runtime.NewContext(), tobless, granter, flagBlessRemoteToken)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800246 }
247 // Blessing a principal whose key is available locally.
248 var key security.PublicKey
Asim Shankar66c52f92014-10-15 23:39:10 -0700249 if finfo, err := os.Stat(tobless); err == nil && finfo.IsDir() {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700250 other, err := vsecurity.LoadPersistentPrincipal(tobless, nil)
Asim Shankar66c52f92014-10-15 23:39:10 -0700251 if err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700252 if other, err = vsecurity.CreatePersistentPrincipal(tobless, nil); err != nil {
253 return fmt.Errorf("failed to read principal in directory %q: %v", tobless, err)
254 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700255 }
256 key = other.PublicKey()
257 } else if other, err := decodeBlessings(tobless); err != nil {
258 return fmt.Errorf("failed to decode blessings in %q: %v", tobless, err)
259 } else {
260 key = other.PublicKey()
261 }
262
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800263 blessings, err := p.Bless(key, with, extension, caveats[0], caveats[1:]...)
Asim Shankar66c52f92014-10-15 23:39:10 -0700264 if err != nil {
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800265 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700266 }
267 return dumpBlessings(blessings)
268 },
269 }
270
271 cmdStoreForPeer = &cmdline.Command{
272 Name: "forpeer",
Ankurcf6a89f2014-10-06 18:33:03 -0700273 Short: "Return blessings marked for the provided peer",
274 Long: `
275Returns blessings that are marked for the provided peer in the
Asim Shankar1789b8a2014-10-31 17:31:41 -0700276BlessingStore specified by the environment that this tool is
277running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700278`,
279 ArgsName: "[<peer_1> ... <peer_k>]",
280 ArgsLong: `
281<peer_1> ... <peer_k> are the (human-readable string) blessings bound
282to the peer. The returned blessings are marked with a pattern that is
283matched by at least one of these. If no arguments are specified,
284store.forpeer returns the blessings that are marked for all peers (i.e.,
285blessings set on the store with the "..." pattern).
286`,
287 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800288 runtime, err := rt.New()
289 if err != nil {
290 panic(err)
291 }
292 defer runtime.Cleanup()
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800293 principal := veyron2.GetPrincipal(runtime.NewContext())
294 return dumpBlessings(principal.BlessingStore().ForPeer(args...))
Ankurcf6a89f2014-10-06 18:33:03 -0700295 },
296 }
297
Asim Shankar66c52f92014-10-15 23:39:10 -0700298 cmdStoreDefault = &cmdline.Command{
299 Name: "default",
Ankurcf6a89f2014-10-06 18:33:03 -0700300 Short: "Return blessings marked as default",
301 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700302Returns blessings that are marked as default in the BlessingStore specified by
303the environment that this tool is running in.
Ankurcf6a89f2014-10-06 18:33:03 -0700304`,
305 Run: func(cmd *cmdline.Command, args []string) error {
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800306 runtime, err := rt.New()
307 if err != nil {
308 panic(err)
309 }
310 defer runtime.Cleanup()
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800311 principal := veyron2.GetPrincipal(runtime.NewContext())
312 return dumpBlessings(principal.BlessingStore().Default())
Ankurcf6a89f2014-10-06 18:33:03 -0700313 },
314 }
Ankur8d304122014-10-07 10:43:43 -0700315
Asim Shankar66c52f92014-10-15 23:39:10 -0700316 cmdStoreSet = &cmdline.Command{
317 Name: "set",
Ankur8d304122014-10-07 10:43:43 -0700318 Short: "Set provided blessings for peer",
319 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700320Marks the provided blessings to be shared with the provided peers on the
321BlessingStore specified by the environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700322
323'set b pattern' marks the intention to reveal b to peers who
324present blessings of their own matching 'pattern'.
325
326'set nil pattern' can be used to remove the blessings previously
327associated with the pattern (by a prior 'set' command).
328
329It is an error to call 'store.set' with blessings whose public
330key does not match the public key of this principal specified
331by the environment.
332`,
333 ArgsName: "<file> <pattern>",
334 ArgsLong: `
335<file> is the path to a file containing a blessing typically obtained
336from this tool. - is used for STDIN.
337
338<pattern> is the BlessingPattern used to identify peers with whom this
339blessing can be shared with.
340`,
341 Run: func(cmd *cmdline.Command, args []string) error {
342 if len(args) != 2 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700343 return fmt.Errorf("requires exactly two arguments <file>, <pattern>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700344 }
345 blessings, err := decodeBlessings(args[0])
346 if err != nil {
347 return fmt.Errorf("failed to decode provided blessings: %v", err)
348 }
349 pattern := security.BlessingPattern(args[1])
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800350
351 runtime, err := rt.New()
352 if err != nil {
353 panic(err)
354 }
355 defer runtime.Cleanup()
356
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800357 p := veyron2.GetPrincipal(runtime.NewContext())
Asim Shankar66c52f92014-10-15 23:39:10 -0700358 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700359 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
360 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700361 if flagAddToRoots {
362 if err := p.AddToRoots(blessings); err != nil {
363 return fmt.Errorf("AddToRoots failed: %v", err)
364 }
365 }
Ankur8d304122014-10-07 10:43:43 -0700366 return nil
367 },
368 }
369
Mike Burrows367515e2014-12-02 11:30:18 -0800370 cmdStoreAddToRoots = &cmdline.Command{
371 Name: "addtoroots",
372 Short: "Add provided blessings to root set",
373 Long: `
374Adds the provided blessings to the set of trusted roots for this principal.
375
376'addtoroots b' adds blessings b to the trusted root set.
377
378For example, to make the principal in credentials directory A trust the
379root of the default blessing in credentials directory B:
380 principal -veyron.credentials=B bless A some_extension |
381 principal -veyron.credentials=A store addtoroots -
382
383The extension 'some_extension' has no effect in the command above.
384`,
385 ArgsName: "<file>",
386 ArgsLong: `
387<file> is the path to a file containing a blessing typically obtained
388from this tool. - is used for STDIN.
389`,
390 Run: func(cmd *cmdline.Command, args []string) error {
391 if len(args) != 1 {
392 return fmt.Errorf("requires exactly one argument <file>, provided %d", len(args))
393 }
394 blessings, err := decodeBlessings(args[0])
395 if err != nil {
396 return fmt.Errorf("failed to decode provided blessings: %v", err)
397 }
398
399 runtime, err := rt.New()
400 if err != nil {
401 panic(err)
402 }
403 defer runtime.Cleanup()
404
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800405 p := veyron2.GetPrincipal(runtime.NewContext())
Mike Burrows367515e2014-12-02 11:30:18 -0800406 if err := p.AddToRoots(blessings); err != nil {
407 return fmt.Errorf("AddToRoots failed: %v", err)
408 }
409 return nil
410 },
411 }
412
Asim Shankar66c52f92014-10-15 23:39:10 -0700413 cmdStoreSetDefault = &cmdline.Command{
414 Name: "setdefault",
Ankur8d304122014-10-07 10:43:43 -0700415 Short: "Set provided blessings as default",
416 Long: `
Asim Shankar1789b8a2014-10-31 17:31:41 -0700417Sets the provided blessings as default in the BlessingStore specified by the
418environment that this tool is running in.
Ankur8d304122014-10-07 10:43:43 -0700419
Asim Shankar1789b8a2014-10-31 17:31:41 -0700420It is an error to call 'store.setdefault' with blessings whose public key does
421not match the public key of the principal specified by the environment.
Ankur8d304122014-10-07 10:43:43 -0700422`,
423 ArgsName: "<file>",
424 ArgsLong: `
425<file> is the path to a file containing a blessing typically obtained from
426this tool. - is used for STDIN.
427`,
428 Run: func(cmd *cmdline.Command, args []string) error {
429 if len(args) != 1 {
Asim Shankar66c52f92014-10-15 23:39:10 -0700430 return fmt.Errorf("requires exactly one argument, <file>, provided %d", len(args))
Ankur8d304122014-10-07 10:43:43 -0700431 }
432 blessings, err := decodeBlessings(args[0])
433 if err != nil {
434 return fmt.Errorf("failed to decode provided blessings: %v", err)
435 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800436
437 runtime, err := rt.New()
438 if err != nil {
439 panic(err)
440 }
441 defer runtime.Cleanup()
442
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800443 p := veyron2.GetPrincipal(runtime.NewContext())
Asim Shankar1789b8a2014-10-31 17:31:41 -0700444 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur8d304122014-10-07 10:43:43 -0700445 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
446 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700447 if flagAddToRoots {
448 if err := p.AddToRoots(blessings); err != nil {
449 return fmt.Errorf("AddToRoots failed: %v", err)
450 }
451 }
452 return nil
453 },
454 }
455
456 cmdCreate = &cmdline.Command{
457 Name: "create",
458 Short: "Create a new principal and persist it into a directory",
459 Long: `
Ankur4704f5f2014-10-23 12:40:54 -0700460Creates a new principal with a single self-blessed blessing and writes it out
Ankurc24ff422014-12-16 17:59:26 -0800461to the provided directory. The same directory can then be used to set the
462VEYRON_CREDENTIALS environment variable for other veyron applications.
Ankur4704f5f2014-10-23 12:40:54 -0700463
464The operation fails if the directory already contains a principal. In this case
Ankurc24ff422014-12-16 17:59:26 -0800465the --overwrite flag can be provided to clear the directory and write out the
gauthamtb7bb39b2014-11-10 11:40:41 -0800466new principal.
Ankur4704f5f2014-10-23 12:40:54 -0700467`,
Asim Shankar66c52f92014-10-15 23:39:10 -0700468 ArgsName: "<directory> <blessing>",
469 ArgsLong: `
Ankurc24ff422014-12-16 17:59:26 -0800470 <directory> is the directory to which the new principal will be persisted.
Asim Shankar66c52f92014-10-15 23:39:10 -0700471 <blessing> is the self-blessed blessing that the principal will be setup to use by default.
472 `,
473 Run: func(cmd *cmdline.Command, args []string) error {
474 if len(args) != 2 {
475 return fmt.Errorf("requires exactly two arguments: <directory> and <blessing>, provided %d", len(args))
476 }
477 dir, name := args[0], args[1]
Ankur4704f5f2014-10-23 12:40:54 -0700478 if flagCreateOverwrite {
Ankurc24ff422014-12-16 17:59:26 -0800479 if err := os.RemoveAll(dir); err != nil {
gauthamtb7bb39b2014-11-10 11:40:41 -0800480 return err
481 }
Ankur4704f5f2014-10-23 12:40:54 -0700482 }
Ankurc24ff422014-12-16 17:59:26 -0800483 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700484 if err != nil {
485 return err
Asim Shankar66c52f92014-10-15 23:39:10 -0700486 }
487 blessings, err := p.BlessSelf(name)
488 if err != nil {
489 return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
490 }
Ankurc24ff422014-12-16 17:59:26 -0800491 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
492 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700493 }
Ankurc24ff422014-12-16 17:59:26 -0800494 return nil
495 },
496 }
497
498 cmdFork = &cmdline.Command{
499 Name: "fork",
500 Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
501 Long: `
502Creates a new principal with a blessing from the principal specified by the
503environment that this tool is running in, and writes it out to the provided
504directory. The blessing that will be extended is the default one from the
505blesser's store, or specified by the --with flag. Caveats on the blessing
506are controlled via the --for flag. The blessing is marked as default and
507shareable with all peers on the new principal's blessing store.
508
509The operation fails if the directory already contains a principal. In this case
510the --overwrite flag can be provided to clear the directory and write out the
511forked principal.
512`,
513 ArgsName: "<directory> <extension>",
514 ArgsLong: `
515 <directory> is the directory to which the forked principal will be persisted.
516 <extension> is the extension under which the forked principal is blessed.
517 `,
518 Run: func(cmd *cmdline.Command, args []string) error {
519 if len(args) != 2 {
520 return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
Asim Shankar66c52f92014-10-15 23:39:10 -0700521 }
Ankurc24ff422014-12-16 17:59:26 -0800522 dir, extension := args[0], args[1]
523
524 if flagCreateOverwrite {
525 if err := os.RemoveAll(dir); err != nil {
526 return err
527 }
528 }
529 p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
530 if err != nil {
531 return err
532 }
533
534 runtime, err := rt.New()
535 if err != nil {
536 return err
537 }
538 defer runtime.Cleanup()
539
540 var (
541 with security.Blessings
542 caveats []security.Caveat
543 )
Ankur77c32ac2014-12-18 14:18:19 -0800544 if len(flagForkWith) > 0 {
545 if with, err = decodeBlessings(flagForkWith); err != nil {
546 return fmt.Errorf("failed to read blessings from --with=%q: %v", flagForkWith, err)
Ankurc24ff422014-12-16 17:59:26 -0800547 }
548 } else {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800549 with = veyron2.GetPrincipal(runtime.NewContext()).BlessingStore().Default()
Ankurc24ff422014-12-16 17:59:26 -0800550 }
Ankur77c32ac2014-12-18 14:18:19 -0800551 if c, err := security.ExpiryCaveat(time.Now().Add(flagForkFor)); err != nil {
Ankurc24ff422014-12-16 17:59:26 -0800552 return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
553 } else {
554 caveats = append(caveats, c)
555 }
556 // TODO(ashankar,ataly,suharshs): Work out how to add additional caveats, like maybe
557 // revocation, method etc.
558
559 key := p.PublicKey()
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800560 rp := veyron2.GetPrincipal(runtime.NewContext())
561 blessings, err := rp.Bless(key, with, extension, caveats[0], caveats[1:]...)
Ankurc24ff422014-12-16 17:59:26 -0800562 if err != nil {
563 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
564 }
565 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
566 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700567 }
Ankur8d304122014-10-07 10:43:43 -0700568 return nil
569 },
570 }
Ankur1d46f552014-10-09 12:13:31 -0700571
572 cmdSeekBlessings = &cmdline.Command{
573 Name: "seekblessings",
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800574 Short: "Seek blessings from a web-based Veyron blessing service",
Ankur1d46f552014-10-09 12:13:31 -0700575 Long: `
576Seeks blessings from a web-based Veyron blesser which
577requires the caller to first authenticate with Google using OAuth. Simply
578run the command to see what happens.
579
Asim Shankar1789b8a2014-10-31 17:31:41 -0700580The blessings are sought for the principal specified by the environment that
581this tool is running in.
Ankur1d46f552014-10-09 12:13:31 -0700582
Ankure548f392014-12-08 18:42:41 -0800583The blessings obtained are set as default, unless the --set_default flag is
584set to true, and are also set for sharing with all peers, unless a more
Ankur1d46f552014-10-09 12:13:31 -0700585specific peer pattern is provided using the --for_peer flag.
586`,
587 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700588 // Initialize the runtime first so that any local errors are reported
589 // before the HTTP roundtrips for obtaining the macaroon begin.
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800590 runtime, err := rt.New()
591 if err != nil {
592 panic(err)
593 }
594 defer runtime.Cleanup()
595
Ankur1d46f552014-10-09 12:13:31 -0700596 blessedChan := make(chan string)
597 defer close(blessedChan)
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800598 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
Ankur1d46f552014-10-09 12:13:31 -0700599 if err != nil {
600 return fmt.Errorf("failed to get macaroon from Veyron blesser: %v", err)
601 }
602 macaroon := <-macaroonChan
603 service := <-macaroonChan
Matt Rosencrantz89445a42015-01-05 13:32:37 -0800604 ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
Ankur1d46f552014-10-09 12:13:31 -0700605 defer cancel()
606
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700607 var reply security.WireBlessings
Todd Wang702385a2014-11-07 01:54:08 -0800608 reply, err = identity.MacaroonBlesserClient(service).Bless(ctx, macaroon)
Ankur1d46f552014-10-09 12:13:31 -0700609 if err != nil {
610 return fmt.Errorf("failed to get blessing from %q: %v", service, err)
611 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700612 blessings, err := security.NewBlessings(reply)
Ankur1d46f552014-10-09 12:13:31 -0700613 if err != nil {
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700614 return fmt.Errorf("failed to construct Blessings object from response: %v", err)
Ankur1d46f552014-10-09 12:13:31 -0700615 }
616 blessedChan <- fmt.Sprint(blessings)
617 // Wait for getTokenForBlessRPC to clean up:
618 <-macaroonChan
619
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800620 p := veyron2.GetPrincipal(runtime.NewContext())
621
Asim Shankar66c52f92014-10-15 23:39:10 -0700622 if flagSeekBlessingsSetDefault {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800623 if err := p.BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700624 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
625 }
626 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700627 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800628 if _, err := p.BlessingStore().Set(blessings, pattern); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700629 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
630 }
631 }
632 if flagAddToRoots {
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800633 if err := p.AddToRoots(blessings); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700634 return fmt.Errorf("AddToRoots failed: %v", err)
635 }
Ankur1d46f552014-10-09 12:13:31 -0700636 }
637 return dumpBlessings(blessings)
638 },
639 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800640
641 cmdRecvBlessings = &cmdline.Command{
642 Name: "recvblessings",
643 Short: "Receive blessings sent by another principal and use them as the default",
644 Long: `
645Allow another principal (likely a remote process) to bless this one.
646
647This command sets up the invoker (this process) to wait for a blessing
648from another invocation of this tool (remote process) and prints out the
649command to be run as the remote principal.
650
Ankure548f392014-12-08 18:42:41 -0800651The received blessings are set as default, unless the --set_default flag is
652set to true, and are also set for sharing with all peers, unless a more
653specific peer pattern is provided using the --for_peer flag.
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800654
655TODO(ashankar,cnicolaou): Make this next paragraph possible! Requires
656the ability to obtain the proxied endpoint.
657
658Typically, this command should require no arguments.
659However, if the sender and receiver are on different network domains, it may
660make sense to use the --veyron.proxy flag:
Robin Thellend8fea01c2014-12-11 13:48:10 -0800661 principal --veyron.proxy=proxy recvblessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800662
663The command to be run at the sender is of the form:
664 principal bless --remote_key=KEY --remote_token=TOKEN ADDRESS
665
666The --remote_key flag is used to by the sender to "authenticate" the receiver,
667ensuring it blesses the intended recipient and not any attacker that may have
668taken over the address.
669
670The --remote_token flag is used by the sender to authenticate itself to the
671receiver. This helps ensure that the receiver rejects blessings from senders
672who just happened to guess the network address of the 'recvblessings'
673invocation.
674`,
675 Run: func(cmd *cmdline.Command, args []string) error {
676 if len(args) != 0 {
677 return fmt.Errorf("command accepts no arguments")
678 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800679
680 runtime, err := rt.New()
681 if err != nil {
682 panic(err)
683 }
684 defer runtime.Cleanup()
685
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800686 server, err := veyron2.NewServer(runtime.NewContext())
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800687 if err != nil {
688 return fmt.Errorf("failed to create server to listen for blessings: %v", err)
689 }
690 defer server.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800691 eps, err := server.Listen(profile.ListenSpec)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800692 if err != nil {
693 return fmt.Errorf("failed to setup listening: %v", err)
694 }
695 var token [24]byte
696 if _, err := rand.Read(token[:]); err != nil {
697 return fmt.Errorf("unable to generate token: %v", err)
698 }
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800699
700 p := veyron2.GetPrincipal(runtime.NewContext())
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800701 service := &recvBlessingsService{
Matt Rosencrantzf1c3b442015-01-12 17:53:08 -0800702 principal: p,
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800703 token: base64.URLEncoding.EncodeToString(token[:]),
704 notify: make(chan error),
705 }
706 if err := server.Serve("", service, allowAnyone{}); err != nil {
707 return fmt.Errorf("failed to setup service: %v", err)
708 }
709 // Proposed name:
710 extension := fmt.Sprintf("extension%d", int(token[0])<<16|int(token[1])<<8|int(token[2]))
711 fmt.Println("Run the following command on behalf of the principal that will send blessings:")
712 fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
713 fmt.Println("the --for flag, or change the extension to something more meaningful")
714 fmt.Println()
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800715 fmt.Printf("principal bless --remote_key=%v --remote_token=%v %v %v\n", p.PublicKey(), service.token, eps[0].Name(), extension)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800716 fmt.Println()
717 fmt.Println("...waiting for sender..")
718 return <-service.notify
719 },
720 }
Ankurcf6a89f2014-10-06 18:33:03 -0700721)
722
723func main() {
Asim Shankar66c52f92014-10-15 23:39:10 -0700724 cmdBlessSelf.Flags.DurationVar(&flagBlessSelfFor, "for", 0, "Duration of blessing validity (zero means no that the blessing is always valid)")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800725
Ankur77c32ac2014-12-18 14:18:19 -0800726 cmdFork.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
727 cmdFork.Flags.DurationVar(&flagForkFor, "for", 0, "Duration for which the forked blessing is valid (zero means no that the blessing is always valid)")
728 cmdFork.Flags.StringVar(&flagForkWith, "with", "", "Path to file containing blessing to extend")
729
Asim Shankar66c52f92014-10-15 23:39:10 -0700730 cmdBless.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800731 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
732 cmdBless.Flags.StringVar(&flagBlessRemoteKey, "remote_key", "", "Public key of the remote principal to bless (obtained from the 'recvblessings' command run by the remote principal")
733 cmdBless.Flags.StringVar(&flagBlessRemoteToken, "remote_token", "", "Token provided by principal running the 'recvblessings' command")
734
Robin Thellend8fea01c2014-12-11 13:48:10 -0800735 cmdSeekBlessings.Flags.StringVar(&flagSeekBlessingsFrom, "from", "https://auth.dev.v.io:8125/google", "URL to use to begin the seek blessings process")
Asim Shankar66c52f92014-10-15 23:39:10 -0700736 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
737 cmdSeekBlessings.Flags.StringVar(&flagSeekBlessingsForPeer, "for_peer", string(security.AllPrincipals), "If non-empty, the blessings obtained will be marked for peers matching this pattern in the store")
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800738 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsBrowser, "browser", true, "If false, the seekblessings command will not open the browser and only print the url to visit.")
Asim Shankar66c52f92014-10-15 23:39:10 -0700739 cmdSeekBlessings.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800740
Asim Shankar66c52f92014-10-15 23:39:10 -0700741 cmdStoreSet.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800742
Asim Shankar66c52f92014-10-15 23:39:10 -0700743 cmdStoreSetDefault.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800744
Ankur4704f5f2014-10-23 12:40:54 -0700745 cmdCreate.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
Asim Shankar66c52f92014-10-15 23:39:10 -0700746
Ankure548f392014-12-08 18:42:41 -0800747 cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
748 cmdRecvBlessings.Flags.StringVar(&flagRecvBlessingsForPeer, "for_peer", string(security.AllPrincipals), "If non-empty, the blessings received will be marked for peers matching this pattern in the store")
749
Asim Shankar66c52f92014-10-15 23:39:10 -0700750 cmdStore := &cmdline.Command{
751 Name: "store",
752 Short: "Manipulate and inspect the principal's blessing store",
753 Long: `
754Commands to manipulate and inspect the blessing store of the principal.
755
756All blessings are printed to stdout using base64-VOM-encoding
757`,
Mike Burrows367515e2014-12-02 11:30:18 -0800758 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet, cmdStoreAddToRoots},
Ankurcf6a89f2014-10-06 18:33:03 -0700759 }
Ankurcf6a89f2014-10-06 18:33:03 -0700760
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800761 root := &cmdline.Command{
Ankurcf6a89f2014-10-06 18:33:03 -0700762 Name: "principal",
763 Short: "Create and manage veyron principals",
764 Long: `
765The principal tool helps create and manage blessings and the set of trusted
766roots bound to a principal.
767
768All objects are printed using base64-VOM-encoding.
769`,
Ankurc24ff422014-12-16 17:59:26 -0800770 Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
Matt Rosencrantz92303e12015-01-21 09:02:42 -0800771 }
772 os.Exit(root.Main())
Ankurcf6a89f2014-10-06 18:33:03 -0700773}
774
Ankurcf6a89f2014-10-06 18:33:03 -0700775func decodeBlessings(fname string) (security.Blessings, error) {
776 var wire security.WireBlessings
777 if err := decode(fname, &wire); err != nil {
778 return nil, err
779 }
780 return security.NewBlessings(wire)
781}
782
783func dumpBlessings(blessings security.Blessings) error {
784 if blessings == nil {
785 return errors.New("no blessings found")
786 }
Ankuree0aa812014-11-14 10:56:52 -0800787 str, err := base64VomEncode(security.MarshalBlessings(blessings))
Ankurcf6a89f2014-10-06 18:33:03 -0700788 if err != nil {
789 return fmt.Errorf("base64-VOM encoding failed: %v", err)
790 }
791 fmt.Println(str)
792 return nil
793}
794
795func read(fname string) (string, error) {
796 if len(fname) == 0 {
797 return "", nil
798 }
799 f := os.Stdin
800 if fname != "-" {
801 var err error
802 if f, err = os.Open(fname); err != nil {
803 return "", fmt.Errorf("failed to open %q: %v", fname, err)
804 }
805 }
806 defer f.Close()
807 var buf bytes.Buffer
808 if _, err := io.Copy(&buf, f); err != nil {
809 return "", fmt.Errorf("failed to read %q: %v", fname, err)
810 }
811 return buf.String(), nil
812}
813
814func decode(fname string, val interface{}) error {
815 str, err := read(fname)
816 if err != nil {
817 return err
818 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700819 if err := base64VomDecode(str, val); err != nil || val == nil {
Ankurcf6a89f2014-10-06 18:33:03 -0700820 return fmt.Errorf("failed to decode %q: %v", fname, err)
821 }
822 return nil
823}
824
825func defaultBlessingName() string {
826 var name string
827 if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
828 name = user.Username
829 } else {
830 name = "anonymous"
831 }
832 if host, _ := os.Hostname(); len(host) > 0 {
833 name = name + "@" + host
834 }
835 return name
836}
Asim Shankardf88a2e2014-10-21 17:20:28 -0700837
838func rootkey(chain []security.Certificate) string {
839 if len(chain) == 0 {
840 return "<empty certificate chain>"
841 }
842 key, err := security.UnmarshalPublicKey(chain[0].PublicKey)
843 if err != nil {
844 return fmt.Sprintf("<invalid PublicKey: %v>", err)
845 }
846 return fmt.Sprintf("%v", key)
847}
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700848
849func base64VomEncode(i interface{}) (string, error) {
850 buf := &bytes.Buffer{}
851 closer := base64.NewEncoder(base64.URLEncoding, buf)
Todd Wang3425a902015-01-21 18:43:59 -0800852 enc, err := vom.NewBinaryEncoder(closer)
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800853 if err != nil {
854 return "", err
855 }
856 if err := enc.Encode(i); err != nil {
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700857 return "", err
858 }
859 // Must close the base64 encoder to flush out any partially written
860 // blocks.
861 if err := closer.Close(); err != nil {
862 return "", err
863 }
864 return buf.String(), nil
865}
866
867func base64VomDecode(s string, i interface{}) error {
868 b, err := base64.URLEncoding.DecodeString(s)
869 if err != nil {
870 return err
871 }
Todd Wang3425a902015-01-21 18:43:59 -0800872 dec, err := vom.NewDecoder(bytes.NewBuffer(b))
Suharsh Sivakumar12b089d2015-01-02 14:17:12 -0800873 if err != nil {
874 return err
875 }
876 return dec.Decode(i)
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700877}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800878
879type recvBlessingsService struct {
880 principal security.Principal
881 notify chan error
882 token string
883}
884
885func (r *recvBlessingsService) Grant(call ipc.ServerCall, token string) error {
886 b := call.Blessings()
887 if b == nil {
888 return fmt.Errorf("no blessings granted by sender")
889 }
890 if len(token) != len(r.token) {
891 // A timing attack can be used to figure out the length
892 // of the token, but then again, so can looking at the
893 // source code. So, it's okay.
894 return fmt.Errorf("blessings received from unexpected sender")
895 }
896 if subtle.ConstantTimeCompare([]byte(token), []byte(r.token)) != 1 {
897 return fmt.Errorf("blessings received from unexpected sender")
898 }
Ankure548f392014-12-08 18:42:41 -0800899 if flagRecvBlessingsSetDefault {
900 if err := r.principal.BlessingStore().SetDefault(b); err != nil {
901 return fmt.Errorf("failed to set blessings %v as default: %v", b, err)
902 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800903 }
Ankure548f392014-12-08 18:42:41 -0800904 if pattern := security.BlessingPattern(flagRecvBlessingsForPeer); len(pattern) > 0 {
905 if _, err := r.principal.BlessingStore().Set(b, pattern); err != nil {
906 return fmt.Errorf("failed to set blessings %v for peers %v: %v", b, pattern, err)
907 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800908 }
909 if flagAddToRoots {
910 if err := r.principal.AddToRoots(b); err != nil {
911 return fmt.Errorf("failed to add blessings to recognized roots: %v", err)
912 }
913 }
914 fmt.Println("Received blessings:", b)
915 r.notify <- nil
916 return nil
917}
918
919type allowAnyone struct{}
920
921func (allowAnyone) Authorize(security.Context) error { return nil }
922
923type granter struct {
924 p security.Principal
925 with security.Blessings
926 extension string
927 caveats []security.Caveat
928 serverKey string
929}
930
931func (g *granter) Grant(server security.Blessings) (security.Blessings, error) {
932 if got := fmt.Sprintf("%v", server.PublicKey()); got != g.serverKey {
933 // If the granter returns an error, the IPC framework should
934 // abort the RPC before sending the request to the server.
935 // Thus, there is no concern about leaking the token to an
936 // imposter server.
937 return nil, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
938 }
939 return g.p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
940}
941func (*granter) IPCCallOpt() {}
942
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800943func sendBlessings(ctx *context.T, object string, granter *granter, remoteToken string) error {
944 client := veyron2.GetClient(ctx)
945 call, err := client.StartCall(ctx, object, "Grant", []interface{}{remoteToken}, granter)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800946 if err != nil {
947 return fmt.Errorf("failed to start RPC to %q: %v", object, err)
948 }
949 if ierr := call.Finish(&err); ierr != nil {
950 return fmt.Errorf("failed to finish RPC to %q: %v", object, ierr)
951 }
952 return err
953}