Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -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 | |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 5 | package blesser |
| 6 | |
| 7 | import ( |
Ankur | cfccc8f | 2015-05-19 17:38:37 -0700 | [diff] [blame] | 8 | "errors" |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 9 | "fmt" |
Ankur | cfccc8f | 2015-05-19 17:38:37 -0700 | [diff] [blame] | 10 | "reflect" |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 11 | "time" |
| 12 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 13 | "v.io/x/ref/services/identity" |
Suharsh Sivakumar | c004811 | 2015-03-19 11:48:28 -0700 | [diff] [blame] | 14 | "v.io/x/ref/services/identity/internal/oauth" |
| 15 | "v.io/x/ref/services/identity/internal/util" |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 16 | |
Todd Wang | 54feabe | 2015-04-15 23:38:26 -0700 | [diff] [blame] | 17 | "v.io/v23/context" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 18 | "v.io/v23/rpc" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 19 | "v.io/v23/security" |
| 20 | "v.io/v23/vom" |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 21 | ) |
| 22 | |
| 23 | type macaroonBlesser struct { |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 24 | key []byte |
| 25 | } |
| 26 | |
Asim Shankar | b18a44f | 2014-10-21 20:25:07 -0700 | [diff] [blame] | 27 | // NewMacaroonBlesserServer provides an identity.MacaroonBlesser Service that generates blessings |
| 28 | // after unpacking a BlessingMacaroon. |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 29 | func NewMacaroonBlesserServer(key []byte) identity.MacaroonBlesserServerStub { |
| 30 | return identity.MacaroonBlesserServer(&macaroonBlesser{key}) |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 31 | } |
| 32 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 33 | func (b *macaroonBlesser) Bless(ctx *context.T, call rpc.ServerCall, macaroon string) (security.Blessings, error) { |
| 34 | secCall := call.Security() |
Asim Shankar | b07ec69 | 2015-02-27 23:40:44 -0800 | [diff] [blame] | 35 | var empty security.Blessings |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 36 | inputs, err := util.Macaroon(macaroon).Decode(b.key) |
| 37 | if err != nil { |
Asim Shankar | b3a82ba | 2014-10-29 11:41:27 -0700 | [diff] [blame] | 38 | return empty, err |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 39 | } |
Ankur | 123a5c7 | 2015-01-12 16:03:43 -0800 | [diff] [blame] | 40 | var m oauth.BlessingMacaroon |
Todd Wang | 3425a90 | 2015-01-21 18:43:59 -0800 | [diff] [blame] | 41 | if err := vom.Decode(inputs, &m); err != nil { |
Asim Shankar | b3a82ba | 2014-10-29 11:41:27 -0700 | [diff] [blame] | 42 | return empty, err |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 43 | } |
| 44 | if time.Now().After(m.Creation.Add(time.Minute * 5)) { |
Asim Shankar | b3a82ba | 2014-10-29 11:41:27 -0700 | [diff] [blame] | 45 | return empty, fmt.Errorf("macaroon has expired") |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 46 | } |
Matt Rosencrantz | 311378b | 2015-03-25 15:26:12 -0700 | [diff] [blame] | 47 | if secCall.LocalPrincipal() == nil { |
Asim Shankar | b3a82ba | 2014-10-29 11:41:27 -0700 | [diff] [blame] | 48 | return empty, fmt.Errorf("server misconfiguration: no authentication happened") |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 49 | } |
Ankur | cfccc8f | 2015-05-19 17:38:37 -0700 | [diff] [blame] | 50 | macaroonPublicKey, err := security.UnmarshalPublicKey(m.PublicKey) |
| 51 | if err != nil { |
| 52 | return empty, fmt.Errorf("failed to unmarshal public key in macaroon: %v", err) |
| 53 | } |
| 54 | if !reflect.DeepEqual(secCall.RemoteBlessings().PublicKey(), macaroonPublicKey) { |
| 55 | return empty, errors.New("remote end's public key does not match public key in macaroon") |
| 56 | } |
Asim Shankar | f422537 | 2014-10-04 08:34:39 -0700 | [diff] [blame] | 57 | if len(m.Caveats) == 0 { |
| 58 | m.Caveats = []security.Caveat{security.UnconstrainedUse()} |
| 59 | } |
Matt Rosencrantz | 311378b | 2015-03-25 15:26:12 -0700 | [diff] [blame] | 60 | return secCall.LocalPrincipal().Bless(secCall.RemoteBlessings().PublicKey(), |
Asim Shankar | 8e54706 | 2015-05-15 01:00:33 -0700 | [diff] [blame] | 61 | secCall.LocalBlessings(), m.Name, m.Caveats[0], m.Caveats[1:]...) |
Suharsh Sivakumar | d308c7e | 2014-10-03 12:46:50 -0700 | [diff] [blame] | 62 | } |