blob: 3f9ed67e2812933637564001d9751bc3231bdd4d [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 Simsabc26d692014-11-19 18:30:55 -080015 "veyron.io/lib/cmdline"
16 profile "veyron.io/veyron/veyron/profiles/static"
17 vsecurity "veyron.io/veyron/veyron/security"
18 "veyron.io/veyron/veyron/services/identity"
Asim Shankarf11b1bc2014-11-12 17:18:45 -080019 "veyron.io/veyron/veyron2"
20 "veyron.io/veyron/veyron2/ipc"
21 "veyron.io/veyron/veyron2/naming"
Ankurcf6a89f2014-10-06 18:33:03 -070022 "veyron.io/veyron/veyron2/rt"
23 "veyron.io/veyron/veyron2/security"
Asim Shankarb3a82ba2014-10-29 11:41:27 -070024 "veyron.io/veyron/veyron2/vom"
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 Rosencrantzc2ed03e2014-11-25 15:40:48 -080069 p := runtime.Principal()
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()
162
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800163 blessing, err := runtime.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 Rosencrantzc2ed03e2014-11-25 15:40:48 -0800219 p := runtime.Principal()
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 Rosencrantzc2ed03e2014-11-25 15:40:48 -0800245 return sendBlessings(runtime, 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()
293
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800294 return dumpBlessings(runtime.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()
311
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800312 return dumpBlessings(runtime.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 Rosencrantzc2ed03e2014-11-25 15:40:48 -0800357 p := runtime.Principal()
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
405 p := runtime.Principal()
406 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 Rosencrantzc2ed03e2014-11-25 15:40:48 -0800443 p := runtime.Principal()
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 {
549 with = runtime.Principal().BlessingStore().Default()
550 }
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()
560 blessings, err := runtime.Principal().Bless(key, with, extension, caveats[0], caveats[1:]...)
561 if err != nil {
562 return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
563 }
564 if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
565 return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
Asim Shankar66c52f92014-10-15 23:39:10 -0700566 }
Ankur8d304122014-10-07 10:43:43 -0700567 return nil
568 },
569 }
Ankur1d46f552014-10-09 12:13:31 -0700570
571 cmdSeekBlessings = &cmdline.Command{
572 Name: "seekblessings",
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800573 Short: "Seek blessings from a web-based Veyron blessing service",
Ankur1d46f552014-10-09 12:13:31 -0700574 Long: `
575Seeks blessings from a web-based Veyron blesser which
576requires the caller to first authenticate with Google using OAuth. Simply
577run the command to see what happens.
578
Asim Shankar1789b8a2014-10-31 17:31:41 -0700579The blessings are sought for the principal specified by the environment that
580this tool is running in.
Ankur1d46f552014-10-09 12:13:31 -0700581
Ankure548f392014-12-08 18:42:41 -0800582The blessings obtained are set as default, unless the --set_default flag is
583set to true, and are also set for sharing with all peers, unless a more
Ankur1d46f552014-10-09 12:13:31 -0700584specific peer pattern is provided using the --for_peer flag.
585`,
586 Run: func(cmd *cmdline.Command, args []string) error {
Asim Shankar08ab3892014-10-16 12:04:07 -0700587 // Initialize the runtime first so that any local errors are reported
588 // before the HTTP roundtrips for obtaining the macaroon begin.
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800589 runtime, err := rt.New()
590 if err != nil {
591 panic(err)
592 }
593 defer runtime.Cleanup()
594
Ankur1d46f552014-10-09 12:13:31 -0700595 blessedChan := make(chan string)
596 defer close(blessedChan)
Suharsh Sivakumara76dba62014-12-22 16:00:34 -0800597 macaroonChan, err := getMacaroonForBlessRPC(flagSeekBlessingsFrom, blessedChan, flagSeekBlessingsBrowser)
Ankur1d46f552014-10-09 12:13:31 -0700598 if err != nil {
599 return fmt.Errorf("failed to get macaroon from Veyron blesser: %v", err)
600 }
601 macaroon := <-macaroonChan
602 service := <-macaroonChan
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800603 ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
Ankur1d46f552014-10-09 12:13:31 -0700604 defer cancel()
605
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700606 var reply security.WireBlessings
Todd Wang702385a2014-11-07 01:54:08 -0800607 reply, err = identity.MacaroonBlesserClient(service).Bless(ctx, macaroon)
Ankur1d46f552014-10-09 12:13:31 -0700608 if err != nil {
609 return fmt.Errorf("failed to get blessing from %q: %v", service, err)
610 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700611 blessings, err := security.NewBlessings(reply)
Ankur1d46f552014-10-09 12:13:31 -0700612 if err != nil {
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700613 return fmt.Errorf("failed to construct Blessings object from response: %v", err)
Ankur1d46f552014-10-09 12:13:31 -0700614 }
615 blessedChan <- fmt.Sprint(blessings)
616 // Wait for getTokenForBlessRPC to clean up:
617 <-macaroonChan
618
Asim Shankar66c52f92014-10-15 23:39:10 -0700619 if flagSeekBlessingsSetDefault {
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800620 if err := runtime.Principal().BlessingStore().SetDefault(blessings); err != nil {
Ankur1d46f552014-10-09 12:13:31 -0700621 return fmt.Errorf("failed to set blessings %v as default: %v", blessings, err)
622 }
623 }
Asim Shankar66c52f92014-10-15 23:39:10 -0700624 if pattern := security.BlessingPattern(flagSeekBlessingsForPeer); len(pattern) > 0 {
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800625 if _, err := runtime.Principal().BlessingStore().Set(blessings, pattern); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700626 return fmt.Errorf("failed to set blessings %v for peers %v: %v", blessings, pattern, err)
627 }
628 }
629 if flagAddToRoots {
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800630 if err := runtime.Principal().AddToRoots(blessings); err != nil {
Asim Shankar66c52f92014-10-15 23:39:10 -0700631 return fmt.Errorf("AddToRoots failed: %v", err)
632 }
Ankur1d46f552014-10-09 12:13:31 -0700633 }
634 return dumpBlessings(blessings)
635 },
636 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800637
638 cmdRecvBlessings = &cmdline.Command{
639 Name: "recvblessings",
640 Short: "Receive blessings sent by another principal and use them as the default",
641 Long: `
642Allow another principal (likely a remote process) to bless this one.
643
644This command sets up the invoker (this process) to wait for a blessing
645from another invocation of this tool (remote process) and prints out the
646command to be run as the remote principal.
647
Ankure548f392014-12-08 18:42:41 -0800648The received blessings are set as default, unless the --set_default flag is
649set to true, and are also set for sharing with all peers, unless a more
650specific peer pattern is provided using the --for_peer flag.
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800651
652TODO(ashankar,cnicolaou): Make this next paragraph possible! Requires
653the ability to obtain the proxied endpoint.
654
655Typically, this command should require no arguments.
656However, if the sender and receiver are on different network domains, it may
657make sense to use the --veyron.proxy flag:
Robin Thellend8fea01c2014-12-11 13:48:10 -0800658 principal --veyron.proxy=proxy recvblessings
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800659
660The command to be run at the sender is of the form:
661 principal bless --remote_key=KEY --remote_token=TOKEN ADDRESS
662
663The --remote_key flag is used to by the sender to "authenticate" the receiver,
664ensuring it blesses the intended recipient and not any attacker that may have
665taken over the address.
666
667The --remote_token flag is used by the sender to authenticate itself to the
668receiver. This helps ensure that the receiver rejects blessings from senders
669who just happened to guess the network address of the 'recvblessings'
670invocation.
671`,
672 Run: func(cmd *cmdline.Command, args []string) error {
673 if len(args) != 0 {
674 return fmt.Errorf("command accepts no arguments")
675 }
Matt Rosencrantz574d5e12014-11-26 10:01:37 -0800676
677 runtime, err := rt.New()
678 if err != nil {
679 panic(err)
680 }
681 defer runtime.Cleanup()
682
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800683 server, err := runtime.NewServer()
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800684 if err != nil {
685 return fmt.Errorf("failed to create server to listen for blessings: %v", err)
686 }
687 defer server.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800688 eps, err := server.Listen(profile.ListenSpec)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800689 if err != nil {
690 return fmt.Errorf("failed to setup listening: %v", err)
691 }
692 var token [24]byte
693 if _, err := rand.Read(token[:]); err != nil {
694 return fmt.Errorf("unable to generate token: %v", err)
695 }
696 service := &recvBlessingsService{
Matt Rosencrantzc2ed03e2014-11-25 15:40:48 -0800697 principal: runtime.Principal(),
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800698 token: base64.URLEncoding.EncodeToString(token[:]),
699 notify: make(chan error),
700 }
701 if err := server.Serve("", service, allowAnyone{}); err != nil {
702 return fmt.Errorf("failed to setup service: %v", err)
703 }
704 // Proposed name:
705 extension := fmt.Sprintf("extension%d", int(token[0])<<16|int(token[1])<<8|int(token[2]))
706 fmt.Println("Run the following command on behalf of the principal that will send blessings:")
707 fmt.Println("You may want to adjust flags affecting the caveats on this blessing, for example using")
708 fmt.Println("the --for flag, or change the extension to something more meaningful")
709 fmt.Println()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800710 fmt.Printf("principal bless --remote_key=%v --remote_token=%v %v %v\n", runtime.Principal().PublicKey(), service.token, naming.JoinAddressName(eps[0].String(), ""), extension)
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800711 fmt.Println()
712 fmt.Println("...waiting for sender..")
713 return <-service.notify
714 },
715 }
Ankurcf6a89f2014-10-06 18:33:03 -0700716)
717
718func main() {
Asim Shankar66c52f92014-10-15 23:39:10 -0700719 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 -0800720
Ankur77c32ac2014-12-18 14:18:19 -0800721 cmdFork.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
722 cmdFork.Flags.DurationVar(&flagForkFor, "for", 0, "Duration for which the forked blessing is valid (zero means no that the blessing is always valid)")
723 cmdFork.Flags.StringVar(&flagForkWith, "with", "", "Path to file containing blessing to extend")
724
Asim Shankar66c52f92014-10-15 23:39:10 -0700725 cmdBless.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800726 cmdBless.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
727 cmdBless.Flags.StringVar(&flagBlessRemoteKey, "remote_key", "", "Public key of the remote principal to bless (obtained from the 'recvblessings' command run by the remote principal")
728 cmdBless.Flags.StringVar(&flagBlessRemoteToken, "remote_token", "", "Token provided by principal running the 'recvblessings' command")
729
Robin Thellend8fea01c2014-12-11 13:48:10 -0800730 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 -0700731 cmdSeekBlessings.Flags.BoolVar(&flagSeekBlessingsSetDefault, "set_default", true, "If true, the blessings obtained will be set as the default blessing in the store")
732 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 -0800733 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 -0700734 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 -0800735
Asim Shankar66c52f92014-10-15 23:39:10 -0700736 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 -0800737
Asim Shankar66c52f92014-10-15 23:39:10 -0700738 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 -0800739
Ankur4704f5f2014-10-23 12:40:54 -0700740 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 -0700741
Ankure548f392014-12-08 18:42:41 -0800742 cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
743 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")
744
Asim Shankar66c52f92014-10-15 23:39:10 -0700745 cmdStore := &cmdline.Command{
746 Name: "store",
747 Short: "Manipulate and inspect the principal's blessing store",
748 Long: `
749Commands to manipulate and inspect the blessing store of the principal.
750
751All blessings are printed to stdout using base64-VOM-encoding
752`,
Mike Burrows367515e2014-12-02 11:30:18 -0800753 Children: []*cmdline.Command{cmdStoreDefault, cmdStoreSetDefault, cmdStoreForPeer, cmdStoreSet, cmdStoreAddToRoots},
Ankurcf6a89f2014-10-06 18:33:03 -0700754 }
Ankurcf6a89f2014-10-06 18:33:03 -0700755
756 (&cmdline.Command{
757 Name: "principal",
758 Short: "Create and manage veyron principals",
759 Long: `
760The principal tool helps create and manage blessings and the set of trusted
761roots bound to a principal.
762
763All objects are printed using base64-VOM-encoding.
764`,
Ankurc24ff422014-12-16 17:59:26 -0800765 Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
Ankurcf6a89f2014-10-06 18:33:03 -0700766 }).Main()
767}
768
Ankurcf6a89f2014-10-06 18:33:03 -0700769func decodeBlessings(fname string) (security.Blessings, error) {
770 var wire security.WireBlessings
771 if err := decode(fname, &wire); err != nil {
772 return nil, err
773 }
774 return security.NewBlessings(wire)
775}
776
777func dumpBlessings(blessings security.Blessings) error {
778 if blessings == nil {
779 return errors.New("no blessings found")
780 }
Ankuree0aa812014-11-14 10:56:52 -0800781 str, err := base64VomEncode(security.MarshalBlessings(blessings))
Ankurcf6a89f2014-10-06 18:33:03 -0700782 if err != nil {
783 return fmt.Errorf("base64-VOM encoding failed: %v", err)
784 }
785 fmt.Println(str)
786 return nil
787}
788
789func read(fname string) (string, error) {
790 if len(fname) == 0 {
791 return "", nil
792 }
793 f := os.Stdin
794 if fname != "-" {
795 var err error
796 if f, err = os.Open(fname); err != nil {
797 return "", fmt.Errorf("failed to open %q: %v", fname, err)
798 }
799 }
800 defer f.Close()
801 var buf bytes.Buffer
802 if _, err := io.Copy(&buf, f); err != nil {
803 return "", fmt.Errorf("failed to read %q: %v", fname, err)
804 }
805 return buf.String(), nil
806}
807
808func decode(fname string, val interface{}) error {
809 str, err := read(fname)
810 if err != nil {
811 return err
812 }
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700813 if err := base64VomDecode(str, val); err != nil || val == nil {
Ankurcf6a89f2014-10-06 18:33:03 -0700814 return fmt.Errorf("failed to decode %q: %v", fname, err)
815 }
816 return nil
817}
818
819func defaultBlessingName() string {
820 var name string
821 if user, _ := user.Current(); user != nil && len(user.Username) > 0 {
822 name = user.Username
823 } else {
824 name = "anonymous"
825 }
826 if host, _ := os.Hostname(); len(host) > 0 {
827 name = name + "@" + host
828 }
829 return name
830}
Asim Shankardf88a2e2014-10-21 17:20:28 -0700831
832func rootkey(chain []security.Certificate) string {
833 if len(chain) == 0 {
834 return "<empty certificate chain>"
835 }
836 key, err := security.UnmarshalPublicKey(chain[0].PublicKey)
837 if err != nil {
838 return fmt.Sprintf("<invalid PublicKey: %v>", err)
839 }
840 return fmt.Sprintf("%v", key)
841}
Asim Shankarb3a82ba2014-10-29 11:41:27 -0700842
843func base64VomEncode(i interface{}) (string, error) {
844 buf := &bytes.Buffer{}
845 closer := base64.NewEncoder(base64.URLEncoding, buf)
846 if err := vom.NewEncoder(closer).Encode(i); err != nil {
847 return "", err
848 }
849 // Must close the base64 encoder to flush out any partially written
850 // blocks.
851 if err := closer.Close(); err != nil {
852 return "", err
853 }
854 return buf.String(), nil
855}
856
857func base64VomDecode(s string, i interface{}) error {
858 b, err := base64.URLEncoding.DecodeString(s)
859 if err != nil {
860 return err
861 }
862 return vom.NewDecoder(bytes.NewBuffer(b)).Decode(i)
863}
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800864
865type recvBlessingsService struct {
866 principal security.Principal
867 notify chan error
868 token string
869}
870
871func (r *recvBlessingsService) Grant(call ipc.ServerCall, token string) error {
872 b := call.Blessings()
873 if b == nil {
874 return fmt.Errorf("no blessings granted by sender")
875 }
876 if len(token) != len(r.token) {
877 // A timing attack can be used to figure out the length
878 // of the token, but then again, so can looking at the
879 // source code. So, it's okay.
880 return fmt.Errorf("blessings received from unexpected sender")
881 }
882 if subtle.ConstantTimeCompare([]byte(token), []byte(r.token)) != 1 {
883 return fmt.Errorf("blessings received from unexpected sender")
884 }
Ankure548f392014-12-08 18:42:41 -0800885 if flagRecvBlessingsSetDefault {
886 if err := r.principal.BlessingStore().SetDefault(b); err != nil {
887 return fmt.Errorf("failed to set blessings %v as default: %v", b, err)
888 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800889 }
Ankure548f392014-12-08 18:42:41 -0800890 if pattern := security.BlessingPattern(flagRecvBlessingsForPeer); len(pattern) > 0 {
891 if _, err := r.principal.BlessingStore().Set(b, pattern); err != nil {
892 return fmt.Errorf("failed to set blessings %v for peers %v: %v", b, pattern, err)
893 }
Asim Shankarf11b1bc2014-11-12 17:18:45 -0800894 }
895 if flagAddToRoots {
896 if err := r.principal.AddToRoots(b); err != nil {
897 return fmt.Errorf("failed to add blessings to recognized roots: %v", err)
898 }
899 }
900 fmt.Println("Received blessings:", b)
901 r.notify <- nil
902 return nil
903}
904
905type allowAnyone struct{}
906
907func (allowAnyone) Authorize(security.Context) error { return nil }
908
909type granter struct {
910 p security.Principal
911 with security.Blessings
912 extension string
913 caveats []security.Caveat
914 serverKey string
915}
916
917func (g *granter) Grant(server security.Blessings) (security.Blessings, error) {
918 if got := fmt.Sprintf("%v", server.PublicKey()); got != g.serverKey {
919 // If the granter returns an error, the IPC framework should
920 // abort the RPC before sending the request to the server.
921 // Thus, there is no concern about leaking the token to an
922 // imposter server.
923 return nil, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
924 }
925 return g.p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
926}
927func (*granter) IPCCallOpt() {}
928
929func sendBlessings(r veyron2.Runtime, object string, granter *granter, remoteToken string) error {
930 call, err := r.Client().StartCall(r.NewContext(), object, "Grant", []interface{}{remoteToken}, granter)
931 if err != nil {
932 return fmt.Errorf("failed to start RPC to %q: %v", object, err)
933 }
934 if ierr := call.Finish(&err); ierr != nil {
935 return fmt.Errorf("failed to finish RPC to %q: %v", object, ierr)
936 }
937 return err
938}