func runListKeys(ctx *context.T, env *cmdline.Env, args []string) error { peerBlessings := v23.GetPrincipal(ctx).BlessingStore().PeerBlessings() const format = "%-30s %s (Expires: %s)\n" fmt.Printf(format, "Lock", "Key", "<expiry time>") for lock, key := range peerBlessings { if !isValidLockName(string(lock)) { continue } if !isKeyValidForLock(ctx, key, string(lock)) { continue } var ( expiresIn string now = time.Now() ) if exp := key.Expiry(); !exp.IsZero() && exp.Before(now) { // TODO(ataly): Remove the key from the blessing // store. continue } else if exp.IsZero() { expiresIn = "NEVER" } else { expiresIn = fmt.Sprintf("in %v", exp.Sub(now)) } fmt.Printf(format, lock, key, expiresIn) } return nil }
func startLockServer(ctx *context.T, configDir string) (func(), error) { blessings, _ := v23.GetPrincipal(ctx).BlessingStore().Default() lockNhSuffix := fmt.Sprint(blessings) // Start a local mounttable where the lock server would be // mounted, and make this mounttable visible in the local // neighborhood. mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.LockNhPrefix+lockNhSuffix) if err != nil { return nil, err } ctx, _, err = v23.WithNewNamespace(ctx, mtName) if err != nil { stopMT() return nil, err } ctx, cancel := context.WithCancel(ctx) _, server, err := v23.WithNewServer(ctx, lockObjectName(ctx), newLock(), security.DefaultAuthorizer()) if err != nil { stopMT() return nil, err } stopLock := func() { cancel() vlog.Infof("Stopping lock server...") <-server.Closed() vlog.Infof("Stopped lock server...") stopMT() } vlog.Infof("Started lock server\n") vlog.Infof("ENDPOINT: %v\n", server.Status().Endpoints[0].Name()) return stopLock, nil }
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 lockUserNhName(ctx *context.T) string { var ( principal = v23.GetPrincipal(ctx) blessings, _ = principal.BlessingStore().Default() bNames = security.BlessingNames(principal, blessings) ) return lockUserNhPrefix + vUser(bNames...) }
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 }
//export swift_io_v_v23_security_simple_nativePublicKey func swift_io_v_v23_security_simple_nativePublicKey(ctxHandle C.GoContextHandle, errOut *C.SwiftVError) *C.char { ctx := context.GoContext(uint64(ctxHandle)) der, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary() if err != nil { util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut)) return nil } // Swift will have to free the allocation return C.CString(base64.URLEncoding.EncodeToString(der)) }
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 }
func (ul *unclaimedLock) Claim(ctx *context.T, call rpc.ServerCall, name string) (security.Blessings, error) { vlog.Infof("Claim called by %q", call.Security().RemoteBlessings()) if strings.ContainsAny(name, security.ChainSeparator) { // TODO(ataly, ashankar): We have to error out in this case because of the current // neighborhood setup wherein the neighborhood-name of a claimed lock's mounttable is // the same as the locks's name. Since neighborhood-names aren't allowed to contain // slashes, we have to disallow slashes in the lock name as well. return security.Blessings{}, NewErrInvalidLockName(ctx, name, security.ChainSeparator) } var ( principal = v23.GetPrincipal(ctx) origDefault, _ = principal.BlessingStore().Default() restore = func() error { // TODO(ataly): Remove roots of current default blessing if needed // (i.e., if current default != origDefault). if err := principal.BlessingStore().SetDefault(origDefault); err != nil { return verror.Convert(verror.ErrInternal, ctx, err) } return nil } ) defer ul.mu.Unlock() ul.mu.Lock() if ul.claimed == nil { return security.Blessings{}, NewErrLockAlreadyClaimed(ctx) } keyBlessing, err := ul.makeKey(principal, name, call.Security().RemoteBlessings().PublicKey()) if err != nil { restore() return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err) } // Create a file in the config directory to indicate that lock has been claimed. f, err := os.Create(filepath.Join(ul.configDir, claimFileName)) if err != nil { restore() return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err) } f.Close() close(ul.claimed) ul.claimed = nil vlog.Infof("Lock successfullly claimed with name %q", name) return keyBlessing, nil }
//export swift_io_v_v23_security_simple_nativeSetBlessings func swift_io_v_v23_security_simple_nativeSetBlessings(ctxHandle C.GoContextHandle, encodedSwiftBlessings C.SwiftByteArray, errOut *C.SwiftVError) { ctx := context.GoContext(uint64(ctxHandle)) encodedBlessings := util.GoBytesNoCopy(unsafe.Pointer(&encodedSwiftBlessings)) var blessings security.Blessings if err := vom.Decode(encodedBlessings, &blessings); err != nil { ctx.Error("Unable to decode:", err) util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut)) return } principal := v23.GetPrincipal(ctx) if err := principal.BlessingStore().SetDefault(blessings); err != nil { util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut)) return } }
func keyForLock(ctx *context.T, lockName string) (security.Blessings, error) { // We could simply return v23.GetPrincipal(ctx).BlessingStore().ForPeer(lock) // however this would also include any blessings tagged for a peer pattern // is matched by 'lock'. Therefore we iterate over all the blessings // and pick the specific ones that are meant for 'lock'. var ret security.Blessings for _, b := range v23.GetPrincipal(ctx).BlessingStore().PeerBlessings() { if isKeyValidForLock(ctx, b, lockName) { if union, err := security.UnionOfBlessings(ret, b); err != nil { vlog.Errorf("UnionOfBlessings(%v, %v) failed: %v, dropping latter blessing", ret, b, err) } else { ret = union } } } if ret.IsZero() { return security.Blessings{}, fmt.Errorf("no available key for lock %v", lockName) } return ret, nil }
func (nm *networkManager) run(ready chan<- interface{}, newLeftScreen, newRightScreen chan<- chan<- *spec.Triangle, newInvite chan<- Invitation) { defer close(nm.myScreen) defer close(newLeftScreen) defer close(newRightScreen) notifyReady := func(result interface{}) { ready <- result close(ready) ready = nil } ctx, shutdown := v23.Init() defer shutdown() ctx, server, err := v23.WithNewServer(ctx, "", spec.ScreenServer(nm), security.AllowEveryone()) if err != nil { notifyReady(err) return } disc, err := v23.NewDiscovery(ctx) if err != nil { notifyReady(err) return } // Select a color based on some unique identifier of the process, the PublicKey serves as one. notifyReady(selectColor(v23.GetPrincipal(ctx).PublicKey())) var ( left = remoteScreen{myScreen: nm.myScreen, notify: newLeftScreen} right = remoteScreen{myScreen: nm.myScreen, notify: newRightScreen} accepted = make(chan string) // Names of remote screens that accepted an invitation seek = make(chan bool) // Send false to stop seeking invitations from others, true otherwise pendingInviterName string pendingInviteUserResponse <-chan error pendingInviteRPCResponse chan<- error ) seekInvites(ctx, disc, server, seek) go sendInvites(ctx, disc, accepted) for { select { case invitation := <-nm.inviteRPCs: if left.Active() { invitation.Response <- fmt.Errorf("thanks for the invite but I'm already engaged with a previous invitation") break } // Defer the response to the user interface. ch := make(chan error) pendingInviterName = invitation.Name pendingInviteRPCResponse = invitation.Response pendingInviteUserResponse = ch invitation.Response = ch newInvite <- invitation case err := <-pendingInviteUserResponse: pendingInviteRPCResponse <- err if err == nil { ctx.Infof("Activating left screen %q", pendingInviterName) left.Activate(ctx, pendingInviterName) seek <- false } pendingInviterName = "" pendingInviteUserResponse = nil pendingInviteRPCResponse = nil case <-left.Lost(): ctx.Infof("Deactivating left screen") left.Deactivate() seek <- true case invitee := <-accepted: ctx.Infof("Activating right screen %q", invitee) right.Activate(ctx, invitee) case <-right.Lost(): ctx.Infof("Deactivating right screen") right.Deactivate() go sendInvites(ctx, disc, accepted) case <-ctx.Done(): return } } }
//export swift_io_v_v23_security_simple_nativeBlessingsDebugString func swift_io_v_v23_security_simple_nativeBlessingsDebugString(ctxHandle C.GoContextHandle) *C.char { ctx := context.GoContext(uint64(ctxHandle)) blessings, _ := v23.GetPrincipal(ctx).BlessingStore().Default() return C.CString(fmt.Sprintf("%v", blessings)) }