func (g *granter) Grant(ctx *context.T, call security.Call) (security.Blessings, error) { // Verify that the remote end's blessings encapsulates the // same user identity as g.user. remoteBlessingNames, _ := security.RemoteBlessingNames(ctx, call) authorized := false for _, b := range remoteBlessingNames { if vUser(b) == g.user { authorized = true } } if !authorized { return security.Blessings{}, fmt.Errorf("remote end presented blessings %v, want a blessing for user %v", remoteBlessingNames, g.user) } peerPattern := security.BlessingPattern(g.lockName) onlyThisLockCav, err := security.NewCaveat(security.PeerBlessingsCaveat, []security.BlessingPattern{peerPattern}) if err != nil { return security.Blessings{}, fmt.Errorf("failed to create peer blessings caveat for key: %v", err) } caveats := []security.Caveat{onlyThisLockCav} if g.expiry != 0 { expiryCav, err := security.NewExpiryCaveat(time.Now().Add(g.expiry)) if err != nil { return security.Blessings{}, fmt.Errorf("failed to create expiration caveat for key: %v", err) } caveats = append(caveats, expiryCav) } return call.LocalPrincipal().Bless(call.RemoteBlessings().PublicKey(), g.key, g.category, caveats[0], caveats[1:]...) }
func runClaim(ctx *context.T, env *cmdline.Env, args []string) error { if numargs := len(args); numargs != 2 { return fmt.Errorf("requires exactly two arguments <lock>, <name>, provided %d", numargs) } lockName, name := args[0], args[1] ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx)) if err != nil { return err } defer stop() ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() // TODO(ataly): We should not skip server endpoint authorization while // claiming locks but instead fetch the blessing root of the lock manufacturer // from an authoritative source and then appropriately authenticate the server. b, err := lock.UnclaimedLockClient(lockObjName(lockName)).Claim( ctx, name, options.ServerAuthorizer{security.AllowEveryone()}) if err != nil { return err } p := v23.GetPrincipal(ctx) if err := security.AddToRoots(p, b); err != nil { return fmt.Errorf("failed to add (key) blessing (%v) to roots: %v", b, err) } if _, err := p.BlessingStore().Set(b, security.BlessingPattern(name)); err != nil { return fmt.Errorf("failed to set (key) blessing (%v) for peer %v: %v", b, name, err) } fmt.Printf("Claimed lock: %v as %v and received key: %v\n", lockName, name, b) return nil }
func (ul *unclaimedLock) makeKey(principal security.Principal, name string, remoteKey security.PublicKey) (security.Blessings, error) { lockBlessing, err := principal.BlessSelf(name) if err != nil { return security.Blessings{}, err } if err := principal.BlessingStore().SetDefault(lockBlessing); err != nil { return security.Blessings{}, err } if err := security.AddToRoots(principal, lockBlessing); err != nil { return security.Blessings{}, err } // Add a caveat to the "key" blessing so that it can only be used to talking // to this lock object. // TODO(ataly): Add a client-only caveat as well so that someone who obtains // this blessing or an extension of it cannot maliciously (or accidentally) // start a server with this blessing (such a server could impersonate this // lock object). peerPattern := security.BlessingPattern(name) onlyThisLockCav, err := security.NewCaveat(security.PeerBlessingsCaveat, []security.BlessingPattern{peerPattern}) if err != nil { return security.Blessings{}, err } keyBlessing, err := principal.Bless(remoteKey, lockBlessing, keyBlessingExtension, onlyThisLockCav) if err != nil { return security.Blessings{}, err } return keyBlessing, nil }
func isKeyValidForLock(ctx *context.T, key security.Blessings, lockName string) bool { bp := security.BlessingPattern(lockName + security.ChainSeparator + "key") for _, b := range security.BlessingNames(v23.GetPrincipal(ctx), key) { if bp.MatchedBy(b) { return true } } return false }
func m2vVisibility(visibility *[]string) []security.BlessingPattern { if visibility == nil { return nil } vVisibility := make([]security.BlessingPattern, len(*visibility)) for i, p := range *visibility { vVisibility[i] = security.BlessingPattern(p) } return vVisibility }
func saveKeyForLock(ctx *context.T, key security.Blessings, lockName string) error { if isKeyValidForLock(ctx, key, lockName) { return fmt.Errorf("key %v is not valid for lock %v", key, lockName) } p := v23.GetPrincipal(ctx) if _, err := p.BlessingStore().Set(key, security.BlessingPattern(lockName)); err != nil { return fmt.Errorf("failed to save key %v for lock %v", key, lockName) } if err := security.AddToRoots(p, key); err != nil { return fmt.Errorf("failed to save key %v for lock %v", key, lockName) } return nil }
// vUser returns a comma-separated string of user identities obtained // from the provided blessing names. // // For each blessing name, vUser checks if it matches the pattern // 'vanadiumBlessingPrefix' and if so constructs the user identity by // stripping off 'vanadiumBlessingPrefix' from the blessing name. // Otherwise the user identity is simply the blessing name. // // In all case, the user identity is converted into a valid neighborhood-name // by replacing slahes with "@@". // TODO(ataly): Try to use conventions.GetClientUserIds instead. func vUser(bNames ...string) string { nhFriendly := func(b string) string { return strings.Replace(b, security.ChainSeparator, "@@", -1) } users := make([]string, len(bNames)) for i, b := range bNames { if !security.BlessingPattern(vanadiumBlessingPrefix).MatchedBy(b) { users[i] = nhFriendly(b) continue } users[i] = nhFriendly(strings.TrimPrefix(b, vanadiumBlessingPrefix+security.ChainSeparator)) } return strings.Join(users, ",") }
// Exports the discovery advertise API to CGO using JSON to marshal ads //export swift_io_v_v23_discovery_advertise func swift_io_v_v23_discovery_advertise(ctxHandle C.GoContextHandle, discoveryHandle C.GoDiscoveryHandle, adJson C.SwiftByteArray, visibilityArray C.SwiftCStringArray, asyncId C.AsyncCallbackIdentifier, doneCallback C.SwiftAsyncSuccessCallback, errOut *C.SwiftVError) bool { ctx := scontext.GoContext(uint64(ctxHandle)) d := GoDiscoveryT(uint64(discoveryHandle)) ad := discovery.Advertisement{} if err := json.Unmarshal(sutil.GoBytesNoCopy(unsafe.Pointer(&adJson)), &ad); err != nil { sutil.ThrowSwiftError(ctx, err, unsafe.Pointer(errOut)) return false } var visibility []security.BlessingPattern for _, v := range visibilityArray.toStrings() { visibility = append(visibility, security.BlessingPattern(v)) } doneChan, err := d.Advertise(ctx, &ad, visibility) if err != nil { sutil.ThrowSwiftError(ctx, err, unsafe.Pointer(errOut)) return false } go func() { <-doneChan C.CallAdvertisingCallback(doneCallback, asyncId) }() return true }
//export Java_io_v_v23_security_BlessingPattern_nativeCreate func Java_io_v_v23_security_BlessingPattern_nativeCreate(jenv *C.JNIEnv, jBlessingPatternClass C.jclass, jValue C.jstring) C.jlong { env := jutil.Env(uintptr(unsafe.Pointer(jenv))) pattern := security.BlessingPattern(jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jValue))))) ref := jutil.GoNewRef(&pattern) // Un-refed when the BlessingPattern object is finalized. return C.jlong(ref) }