github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/status/status.go (about)

     1  // Copyright 2019 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package status
     5  
     6  import (
     7  	"errors"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/keybase/client/go/install"
    13  	"github.com/keybase/client/go/libkb"
    14  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    15  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    16  )
    17  
    18  func GetCurrentStatus(mctx libkb.MetaContext) (res keybase1.CurrentStatus, err error) {
    19  	cr := mctx.G().Env.GetConfig()
    20  	if cr == nil {
    21  		return res, nil
    22  	}
    23  	res.Configured = true
    24  	if uid := cr.GetUID(); uid.Exists() {
    25  		res.Registered = true
    26  		res.User = libkb.NewUserThin(cr.GetUsername().String(), uid).Export()
    27  	}
    28  	res.SessionIsValid = mctx.ActiveDevice().Valid()
    29  	res.LoggedIn = res.SessionIsValid
    30  	res.DeviceName = mctx.ActiveDevice().Name()
    31  	return res, nil
    32  }
    33  
    34  func GetExtendedStatus(mctx libkb.MetaContext) (res keybase1.ExtendedStatus, err error) {
    35  	mctx = mctx.WithLogTag("EXTSTATUS")
    36  	defer mctx.Trace("GetExtendedStatus", &err)()
    37  	g := mctx.G()
    38  
    39  	res.Standalone = g.Env.GetStandalone()
    40  	res.LogDir = g.Env.GetLogDir()
    41  	res.Clients = libkb.GetClientStatus(mctx)
    42  
    43  	if err = g.GetFullSelfer().WithSelf(mctx.Ctx(), func(me *libkb.User) error {
    44  		ckf := me.GetComputedKeyFamily()
    45  		if ckf == nil {
    46  			return errors.New("Couldn't load key family")
    47  		}
    48  		device, err := ckf.GetCurrentDevice(g)
    49  		if err != nil {
    50  			mctx.Debug("| GetCurrentDevice failed: %s", err)
    51  			res.DeviceErr = &keybase1.LoadDeviceErr{Where: "ckf.GetCurrentDevice", Desc: err.Error()}
    52  		} else {
    53  			res.Device = device.ProtExport()
    54  		}
    55  
    56  		ss := g.SecretStore()
    57  		if me != nil && ss != nil {
    58  			s, err := ss.RetrieveSecret(mctx, me.GetNormalizedName())
    59  			if err == nil && !s.IsNil() {
    60  				res.StoredSecret = true
    61  			}
    62  		}
    63  		return nil
    64  	}); err != nil {
    65  		mctx.Debug("| could not load me user: %s", err)
    66  		res.DeviceErr = &keybase1.LoadDeviceErr{Where: "libkb.LoadMe", Desc: err.Error()}
    67  	}
    68  
    69  	// cached device key status
    70  	_, _, _, sk, ek := g.ActiveDevice.AllFields()
    71  	res.DeviceSigKeyCached = sk != nil
    72  	res.DeviceEncKeyCached = ek != nil
    73  
    74  	ad := mctx.ActiveDevice()
    75  	// cached paper key status
    76  	if pk := ad.ProvisioningKey(mctx); pk != nil {
    77  		if pk.EncryptionKey() != nil {
    78  			res.PaperEncKeyCached = true
    79  		}
    80  		if pk.SigningKey() != nil {
    81  			res.PaperSigKeyCached = true
    82  		}
    83  	}
    84  
    85  	psc := ad.PassphraseStreamCache()
    86  	res.PassphraseStreamCached = psc.ValidPassphraseStream()
    87  	res.TsecCached = psc.ValidTsec()
    88  	res.SecretPromptSkip = mctx.ActiveDevice().SecretPromptCancelTimer().WasRecentlyCanceled(mctx)
    89  
    90  	current, all, err := libkb.GetAllProvisionedUsernames(mctx)
    91  	if err != nil {
    92  		mctx.Debug("| died in GetAllProvisionedUsernames()")
    93  		return res, err
    94  	}
    95  	res.DefaultUsername = current.String()
    96  	p := make([]string, len(all))
    97  	for i, u := range all {
    98  		p[i] = u.String()
    99  	}
   100  	res.ProvisionedUsernames = p
   101  
   102  	accounts, err := libkb.GetConfiguredAccountsFromProvisionedUsernames(mctx, mctx.G().SecretStore(), current, all)
   103  	if err != nil {
   104  		mctx.Debug("| died in GetConfiguredAccounts()")
   105  		return res, err
   106  	}
   107  	res.ConfiguredAccounts = accounts
   108  
   109  	res.PlatformInfo = getPlatformInfo()
   110  	res.DefaultDeviceID = g.Env.GetDeviceID()
   111  	res.RememberPassphrase = g.Env.GetRememberPassphrase(g.Env.GetUsername())
   112  	// DeviceEK status, can be nil if user is logged out
   113  	deviceEKStorage := g.GetDeviceEKStorage()
   114  	if deviceEKStorage != nil {
   115  		dekNames, err := deviceEKStorage.ListAllForUser(mctx)
   116  		if err != nil {
   117  			return res, err
   118  		}
   119  		res.DeviceEkNames = dekNames
   120  	}
   121  
   122  	res.LocalDbStats = strings.Split(g.LocalDb.Stats(), "\n")
   123  	res.LocalChatDbStats = strings.Split(g.LocalChatDb.Stats(), "\n")
   124  	if cacheSizeInfo, err := CacheSizeInfo(g); err == nil {
   125  		res.CacheDirSizeInfo = cacheSizeInfo
   126  	}
   127  
   128  	if g.ConnectionManager != nil {
   129  		xp := g.ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
   130  		if xp == nil {
   131  			mctx.Debug("| KBFS stats not available")
   132  		} else {
   133  			cli := &keybase1.SimpleFSClient{
   134  				Cli: rpc.NewClient(
   135  					xp, libkb.NewContextifiedErrorUnwrapper(g), nil),
   136  			}
   137  			stats, err := cli.SimpleFSGetStats(mctx.Ctx())
   138  			if err != nil {
   139  				mctx.Debug("| KBFS stats error: %+v", err)
   140  			} else {
   141  				res.LocalBlockCacheDbStats = stats.BlockCacheDbStats
   142  				res.LocalSyncCacheDbStats = stats.SyncCacheDbStats
   143  			}
   144  		}
   145  	}
   146  
   147  	if g.UIRouter != nil {
   148  		uiMapping := map[string]int{}
   149  		for k, v := range g.UIRouter.DumpUIs() {
   150  			uiMapping[k.String()] = int(v)
   151  		}
   152  		res.UiRouterMapping = uiMapping
   153  	}
   154  
   155  	return res, nil
   156  }
   157  
   158  func GetConfig(mctx libkb.MetaContext, forkType keybase1.ForkType) (c keybase1.Config, err error) {
   159  	serverURI, err := mctx.G().Env.GetServerURI()
   160  	if err != nil {
   161  		return c, err
   162  	}
   163  
   164  	c.ServerURI = serverURI
   165  	c.RunMode = string(mctx.G().Env.GetRunMode())
   166  	c.SocketFile, err = mctx.G().Env.GetSocketBindFile()
   167  	if err != nil {
   168  		return c, err
   169  	}
   170  
   171  	gpg := mctx.G().GetGpgClient()
   172  	canExec, err := gpg.CanExec(mctx)
   173  	if err == nil {
   174  		c.GpgExists = canExec
   175  		c.GpgPath = gpg.Path(mctx)
   176  	}
   177  
   178  	c.Version = libkb.VersionString()
   179  	c.VersionShort = libkb.Version
   180  
   181  	var v []string
   182  	libkb.VersionMessage(func(s string) {
   183  		v = append(v, s)
   184  	})
   185  	c.VersionFull = strings.Join(v, "\n")
   186  
   187  	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
   188  	if err == nil {
   189  		c.Path = dir
   190  	} else {
   191  		mctx.Warning("Failed to get service path: %s", err)
   192  	}
   193  
   194  	realpath, err := libkb.CurrentBinaryRealpath()
   195  	if err == nil {
   196  		c.BinaryRealpath = realpath
   197  	} else {
   198  		mctx.Debug("Failed to get service realpath: %s", err)
   199  	}
   200  
   201  	c.ConfigPath = mctx.G().Env.GetConfigFilename()
   202  	c.Label = mctx.G().Env.GetLabel()
   203  	if forkType == keybase1.ForkType_AUTO {
   204  		c.IsAutoForked = true
   205  	}
   206  	c.ForkType = forkType
   207  	return c, nil
   208  }
   209  
   210  func GetFullStatus(mctx libkb.MetaContext) (status *keybase1.FullStatus, err error) {
   211  	status = &keybase1.FullStatus{}
   212  	// The client overrides this value when sending logs
   213  	status.Client.Version = libkb.VersionString()
   214  	status.ConfigPath = mctx.G().Env.GetConfigFilename()
   215  
   216  	status.CurStatus, err = GetCurrentStatus(mctx)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  	// Duplicate the username at top-level for backwards compatibility of
   222  	// output.
   223  	if status.CurStatus.User != nil {
   224  		status.Username = status.CurStatus.User.Username
   225  	}
   226  
   227  	status.ExtStatus, err = GetExtendedStatus(mctx)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  
   232  	// set service status
   233  	if status.ExtStatus.Standalone {
   234  		status.Service.Running = false
   235  	} else {
   236  		status.Service.Running = true
   237  	}
   238  	status.Service.Version = libkb.VersionString()
   239  
   240  	// set kbfs status
   241  	kbfsInstalledVersion, err := install.KBFSBundleVersion(mctx.G(), "")
   242  	if err != nil {
   243  		mctx.Debug("Failed to get KBFSBundleVersion: %s", err)
   244  	} else {
   245  		mctx.Debug("Got KBFSBundleVersion: %s", kbfsInstalledVersion)
   246  		status.Kbfs.InstalledVersion = kbfsInstalledVersion
   247  	}
   248  	if kbfs := GetFirstClient(status.ExtStatus.Clients, keybase1.ClientType_KBFS); kbfs != nil {
   249  		status.Kbfs.Version = kbfs.Version
   250  		status.Kbfs.Running = true
   251  		// This just gets the mountpoint from the environment; the
   252  		// user could have technically passed a different mountpoint
   253  		// to KBFS on macOS or Linux.  TODO(KBFS-2723): fetch the
   254  		// actual mountpoint with a new RPC from KBFS.
   255  		mountDir, err := mctx.G().Env.GetMountDir()
   256  		if err != nil {
   257  			return nil, err
   258  		}
   259  		status.Kbfs.Mount = mountDir
   260  	} else {
   261  		status.Kbfs.Version = kbfsInstalledVersion
   262  	}
   263  
   264  	// set desktop status
   265  	if desktop := GetFirstClient(status.ExtStatus.Clients, keybase1.ClientType_GUI_MAIN); desktop != nil {
   266  		status.Desktop.Running = true
   267  		status.Desktop.Version = desktop.Version
   268  	}
   269  
   270  	// set log paths
   271  	status.Service.Log = getServiceLog(mctx, status.ExtStatus.LogDir)
   272  	status.Service.EkLog = filepath.Join(status.ExtStatus.LogDir, libkb.EKLogFileName)
   273  	status.Service.PerfLog = filepath.Join(status.ExtStatus.LogDir, libkb.PerfLogFileName)
   274  	status.Kbfs.Log = filepath.Join(status.ExtStatus.LogDir, libkb.KBFSLogFileName)
   275  	status.Kbfs.PerfLog = filepath.Join(status.ExtStatus.LogDir, libkb.KBFSPerfLogFileName)
   276  	status.Desktop.Log = filepath.Join(status.ExtStatus.LogDir, libkb.GUILogFileName)
   277  	status.Updater.Log = filepath.Join(status.ExtStatus.LogDir, libkb.UpdaterLogFileName)
   278  	status.Start.Log = filepath.Join(status.ExtStatus.LogDir, libkb.StartLogFileName)
   279  	status.Git.Log = filepath.Join(status.ExtStatus.LogDir, libkb.GitLogFileName)
   280  	status.Git.PerfLog = filepath.Join(status.ExtStatus.LogDir, libkb.GitPerfLogFileName)
   281  
   282  	// set anything os-specific
   283  	mctx.Debug("Getting osSpecific status info")
   284  	if err := osSpecific(mctx, status); err != nil {
   285  		return nil, err
   286  	}
   287  	return status, nil
   288  }