github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/env.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"os/user"
    10  	"path/filepath"
    11  	"runtime"
    12  	"strconv"
    13  	"strings"
    14  	"sync"
    15  	"time"
    16  
    17  	logger "github.com/keybase/client/go/logger"
    18  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    19  	"github.com/keybase/client/go/systemd"
    20  	"github.com/syndtr/goleveldb/leveldb/opt"
    21  )
    22  
    23  type NullConfiguration struct{}
    24  
    25  func (n NullConfiguration) GetHome() string                                                { return "" }
    26  func (n NullConfiguration) GetMobileSharedHome() string                                    { return "" }
    27  func (n NullConfiguration) GetServerURI() (string, error)                                  { return "", nil }
    28  func (n NullConfiguration) GetConfigFilename() string                                      { return "" }
    29  func (n NullConfiguration) GetUpdaterConfigFilename() string                               { return "" }
    30  func (n NullConfiguration) GetGUIConfigFilename() string                                   { return "" }
    31  func (n NullConfiguration) GetDeviceCloneStateFilename() string                            { return "" }
    32  func (n NullConfiguration) GetSessionFilename() string                                     { return "" }
    33  func (n NullConfiguration) GetDbFilename() string                                          { return "" }
    34  func (n NullConfiguration) GetChatDbFilename() string                                      { return "" }
    35  func (n NullConfiguration) GetPvlKitFilename() string                                      { return "" }
    36  func (n NullConfiguration) GetParamProofKitFilename() string                               { return "" }
    37  func (n NullConfiguration) GetExternalURLKitFilename() string                              { return "" }
    38  func (n NullConfiguration) GetProveBypass() (bool, bool)                                   { return false, false }
    39  func (n NullConfiguration) GetUsername() NormalizedUsername                                { return NormalizedUsername("") }
    40  func (n NullConfiguration) GetEmail() string                                               { return "" }
    41  func (n NullConfiguration) GetProxy() string                                               { return "" }
    42  func (n NullConfiguration) GetProxyType() string                                           { return "" }
    43  func (n NullConfiguration) IsCertPinningEnabled() bool                                     { return true }
    44  func (n NullConfiguration) GetGpgHome() string                                             { return "" }
    45  func (n NullConfiguration) GetBundledCA(h string) string                                   { return "" }
    46  func (n NullConfiguration) GetUserCacheMaxAge() (time.Duration, bool)                      { return 0, false }
    47  func (n NullConfiguration) GetProofCacheSize() (int, bool)                                 { return 0, false }
    48  func (n NullConfiguration) GetProofCacheLongDur() (time.Duration, bool)                    { return 0, false }
    49  func (n NullConfiguration) GetProofCacheMediumDur() (time.Duration, bool)                  { return 0, false }
    50  func (n NullConfiguration) GetProofCacheShortDur() (time.Duration, bool)                   { return 0, false }
    51  func (n NullConfiguration) GetLinkCacheSize() (int, bool)                                  { return 0, false }
    52  func (n NullConfiguration) GetLinkCacheCleanDur() (time.Duration, bool)                    { return 0, false }
    53  func (n NullConfiguration) GetUPAKCacheSize() (int, bool)                                  { return 0, false }
    54  func (n NullConfiguration) GetUIDMapFullNameCacheSize() (int, bool)                        { return 0, false }
    55  func (n NullConfiguration) GetPayloadCacheSize() (int, bool)                               { return 0, false }
    56  func (n NullConfiguration) GetMerkleKIDs() []string                                        { return nil }
    57  func (n NullConfiguration) GetCodeSigningKIDs() []string                                   { return nil }
    58  func (n NullConfiguration) GetPinentry() string                                            { return "" }
    59  func (n NullConfiguration) GetUID() (ret keybase1.UID)                                     { return }
    60  func (n NullConfiguration) GetGpg() string                                                 { return "" }
    61  func (n NullConfiguration) GetGpgOptions() []string                                        { return nil }
    62  func (n NullConfiguration) GetPGPFingerprint() *PGPFingerprint                             { return nil }
    63  func (n NullConfiguration) GetSecretKeyringTemplate() string                               { return "" }
    64  func (n NullConfiguration) GetSalt() []byte                                                { return nil }
    65  func (n NullConfiguration) GetSocketFile() string                                          { return "" }
    66  func (n NullConfiguration) GetPidFile() string                                             { return "" }
    67  func (n NullConfiguration) GetStandalone() (bool, bool)                                    { return false, false }
    68  func (n NullConfiguration) GetLocalRPCDebug() string                                       { return "" }
    69  func (n NullConfiguration) GetTimers() string                                              { return "" }
    70  func (n NullConfiguration) GetDeviceID() keybase1.DeviceID                                 { return "" }
    71  func (n NullConfiguration) GetDeviceIDForUsername(un NormalizedUsername) keybase1.DeviceID { return "" }
    72  func (n NullConfiguration) GetDeviceIDForUID(u keybase1.UID) keybase1.DeviceID             { return "" }
    73  func (n NullConfiguration) GetProxyCACerts() ([]string, error)                             { return nil, nil }
    74  func (n NullConfiguration) GetUsernameForUID(u keybase1.UID) NormalizedUsername {
    75  	return NormalizedUsername("")
    76  }
    77  func (n NullConfiguration) GetUIDForUsername(u NormalizedUsername) keybase1.UID {
    78  	return keybase1.UID("")
    79  }
    80  func (n NullConfiguration) GetStayLoggedOut() (bool, bool)                  { return false, false }
    81  func (n NullConfiguration) GetAutoFork() (bool, bool)                       { return false, false }
    82  func (n NullConfiguration) GetRunMode() (RunMode, error)                    { return NoRunMode, nil }
    83  func (n NullConfiguration) GetNoAutoFork() (bool, bool)                     { return false, false }
    84  func (n NullConfiguration) GetLogFile() string                              { return "" }
    85  func (n NullConfiguration) GetEKLogFile() string                            { return "" }
    86  func (n NullConfiguration) GetPerfLogFile() string                          { return "" }
    87  func (n NullConfiguration) GetGUILogFile() string                           { return "" }
    88  func (n NullConfiguration) GetUseDefaultLogFile() (bool, bool)              { return false, false }
    89  func (n NullConfiguration) GetUseRootConfigFile() (bool, bool)              { return false, false }
    90  func (n NullConfiguration) GetLogPrefix() string                            { return "" }
    91  func (n NullConfiguration) GetScraperTimeout() (time.Duration, bool)        { return 0, false }
    92  func (n NullConfiguration) GetAPITimeout() (time.Duration, bool)            { return 0, false }
    93  func (n NullConfiguration) GetTorMode() (TorMode, error)                    { return TorNone, nil }
    94  func (n NullConfiguration) GetTorHiddenAddress() string                     { return "" }
    95  func (n NullConfiguration) GetTorProxy() string                             { return "" }
    96  func (n NullConfiguration) GetUpdatePreferenceAuto() (bool, bool)           { return false, false }
    97  func (n NullConfiguration) GetUpdatePreferenceSnoozeUntil() keybase1.Time   { return keybase1.Time(0) }
    98  func (n NullConfiguration) GetUpdateLastChecked() keybase1.Time             { return keybase1.Time(0) }
    99  func (n NullConfiguration) GetUpdatePreferenceSkip() string                 { return "" }
   100  func (n NullConfiguration) GetUpdateURL() string                            { return "" }
   101  func (n NullConfiguration) GetUpdateDisabled() (bool, bool)                 { return false, false }
   102  func (n NullConfiguration) GetVDebugSetting() string                        { return "" }
   103  func (n NullConfiguration) GetLocalTrackMaxAge() (time.Duration, bool)      { return 0, false }
   104  func (n NullConfiguration) GetGregorURI() string                            { return "" }
   105  func (n NullConfiguration) GetGregorSaveInterval() (time.Duration, bool)    { return 0, false }
   106  func (n NullConfiguration) GetGregorPingInterval() (time.Duration, bool)    { return 0, false }
   107  func (n NullConfiguration) GetGregorPingTimeout() (time.Duration, bool)     { return 0, false }
   108  func (n NullConfiguration) GetChatDelivererInterval() (time.Duration, bool) { return 0, false }
   109  func (n NullConfiguration) GetGregorDisabled() (bool, bool)                 { return false, false }
   110  func (n NullConfiguration) GetSecretStorePrimingDisabled() (bool, bool)     { return false, false }
   111  func (n NullConfiguration) GetMountDir() string                             { return "" }
   112  func (n NullConfiguration) GetMountDirDefault() string                      { return "" }
   113  func (n NullConfiguration) GetBGIdentifierDisabled() (bool, bool)           { return false, false }
   114  func (n NullConfiguration) GetFeatureFlags() (FeatureFlags, error)          { return FeatureFlags{}, nil }
   115  func (n NullConfiguration) GetAppType() AppType                             { return NoAppType }
   116  func (n NullConfiguration) IsMobileExtension() (bool, bool)                 { return false, false }
   117  func (n NullConfiguration) GetSlowGregorConn() (bool, bool)                 { return false, false }
   118  func (n NullConfiguration) GetReadDeletedSigChain() (bool, bool)            { return false, false }
   119  func (n NullConfiguration) GetRememberPassphrase(NormalizedUsername) (bool, bool) {
   120  	return false, false
   121  }
   122  func (n NullConfiguration) GetLevelDBNumFiles() (int, bool)                { return 0, false }
   123  func (n NullConfiguration) GetLevelDBWriteBufferMB() (int, bool)           { return 4, false }
   124  func (n NullConfiguration) GetChatInboxSourceLocalizeThreads() (int, bool) { return 1, false }
   125  func (n NullConfiguration) GetAttachmentHTTPStartPort() (int, bool)        { return 0, false }
   126  func (n NullConfiguration) GetAttachmentDisableMulti() (bool, bool)        { return false, false }
   127  func (n NullConfiguration) GetDisableTeamAuditor() (bool, bool)            { return false, false }
   128  func (n NullConfiguration) GetDisableMerkleAuditor() (bool, bool)          { return false, false }
   129  func (n NullConfiguration) GetDisableSearchIndexer() (bool, bool)          { return false, false }
   130  func (n NullConfiguration) GetDisableBgConvLoader() (bool, bool)           { return false, false }
   131  func (n NullConfiguration) GetDisableTeamBoxAuditor() (bool, bool)         { return false, false }
   132  func (n NullConfiguration) GetDisableEKBackgroundKeygen() (bool, bool)     { return false, false }
   133  func (n NullConfiguration) GetEnableBotLiteMode() (bool, bool)             { return false, false }
   134  func (n NullConfiguration) GetExtraNetLogging() (bool, bool)               { return false, false }
   135  func (n NullConfiguration) GetForceLinuxKeyring() (bool, bool)             { return false, false }
   136  func (n NullConfiguration) GetForceSecretStoreFile() (bool, bool)          { return false, false }
   137  func (n NullConfiguration) GetRuntimeStatsEnabled() (bool, bool)           { return false, false }
   138  func (n NullConfiguration) GetPassphraseState() *keybase1.PassphraseState  { return nil }
   139  func (n NullConfiguration) GetPassphraseStateForUsername(NormalizedUsername) *keybase1.PassphraseState {
   140  	return nil
   141  }
   142  
   143  func (n NullConfiguration) GetBug3964RepairTime(NormalizedUsername) (time.Time, error) {
   144  	return time.Time{}, nil
   145  }
   146  func (n NullConfiguration) GetUserConfig() (*UserConfig, error) { return nil, nil }
   147  func (n NullConfiguration) GetUserConfigForUsername(s NormalizedUsername) (*UserConfig, error) {
   148  	return nil, nil
   149  }
   150  func (n NullConfiguration) GetGString(string) string          { return "" }
   151  func (n NullConfiguration) GetString(string) string           { return "" }
   152  func (n NullConfiguration) GetBool(string, bool) (bool, bool) { return false, false }
   153  
   154  func (n NullConfiguration) GetAllUsernames() (NormalizedUsername, []NormalizedUsername, error) {
   155  	return NormalizedUsername(""), nil, nil
   156  }
   157  func (n NullConfiguration) GetAllUserConfigs() (*UserConfig, []UserConfig, error) {
   158  	return nil, nil, nil
   159  }
   160  
   161  func (n NullConfiguration) GetDebug() (bool, bool)            { return false, false }
   162  func (n NullConfiguration) GetDebugJourneycard() (bool, bool) { return false, false }
   163  func (n NullConfiguration) GetDisplayRawUntrustedOutput() (bool, bool) {
   164  	return false, false
   165  }
   166  func (n NullConfiguration) GetLogFormat() string {
   167  	return ""
   168  }
   169  func (n NullConfiguration) GetAPIDump() (bool, bool) {
   170  	return false, false
   171  }
   172  func (n NullConfiguration) GetNoPinentry() (bool, bool) {
   173  	return false, false
   174  }
   175  
   176  func (n NullConfiguration) GetStringAtPath(string) (string, bool) {
   177  	return "", false
   178  }
   179  func (n NullConfiguration) GetInterfaceAtPath(string) (interface{}, error) {
   180  	return nil, nil
   181  }
   182  
   183  func (n NullConfiguration) GetBoolAtPath(string) (bool, bool) {
   184  	return false, false
   185  }
   186  
   187  func (n NullConfiguration) GetIntAtPath(string) (int, bool) {
   188  	return 0, false
   189  }
   190  
   191  func (n NullConfiguration) GetFloatAtPath(string) (float64, bool) {
   192  	return 0, false
   193  }
   194  
   195  func (n NullConfiguration) GetNullAtPath(string) bool {
   196  	return false
   197  }
   198  
   199  func (n NullConfiguration) GetSecurityAccessGroupOverride() (bool, bool) {
   200  	return false, false
   201  }
   202  
   203  func (n NullConfiguration) GetAndroidInstallReferrerChecked() bool { return false }
   204  
   205  type TestParameters struct {
   206  	ConfigFilename   string
   207  	Home             string
   208  	MobileSharedHome string
   209  	GPG              string
   210  	GPGHome          string
   211  	GPGOptions       []string
   212  	Debug            bool
   213  	// Whether we are in Devel Mode
   214  	Devel bool
   215  	// If we're in dev mode, the name for this test, with a random
   216  	// suffix.
   217  	DevelName                string
   218  	DevelPrefix              string // when in test - name for the test without suffix.
   219  	RuntimeDir               string
   220  	DisableUpgradePerUserKey bool
   221  	EnvironmentFeatureFlags  FeatureFlags
   222  
   223  	// set to true to use production run mode in tests
   224  	UseProductionRunMode bool
   225  
   226  	// whether LogoutIfRevoked check should be skipped to avoid races
   227  	// during resets.
   228  	SkipLogoutIfRevokedCheck bool
   229  
   230  	// On if, in test, we want to skip sending system chat messages
   231  	SkipSendingSystemChatMessages bool
   232  
   233  	// If we need to use the real clock for NIST generation (as in really
   234  	// whacky tests liks TestRekey).
   235  	UseTimeClockForNISTs bool
   236  
   237  	// TeamNoHeadMerkleStore is used for testing to emulate older clients
   238  	// that didn't store the head merkle sequence to team chain state. We
   239  	// have an upgrade path in the code that we'd like to test.
   240  	TeamNoHeadMerkleStore bool
   241  
   242  	// TeamSkipAudit is on because some team chains are "canned" and therefore
   243  	// might point off of the merkle sequence in the database. So it's just
   244  	// easiest to skip the audit in those cases.
   245  	TeamSkipAudit bool
   246  
   247  	// NoGregor is on if we want to test the service without any gregor conection
   248  	NoGregor bool
   249  
   250  	// TeamAuditParams can be customized if we want to control the behavior
   251  	// of audits deep in a test
   252  	TeamAuditParams *TeamAuditParams
   253  
   254  	// Toggle if we want to try to 'prime' the secret store before using it.
   255  	SecretStorePrimingDisabled bool
   256  
   257  	// Extra headers for API
   258  	APIHeaders map[string]string
   259  }
   260  
   261  func (tp TestParameters) GetDebug() (bool, bool) {
   262  	if tp.Debug {
   263  		return true, true
   264  	}
   265  	return false, false
   266  }
   267  
   268  func (tp TestParameters) GetNoGregor() (bool, bool) {
   269  	if tp.NoGregor {
   270  		return true, true
   271  	}
   272  	return false, false
   273  }
   274  
   275  func (tp TestParameters) GetSecretStorePrimingDisabled() (bool, bool) {
   276  	if tp.SecretStorePrimingDisabled {
   277  		return true, true
   278  	}
   279  	return false, false
   280  }
   281  
   282  type Env struct {
   283  	sync.RWMutex
   284  	cmd           CommandLine
   285  	config        ConfigReader
   286  	HomeFinder    HomeFinder
   287  	writer        ConfigWriter
   288  	Test          *TestParameters
   289  	updaterConfig UpdaterConfigReader
   290  	guiConfig     *JSONFile
   291  }
   292  
   293  func (e *Env) GetConfig() ConfigReader {
   294  	e.RLock()
   295  	defer e.RUnlock()
   296  	return e.config
   297  }
   298  
   299  func (e *Env) GetConfigWriter() ConfigWriter {
   300  	e.RLock()
   301  	defer e.RUnlock()
   302  	return e.writer
   303  }
   304  
   305  func (e *Env) SetCommandLine(cmd CommandLine) {
   306  	e.Lock()
   307  	defer e.Unlock()
   308  	e.cmd = cmd
   309  }
   310  
   311  func (e *Env) GetCommandLine() CommandLine {
   312  	e.RLock()
   313  	defer e.RUnlock()
   314  	return e.cmd
   315  }
   316  
   317  func (e *Env) SetConfig(r ConfigReader, w ConfigWriter) {
   318  	e.Lock()
   319  	defer e.Unlock()
   320  	e.config = r
   321  	e.writer = w
   322  }
   323  
   324  func (e *Env) SetGUIConfig(j *JSONFile) {
   325  	e.Lock()
   326  	defer e.Unlock()
   327  	e.guiConfig = j
   328  }
   329  
   330  func (e *Env) GetGUIConfig() *JSONFile {
   331  	e.RLock()
   332  	defer e.RUnlock()
   333  	return e.guiConfig
   334  }
   335  
   336  func (e *Env) SetUpdaterConfig(r UpdaterConfigReader) {
   337  	e.Lock()
   338  	defer e.Unlock()
   339  	e.updaterConfig = r
   340  }
   341  
   342  func (e *Env) GetUpdaterConfig() UpdaterConfigReader {
   343  	e.RLock()
   344  	defer e.RUnlock()
   345  	return e.updaterConfig
   346  }
   347  
   348  func (e *Env) GetOldMountDirDefault() string {
   349  	switch RuntimeGroup() {
   350  	case keybase1.RuntimeGroup_LINUXLIKE:
   351  		return filepath.Join(e.GetDataDir(), "fs")
   352  	default:
   353  		return e.GetMountDirDefault()
   354  	}
   355  }
   356  
   357  func (e *Env) GetMountDirDefault() string {
   358  	switch RuntimeGroup() {
   359  	case keybase1.RuntimeGroup_DARWINLIKE:
   360  		volumes := "/Volumes"
   361  		user, err := user.Current()
   362  		var username string
   363  		if err != nil {
   364  			// The iOS simulator may not have a proper user set,
   365  			username = "<unknown>"
   366  		} else {
   367  			username = user.Username
   368  		}
   369  		var runmodeName string
   370  		switch e.GetRunMode() {
   371  		case DevelRunMode:
   372  			runmodeName = "KeybaseDevel"
   373  		case StagingRunMode:
   374  			runmodeName = "KeybaseStaging"
   375  		case ProductionRunMode:
   376  			runmodeName = "Keybase"
   377  		default:
   378  			panic("Invalid run mode")
   379  		}
   380  		return filepath.Join(volumes, fmt.Sprintf(
   381  			"%s (%s)", runmodeName, username))
   382  	case keybase1.RuntimeGroup_LINUXLIKE:
   383  		return filepath.Join(e.GetRuntimeDir(), "kbfs")
   384  	// kbfsdokan depends on an empty default
   385  	case keybase1.RuntimeGroup_WINDOWSLIKE:
   386  		return ""
   387  	default:
   388  		return filepath.Join(e.GetRuntimeDir(), "kbfs")
   389  	}
   390  }
   391  
   392  func (e *Env) GetMountDir() (string, error) {
   393  	return e.GetString(
   394  		func() string { return e.cmd.GetMountDir() },
   395  		func() string { return os.Getenv("KEYBASE_MOUNTDIR") },
   396  		func() string { return e.GetConfig().GetMountDir() },
   397  		e.GetMountDirDefault,
   398  	), nil
   399  }
   400  
   401  func NewEnv(cmd CommandLine, config ConfigReader, getLog LogGetter) *Env {
   402  	return newEnv(cmd, config, runtime.GOOS, getLog)
   403  }
   404  
   405  func newEnv(cmd CommandLine, config ConfigReader, osname string, getLog LogGetter) *Env {
   406  	if cmd == nil {
   407  		cmd = NullConfiguration{}
   408  	}
   409  	if config == nil {
   410  		config = NullConfiguration{}
   411  	}
   412  	e := Env{cmd: cmd, config: config, Test: &TestParameters{}}
   413  
   414  	e.HomeFinder = NewHomeFinder("keybase",
   415  		e.getHomeFromTestOrCmd,
   416  		func() string { return e.GetConfig().GetHome() },
   417  		e.getMobileSharedHomeFromCmdOrConfig,
   418  		osname,
   419  		e.GetRunMode,
   420  		getLog,
   421  		os.Getenv)
   422  	return &e
   423  }
   424  
   425  func (e *Env) getHomeFromTestOrCmd() string {
   426  	return e.GetString(
   427  		func() string { return e.Test.Home },
   428  		func() string {
   429  			home := e.cmd.GetHome()
   430  			if home == "" {
   431  				return ""
   432  			}
   433  			absHome, err := filepath.Abs(home)
   434  			if err != nil {
   435  				return home
   436  			}
   437  			return absHome
   438  		},
   439  	)
   440  }
   441  
   442  func (e *Env) getMobileSharedHomeFromCmdOrConfig() string {
   443  	return e.GetString(
   444  		func() string { return e.Test.MobileSharedHome },
   445  		func() string { return e.cmd.GetMobileSharedHome() },
   446  		func() string { return e.GetConfig().GetMobileSharedHome() },
   447  	)
   448  }
   449  
   450  func (e *Env) GetDownloadsDir() string     { return e.HomeFinder.DownloadsDir() }
   451  func (e *Env) GetHome() string             { return e.HomeFinder.Home(false) }
   452  func (e *Env) GetMobileSharedHome() string { return e.HomeFinder.MobileSharedHome(false) }
   453  func (e *Env) GetConfigDir() string        { return e.HomeFinder.ConfigDir() }
   454  func (e *Env) GetCacheDir() string         { return e.HomeFinder.CacheDir() }
   455  func (e *Env) GetSharedCacheDir() string   { return e.HomeFinder.SharedCacheDir() }
   456  func (e *Env) GetSandboxCacheDir() string  { return e.HomeFinder.SandboxCacheDir() }
   457  func (e *Env) GetDataDir() string          { return e.HomeFinder.DataDir() }
   458  func (e *Env) GetSharedDataDir() string    { return e.HomeFinder.SharedDataDir() }
   459  func (e *Env) GetLogDir() string           { return e.HomeFinder.LogDir() }
   460  
   461  func (e *Env) SendSystemChatMessages() bool {
   462  	return !e.Test.SkipSendingSystemChatMessages
   463  }
   464  
   465  func (e *Env) UseTimeClockForNISTs() bool {
   466  	return e.Test.UseTimeClockForNISTs
   467  }
   468  
   469  func (e *Env) GetRuntimeDir() string {
   470  	return e.GetString(
   471  		func() string { return e.Test.RuntimeDir },
   472  		func() string { return e.HomeFinder.RuntimeDir() },
   473  	)
   474  }
   475  
   476  func (e *Env) GetInfoDir() string {
   477  	return e.GetString(
   478  		func() string { return e.Test.RuntimeDir }, // needed for systests
   479  		func() string { return e.HomeFinder.InfoDir() },
   480  	)
   481  }
   482  
   483  func (e *Env) GetServiceSpawnDir() (string, error) { return e.HomeFinder.ServiceSpawnDir() }
   484  
   485  func (e *Env) getEnvInt(s string) (int, bool) {
   486  	v := os.Getenv(s)
   487  	if len(v) > 0 {
   488  		tmp, err := strconv.ParseInt(v, 0, 64)
   489  		if err == nil {
   490  			return int(tmp), true
   491  		}
   492  	}
   493  	return 0, false
   494  }
   495  
   496  func (e *Env) getEnvPath(s string) []string {
   497  	if tmp := os.Getenv(s); len(tmp) != 0 {
   498  		return strings.Split(tmp, ":")
   499  	}
   500  	return nil
   501  }
   502  
   503  func (e *Env) getEnvBool(s string) (bool, bool) {
   504  	return getEnvBool(s)
   505  }
   506  
   507  func getEnvBool(s string) (bool, bool) {
   508  	tmp := os.Getenv(s)
   509  	if len(tmp) == 0 {
   510  		return false, false
   511  	}
   512  	tmp = strings.ToLower(tmp)
   513  	if tmp == "0" || tmp[0] == byte('n') {
   514  		return false, true
   515  	}
   516  	return true, true
   517  }
   518  
   519  func (e *Env) getEnvDuration(s string) (time.Duration, bool) {
   520  	d, err := time.ParseDuration(os.Getenv(s))
   521  	if err != nil {
   522  		return 0, false
   523  	}
   524  	return d, true
   525  }
   526  
   527  func (e *Env) GetString(flist ...(func() string)) string {
   528  	var ret string
   529  	for _, f := range flist {
   530  		ret = f()
   531  		if len(ret) > 0 {
   532  			break
   533  		}
   534  	}
   535  	return ret
   536  }
   537  
   538  func (e *Env) GetBool(def bool, flist ...func() (bool, bool)) bool {
   539  	for _, f := range flist {
   540  		if val, isSet := f(); isSet {
   541  			return val
   542  		}
   543  	}
   544  	return def
   545  }
   546  
   547  type NegBoolFunc struct {
   548  	neg bool
   549  	f   func() (bool, bool)
   550  }
   551  
   552  // GetNegBool gets a negatable bool.  You can give it a list of functions,
   553  // and also possible negations for those functions.
   554  func (e *Env) GetNegBool(def bool, flist []NegBoolFunc) bool {
   555  	for _, f := range flist {
   556  		if val, isSet := f.f(); isSet {
   557  			return (val != f.neg)
   558  		}
   559  	}
   560  	return def
   561  }
   562  
   563  func (e *Env) GetInt(def int, flist ...func() (int, bool)) int {
   564  	for _, f := range flist {
   565  		if val, isSet := f(); isSet {
   566  			return val
   567  		}
   568  	}
   569  	return def
   570  }
   571  
   572  func (e *Env) GetDuration(def time.Duration, flist ...func() (time.Duration, bool)) time.Duration {
   573  	for _, f := range flist {
   574  		if val, isSet := f(); isSet {
   575  			return val
   576  		}
   577  	}
   578  	return def
   579  }
   580  
   581  func (e *Env) GetServerURI() (string, error) {
   582  	// appveyor and os x travis CI set server URI, so need to
   583  	// check for test flag here in order for production api endpoint
   584  	// tests to pass.
   585  	if e.Test.UseProductionRunMode {
   586  		server, e := ServerLookup(e, e.GetRunMode())
   587  		if e != nil {
   588  			return "", nil
   589  		}
   590  		return server, nil
   591  	}
   592  
   593  	serverURI := e.GetString(
   594  		func() string {
   595  			serverURI, err := e.cmd.GetServerURI()
   596  			if err != nil {
   597  				return ""
   598  			}
   599  			return serverURI
   600  		},
   601  		func() string { return os.Getenv("KEYBASE_SERVER_URI") },
   602  		func() string {
   603  			serverURI, err := e.GetConfig().GetServerURI()
   604  			if err != nil {
   605  				return ""
   606  			}
   607  			return serverURI
   608  		},
   609  		func() string {
   610  			serverURI, err := ServerLookup(e, e.GetRunMode())
   611  			if err != nil {
   612  				return ""
   613  			}
   614  			return serverURI
   615  		},
   616  	)
   617  
   618  	if serverURI == "" {
   619  		return "", fmt.Errorf("Env failed to read a server URI from any source!")
   620  	}
   621  	return serverURI, nil
   622  }
   623  
   624  func (e *Env) GetUseRootConfigFile() bool {
   625  	return e.GetBool(false, e.cmd.GetUseRootConfigFile)
   626  }
   627  
   628  func (e *Env) GetRootRedirectorMount() (string, error) {
   629  	switch RuntimeGroup() {
   630  	case keybase1.RuntimeGroup_LINUXLIKE, keybase1.RuntimeGroup_DARWINLIKE:
   631  		return "/keybase", nil
   632  	default:
   633  		return "", fmt.Errorf("Root redirector mount unknown on this system.")
   634  	}
   635  }
   636  
   637  func (e *Env) GetRootConfigDirectory() (string, error) {
   638  	// NOTE: If this ever changes to more than one level deep, the configure
   639  	// redirector CLI command needs to be updated to update the permissions
   640  	// back to 0644 for all the created directories, or other processes won't
   641  	// be able to read them.
   642  	// Alternatively, we could package a blank config.json in that directory,
   643  	// but we can't rely on that for other packages.
   644  	switch RuntimeGroup() {
   645  	case keybase1.RuntimeGroup_LINUXLIKE:
   646  		return "/etc/keybase/", nil
   647  	default:
   648  		return "", fmt.Errorf("Root config directory unknown on this system")
   649  	}
   650  }
   651  
   652  func (e *Env) GetRootConfigFilename() (string, error) {
   653  	dir, err := e.GetRootConfigDirectory()
   654  	if err != nil {
   655  		return "", err
   656  	}
   657  	return filepath.Join(dir, "config.json"), nil
   658  }
   659  
   660  func (e *Env) GetEnvFileDir() (string, error) {
   661  	switch RuntimeGroup() {
   662  	case keybase1.RuntimeGroup_LINUXLIKE:
   663  		// Do not respect $XDG_CONFIG_HOME due to debian systemd 229 not supporting %E
   664  		// see keybase.service systemd unit
   665  		return filepath.Join(e.GetHome(), ".config", "keybase"), nil
   666  	default:
   667  		return "", fmt.Errorf("No envfiledir for %s.", runtime.GOOS)
   668  	}
   669  }
   670  
   671  func (e *Env) GetEnvfileName() (string, error) {
   672  	dir, err := e.GetEnvFileDir()
   673  	if err != nil {
   674  		return "", err
   675  	}
   676  	return filepath.Join(dir, "keybase.autogen.env"), nil
   677  }
   678  
   679  func (e *Env) GetOverrideEnvfileName() (string, error) {
   680  	dir, err := e.GetEnvFileDir()
   681  	if err != nil {
   682  		return "", err
   683  	}
   684  	return filepath.Join(dir, "keybase.env"), nil
   685  }
   686  
   687  func (e *Env) GetConfigFilename() string {
   688  	return e.GetString(
   689  		func() string {
   690  			if e.GetUseRootConfigFile() {
   691  				ret, err := e.GetRootConfigFilename()
   692  				if err != nil {
   693  					return ""
   694  				}
   695  				return ret
   696  			}
   697  			return ""
   698  		},
   699  		func() string { return e.Test.ConfigFilename },
   700  		func() string { return e.cmd.GetConfigFilename() },
   701  		func() string { return os.Getenv("KEYBASE_CONFIG_FILE") },
   702  		func() string { return e.GetConfig().GetConfigFilename() },
   703  		func() string { return filepath.Join(e.GetConfigDir(), ConfigFile) },
   704  	)
   705  }
   706  
   707  func (e *Env) GetUpdaterConfigFilename() string {
   708  	return e.GetString(
   709  		func() string {
   710  			if e.GetUseRootConfigFile() {
   711  				dir, err := e.GetRootConfigDirectory()
   712  				if err != nil {
   713  					return ""
   714  				}
   715  				return filepath.Join(dir, UpdaterConfigFile)
   716  			}
   717  			return ""
   718  		},
   719  		func() string { return e.cmd.GetUpdaterConfigFilename() },
   720  		func() string { return os.Getenv("KEYBASE_UPDATER_CONFIG_FILE") },
   721  		func() string { return e.GetConfig().GetUpdaterConfigFilename() },
   722  		func() string { return filepath.Join(e.GetConfigDir(), UpdaterConfigFile) },
   723  	)
   724  }
   725  
   726  func (e *Env) GetGUIConfigFilename() string {
   727  	return e.GetString(
   728  		func() string {
   729  			if e.GetUseRootConfigFile() {
   730  				dir, err := e.GetRootConfigDirectory()
   731  				if err != nil {
   732  					return ""
   733  				}
   734  				return filepath.Join(dir, GUIConfigFile)
   735  			}
   736  			return ""
   737  		},
   738  		func() string { return e.cmd.GetGUIConfigFilename() },
   739  		func() string { return os.Getenv("KEYBASE_GUI_CONFIG_FILE") },
   740  		func() string { return e.GetConfig().GetGUIConfigFilename() },
   741  		func() string { return filepath.Join(e.GetConfigDir(), GUIConfigFile) },
   742  	)
   743  }
   744  
   745  func (e *Env) GetDeviceCloneStateFilename() string {
   746  	return e.GetString(
   747  		func() string { return e.cmd.GetDeviceCloneStateFilename() },
   748  		func() string { return os.Getenv("KEYBASE_DEVICE_CLONE_STATE_FILE") },
   749  		func() string { return e.GetConfig().GetDeviceCloneStateFilename() },
   750  		func() string { return filepath.Join(e.GetConfigDir(), DeviceCloneStateFile) },
   751  	)
   752  }
   753  
   754  func (e *Env) GetSessionFilename() string {
   755  	return e.GetString(
   756  		func() string { return e.cmd.GetSessionFilename() },
   757  		func() string { return os.Getenv("KEYBASE_SESSION_FILE") },
   758  		func() string { return e.GetConfig().GetSessionFilename() },
   759  		func() string { return filepath.Join(e.GetCacheDir(), SessionFile) },
   760  	)
   761  }
   762  
   763  func (e *Env) GetDbFilename() string {
   764  	return e.GetString(
   765  		func() string { return e.cmd.GetDbFilename() },
   766  		func() string { return os.Getenv("KEYBASE_DB_FILE") },
   767  		func() string { return e.GetConfig().GetDbFilename() },
   768  		func() string { return filepath.Join(e.GetDataDir(), DBFile) },
   769  	)
   770  }
   771  
   772  func (e *Env) GetChatDbFilename() string {
   773  	return e.GetString(
   774  		func() string { return e.cmd.GetChatDbFilename() },
   775  		func() string { return os.Getenv("KEYBASE_CHAT_DB_FILE") },
   776  		func() string { return e.GetConfig().GetChatDbFilename() },
   777  		func() string { return filepath.Join(e.GetDataDir(), ChatDBFile) },
   778  	)
   779  }
   780  
   781  // GetPvlKitFilename gets the path to pvl kit file.
   782  // Its value is usually "" which means to use the server.
   783  func (e *Env) GetPvlKitFilename() string {
   784  	return e.GetString(
   785  		func() string { return e.cmd.GetPvlKitFilename() },
   786  		func() string { return os.Getenv("KEYBASE_PVL_KIT_FILE") },
   787  		func() string { return e.GetConfig().GetPvlKitFilename() },
   788  	)
   789  }
   790  
   791  // GetParamProofKitFilename gets the path to param proof kit file.  Its value
   792  // is usually "" which means to use the server.
   793  func (e *Env) GetParamProofKitFilename() string {
   794  	return e.GetString(
   795  		func() string { return e.cmd.GetParamProofKitFilename() },
   796  		func() string { return os.Getenv("KEYBASE_PARAM_PROOF_KIT_FILE") },
   797  		func() string { return e.GetConfig().GetParamProofKitFilename() },
   798  	)
   799  }
   800  
   801  // GetExternalURLKitFilename gets the path to param proof kit file. Its value
   802  // is usually "" which means to use the server.
   803  func (e *Env) GetExternalURLKitFilename() string {
   804  	return e.GetString(
   805  		func() string { return e.cmd.GetExternalURLKitFilename() },
   806  		func() string { return os.Getenv("KEYBASE_EXTERNAL_URL_KIT_FILE") },
   807  		func() string { return e.GetConfig().GetExternalURLKitFilename() },
   808  	)
   809  }
   810  
   811  // GetProveBypass ignores creation_disabled so that the client will let the user
   812  // try to make a proof for any known service.
   813  func (e *Env) GetProveBypass() bool {
   814  	return e.GetBool(false,
   815  		func() (bool, bool) { return e.cmd.GetProveBypass() },
   816  		func() (bool, bool) { return e.getEnvBool("KEYBASE_PROVE_BYPASS") },
   817  		func() (bool, bool) { return e.GetConfig().GetProveBypass() })
   818  }
   819  
   820  // GetDebugJourneycard enables experimental chat journey cards.
   821  func (e *Env) GetDebugJourneycard() bool {
   822  	return e.GetBool(false,
   823  		func() (bool, bool) { return e.cmd.GetDebugJourneycard() },
   824  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DEBUG_JOURNEYCARD") },
   825  		func() (bool, bool) { return e.GetConfig().GetDebugJourneycard() })
   826  }
   827  
   828  func (e *Env) GetDebug() bool {
   829  	return e.GetBool(false,
   830  		func() (bool, bool) { return e.Test.GetDebug() },
   831  		func() (bool, bool) { return e.cmd.GetDebug() },
   832  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DEBUG") },
   833  		func() (bool, bool) { return e.GetConfig().GetDebug() },
   834  	)
   835  }
   836  
   837  func (e *Env) GetDisplayRawUntrustedOutput() bool {
   838  	return e.GetBool(false,
   839  		func() (bool, bool) { return e.cmd.GetDisplayRawUntrustedOutput() },
   840  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISPLAY_RAW_UNTRUSTED_OUTPUT") },
   841  		func() (bool, bool) { return e.GetConfig().GetDisplayRawUntrustedOutput() },
   842  	)
   843  }
   844  
   845  func (e *Env) GetAutoFork() bool {
   846  	// On !Darwin, we auto-fork by default
   847  	def := (runtime.GOOS != "darwin")
   848  	return e.GetNegBool(def,
   849  		[]NegBoolFunc{
   850  			{
   851  				neg: false,
   852  				f:   func() (bool, bool) { return e.cmd.GetAutoFork() },
   853  			},
   854  			{
   855  				neg: true,
   856  				f:   func() (bool, bool) { return e.cmd.GetNoAutoFork() },
   857  			},
   858  			{
   859  				neg: false,
   860  				f:   func() (bool, bool) { return e.getEnvBool("KEYBASE_AUTO_FORK") },
   861  			},
   862  			{
   863  				neg: true,
   864  				f:   func() (bool, bool) { return e.getEnvBool("KEYBASE_NO_AUTO_FORK") },
   865  			},
   866  			{
   867  				neg: false,
   868  				f:   func() (bool, bool) { return e.GetConfig().GetAutoFork() },
   869  			},
   870  		},
   871  	)
   872  }
   873  
   874  func (e *Env) GetStandalone() bool {
   875  	return e.GetBool(false,
   876  		func() (bool, bool) { return e.cmd.GetStandalone() },
   877  		func() (bool, bool) { return e.getEnvBool("KEYBASE_STANDALONE") },
   878  		func() (bool, bool) { return e.GetConfig().GetStandalone() },
   879  	)
   880  }
   881  
   882  func (e *Env) GetLogFormat() string {
   883  	return e.GetString(
   884  		func() string { return e.cmd.GetLogFormat() },
   885  		func() string { return os.Getenv("KEYBASE_LOG_FORMAT") },
   886  		func() string { return e.GetConfig().GetLogFormat() },
   887  	)
   888  }
   889  
   890  func (e *Env) GetLabel() string {
   891  	return e.GetString(
   892  		func() string { return e.cmd.GetString("label") },
   893  		func() string { return os.Getenv("KEYBASE_LABEL") },
   894  	)
   895  }
   896  
   897  func (e *Env) GetServiceType() string {
   898  	return e.GetString(
   899  		func() string { return os.Getenv("KEYBASE_SERVICE_TYPE") },
   900  	)
   901  }
   902  
   903  func (e *Env) GetAPIDump() bool {
   904  	return e.GetBool(false,
   905  		func() (bool, bool) { return e.cmd.GetAPIDump() },
   906  		func() (bool, bool) { return e.getEnvBool("KEYBASE_API_DUMP") },
   907  	)
   908  }
   909  
   910  func (e *Env) GetAllowRoot() bool {
   911  	return e.GetBool(false,
   912  		func() (bool, bool) { return e.getEnvBool("KEYBASE_ALLOW_ROOT") },
   913  	)
   914  }
   915  
   916  func (e *Env) GetUsername() NormalizedUsername {
   917  	return e.GetConfig().GetUsername()
   918  }
   919  
   920  func (e *Env) GetSocketBindFile() (string, error) {
   921  	return e.GetString(
   922  		e.sandboxSocketFile,
   923  		e.defaultSocketFile,
   924  	), nil
   925  }
   926  
   927  func (e *Env) defaultSocketFile() string {
   928  	socketFile := e.GetString(
   929  		func() string { return e.cmd.GetSocketFile() },
   930  		func() string { return os.Getenv("KEYBASE_SOCKET_FILE") },
   931  		func() string { return e.GetConfig().GetSocketFile() },
   932  	)
   933  	if socketFile == "" {
   934  		socketFile = filepath.Join(e.GetRuntimeDir(), SocketFile)
   935  	}
   936  	return socketFile
   937  }
   938  
   939  // sandboxSocketFile is socket file location for sandbox (macOS only)
   940  // Note: this was added for KBFS finder integration, which was never
   941  // activated.
   942  func (e *Env) sandboxSocketFile() string {
   943  	sandboxCacheDir := e.HomeFinder.SandboxCacheDir()
   944  	if sandboxCacheDir == "" {
   945  		return ""
   946  	}
   947  	return filepath.Join(sandboxCacheDir, SocketFile)
   948  }
   949  
   950  func (e *Env) GetSocketDialFiles() ([]string, error) {
   951  	dialFiles := []string{}
   952  	sandboxSocketFile := e.sandboxSocketFile()
   953  	if sandboxSocketFile != "" {
   954  		dialFiles = append(dialFiles, sandboxSocketFile)
   955  	}
   956  	dialFiles = append(dialFiles, e.defaultSocketFile())
   957  	return dialFiles, nil
   958  }
   959  
   960  func (e *Env) GetGregorURI() string {
   961  	return e.GetString(
   962  		func() string { return os.Getenv("KEYBASE_PUSH_SERVER_URI") },
   963  		func() string { return e.GetConfig().GetGregorURI() },
   964  		func() string { return e.cmd.GetGregorURI() },
   965  		func() string { return GregorServerLookup[e.GetRunMode()] },
   966  	)
   967  }
   968  
   969  func (e *Env) GetGregorSaveInterval() time.Duration {
   970  	return e.GetDuration(time.Minute,
   971  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PUSH_SAVE_INTERVAL") },
   972  		func() (time.Duration, bool) { return e.GetConfig().GetGregorSaveInterval() },
   973  		func() (time.Duration, bool) { return e.cmd.GetGregorSaveInterval() },
   974  	)
   975  }
   976  
   977  func (e *Env) GetGregorDisabled() bool {
   978  	return e.GetBool(false,
   979  		func() (bool, bool) { return e.Test.GetNoGregor() },
   980  		func() (bool, bool) { return e.cmd.GetGregorDisabled() },
   981  		func() (bool, bool) { return getEnvBool("KEYBASE_PUSH_DISABLED") },
   982  		func() (bool, bool) { return e.GetConfig().GetGregorDisabled() },
   983  	)
   984  }
   985  
   986  func (e *Env) GetSecretStorePrimingDisabled() bool {
   987  	return e.GetBool(false,
   988  		func() (bool, bool) { return e.Test.GetSecretStorePrimingDisabled() },
   989  	)
   990  }
   991  
   992  func (e *Env) GetBGIdentifierDisabled() bool {
   993  	return e.GetBool(true,
   994  		func() (bool, bool) { return e.cmd.GetBGIdentifierDisabled() },
   995  		func() (bool, bool) { return getEnvBool("KEYBASE_BG_IDENTIFIER_DISABLED") },
   996  		func() (bool, bool) { return e.GetConfig().GetBGIdentifierDisabled() },
   997  	)
   998  }
   999  
  1000  func (e *Env) GetGregorPingInterval() time.Duration {
  1001  	return e.GetDuration(10*time.Second,
  1002  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PUSH_PING_INTERVAL") },
  1003  		func() (time.Duration, bool) { return e.GetConfig().GetGregorPingInterval() },
  1004  		func() (time.Duration, bool) { return e.cmd.GetGregorPingInterval() },
  1005  	)
  1006  }
  1007  
  1008  func (e *Env) GetGregorPingTimeout() time.Duration {
  1009  	return e.GetDuration(5*time.Second,
  1010  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PUSH_PING_TIMEOUT") },
  1011  		func() (time.Duration, bool) { return e.GetConfig().GetGregorPingTimeout() },
  1012  		func() (time.Duration, bool) { return e.cmd.GetGregorPingTimeout() },
  1013  	)
  1014  }
  1015  
  1016  func (e *Env) GetChatDelivererInterval() time.Duration {
  1017  	return e.GetDuration(5*time.Second,
  1018  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_CHAT_DELIVERER_INTERVAL") },
  1019  		func() (time.Duration, bool) { return e.GetConfig().GetChatDelivererInterval() },
  1020  		func() (time.Duration, bool) { return e.cmd.GetChatDelivererInterval() },
  1021  	)
  1022  }
  1023  
  1024  func (e *Env) GetAttachmentHTTPStartPort() int {
  1025  	return e.GetInt(16423,
  1026  		e.cmd.GetAttachmentHTTPStartPort,
  1027  		func() (int, bool) { return e.getEnvInt("KEYBASE_ATTACHMENT_HTTP_START") },
  1028  		e.GetConfig().GetAttachmentHTTPStartPort,
  1029  	)
  1030  }
  1031  
  1032  func (e *Env) GetAttachmentDisableMulti() bool {
  1033  	return e.GetBool(false,
  1034  		e.cmd.GetAttachmentDisableMulti,
  1035  		func() (bool, bool) { return e.getEnvBool("KEYBASE_ATTACHMENT_DISABLE_MULTI") },
  1036  		e.GetConfig().GetAttachmentDisableMulti,
  1037  	)
  1038  }
  1039  
  1040  func (e *Env) GetDisableTeamAuditor() bool {
  1041  	return e.GetBool(false,
  1042  		e.cmd.GetDisableTeamAuditor,
  1043  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_TEAM_AUDITOR") },
  1044  		e.GetConfig().GetDisableTeamAuditor,
  1045  		// If unset, use the BotLite setting
  1046  		func() (bool, bool) { return e.GetEnableBotLiteMode(), true },
  1047  	)
  1048  }
  1049  
  1050  func (e *Env) GetDisableTeamBoxAuditor() bool {
  1051  	return e.GetBool(false,
  1052  		e.cmd.GetDisableTeamBoxAuditor,
  1053  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_TEAM_BOX_AUDITOR") },
  1054  		e.GetConfig().GetDisableTeamBoxAuditor,
  1055  		// If unset, use the BotLite setting
  1056  		func() (bool, bool) { return e.GetEnableBotLiteMode(), true },
  1057  	)
  1058  }
  1059  
  1060  func (e *Env) GetDisableEKBackgroundKeygen() bool {
  1061  	return e.GetBool(false,
  1062  		e.cmd.GetDisableEKBackgroundKeygen,
  1063  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_EK_BACKGROUND_KEYGEN") },
  1064  		e.GetConfig().GetDisableEKBackgroundKeygen,
  1065  	)
  1066  }
  1067  
  1068  func (e *Env) GetDisableMerkleAuditor() bool {
  1069  	return e.GetBool(false,
  1070  		e.cmd.GetDisableMerkleAuditor,
  1071  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_MERKLE_AUDITOR") },
  1072  		e.GetConfig().GetDisableMerkleAuditor,
  1073  		// If unset, use the BotLite setting
  1074  		func() (bool, bool) { return e.GetEnableBotLiteMode(), true },
  1075  	)
  1076  }
  1077  
  1078  func (e *Env) GetDisableSearchIndexer() bool {
  1079  	return e.GetBool(false,
  1080  		e.cmd.GetDisableSearchIndexer,
  1081  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_SEARCH_INDEXER") },
  1082  		e.GetConfig().GetDisableSearchIndexer,
  1083  		// If unset, use the BotLite setting
  1084  		func() (bool, bool) { return e.GetEnableBotLiteMode(), true },
  1085  	)
  1086  }
  1087  
  1088  func (e *Env) GetDisableBgConvLoader() bool {
  1089  	return e.GetBool(false,
  1090  		e.cmd.GetDisableBgConvLoader,
  1091  		func() (bool, bool) { return e.getEnvBool("KEYBASE_DISABLE_BG_CONV_LOADER") },
  1092  		e.GetConfig().GetDisableBgConvLoader,
  1093  		// If unset, use the BotLite setting
  1094  		func() (bool, bool) { return e.GetEnableBotLiteMode(), true },
  1095  	)
  1096  }
  1097  
  1098  func (e *Env) GetEnableBotLiteMode() bool {
  1099  	return e.GetBool(false,
  1100  		e.cmd.GetEnableBotLiteMode,
  1101  		func() (bool, bool) { return e.getEnvBool("KEYBASE_ENABLE_BOT_LITE_MODE") },
  1102  		e.GetConfig().GetEnableBotLiteMode,
  1103  	)
  1104  }
  1105  
  1106  func (e *Env) GetExtraNetLogging() bool {
  1107  	return e.GetBool(false,
  1108  		e.cmd.GetExtraNetLogging,
  1109  		func() (bool, bool) { return e.getEnvBool("KEYBASE_EXTRA_NET_LOGGING") },
  1110  		e.GetConfig().GetExtraNetLogging,
  1111  	)
  1112  }
  1113  
  1114  func (e *Env) GetPidFile() (ret string, err error) {
  1115  	ret = e.GetString(
  1116  		func() string { return e.cmd.GetPidFile() },
  1117  		func() string { return os.Getenv("KEYBASE_PID_FILE") },
  1118  		func() string { return e.GetConfig().GetPidFile() },
  1119  	)
  1120  	if len(ret) == 0 {
  1121  		ret = filepath.Join(e.GetInfoDir(), PIDFile)
  1122  	}
  1123  	return
  1124  }
  1125  
  1126  func (e *Env) GetEmail() string {
  1127  	return e.GetString(
  1128  		func() string { return os.Getenv("KEYBASE_EMAIL") },
  1129  	)
  1130  }
  1131  
  1132  func (e *Env) GetStayLoggedOut() bool {
  1133  	return e.GetBool(false,
  1134  		func() (bool, bool) { return e.GetConfig().GetStayLoggedOut() },
  1135  	)
  1136  }
  1137  
  1138  // Upgrade sigchains to contain per-user-keys.
  1139  func (e *Env) GetUpgradePerUserKey() bool {
  1140  	return !e.Test.DisableUpgradePerUserKey
  1141  }
  1142  
  1143  // If true, do not logout after user.key_change notification handler
  1144  // decides that current device has been revoked.
  1145  func (e *Env) GetSkipLogoutIfRevokedCheck() bool {
  1146  	return e.Test.SkipLogoutIfRevokedCheck
  1147  }
  1148  
  1149  // Get the ProxyType based off of the configured proxy and tor settings
  1150  func (e *Env) GetProxyType() ProxyType {
  1151  	if e.GetTorMode() != TorNone {
  1152  		// Tor mode is enabled. Tor mode is implemented via a socks proxy
  1153  		return Socks
  1154  	}
  1155  	var proxyTypeStr = e.GetString(
  1156  		func() string { return e.cmd.GetProxyType() },
  1157  		func() string { return os.Getenv("PROXY_TYPE") },
  1158  		func() string { return e.GetConfig().GetProxyType() },
  1159  	)
  1160  	return ProxyTypeStrToEnumFunc(proxyTypeStr)
  1161  }
  1162  
  1163  func ProxyTypeStrToEnumFunc(proxyTypeStr string) ProxyType {
  1164  	proxyType, ok := ProxyTypeStrToEnum[strings.ToLower(proxyTypeStr)]
  1165  	if ok {
  1166  		return proxyType
  1167  	}
  1168  	// If they give us a bogus proxy type we just don't enable a proxy
  1169  	return NoProxy
  1170  }
  1171  
  1172  // Get the address (optionally including a port) of the currently configured proxy. Returns an empty string if no proxy
  1173  // is configured.
  1174  func (e *Env) GetProxy() string {
  1175  	return e.GetString(
  1176  		func() string {
  1177  			// Only return the tor proxy address if tor mode is enabled to ensure we fall through to the other options
  1178  			if e.GetTorMode() != TorNone {
  1179  				return e.GetTorProxy()
  1180  			}
  1181  			return ""
  1182  		},
  1183  		// Prioritze tor mode over configured proxies
  1184  		func() string { return e.cmd.GetProxy() },
  1185  		func() string { return e.GetConfig().GetProxy() },
  1186  		func() string { return os.Getenv("PROXY") },
  1187  		// Prioritize the keybase specific methods of configuring a proxy above the standard unix env variables
  1188  		func() string { return os.Getenv("HTTPS_PROXY") },
  1189  		func() string { return os.Getenv("HTTP_PROXY") },
  1190  	)
  1191  }
  1192  
  1193  func (e *Env) IsCertPinningEnabled() bool {
  1194  	// SSL Pinning is enabled if none of the config options say it is disabled
  1195  	if !e.cmd.IsCertPinningEnabled() {
  1196  		return false
  1197  	}
  1198  	res, isSet := e.getEnvBool("DISABLE_SSL_PINNING")
  1199  	if isSet && res {
  1200  		return false
  1201  	}
  1202  	if !e.GetConfig().IsCertPinningEnabled() {
  1203  		return false
  1204  	}
  1205  	return true
  1206  }
  1207  
  1208  func (e *Env) GetGpgHome() string {
  1209  	return e.GetString(
  1210  		func() string { return e.Test.GPGHome },
  1211  		func() string { return e.cmd.GetGpgHome() },
  1212  		func() string { return os.Getenv("GNUPGHOME") },
  1213  		func() string { return e.GetConfig().GetGpgHome() },
  1214  		func() string { return filepath.Join(e.GetHome(), ".gnupg") },
  1215  	)
  1216  }
  1217  
  1218  func (e *Env) GetPinentry() string {
  1219  	return e.GetString(
  1220  		func() string { return e.cmd.GetPinentry() },
  1221  		func() string { return os.Getenv("KEYBASE_PINENTRY") },
  1222  		func() string { return e.GetConfig().GetPinentry() },
  1223  	)
  1224  }
  1225  
  1226  func (e *Env) GetNoPinentry() bool {
  1227  
  1228  	isno := func(s string) (bool, bool) {
  1229  		s = strings.ToLower(s)
  1230  		if s == "0" || s == "no" || s == "n" || s == "none" {
  1231  			return true, true
  1232  		}
  1233  		return false, false
  1234  	}
  1235  
  1236  	return e.GetBool(false,
  1237  		func() (bool, bool) { return isno(e.cmd.GetPinentry()) },
  1238  		func() (bool, bool) { return isno(os.Getenv("KEYBASE_PINENTRY")) },
  1239  		func() (bool, bool) { return e.GetConfig().GetNoPinentry() },
  1240  	)
  1241  }
  1242  
  1243  func (e *Env) GetBundledCA(host string) string {
  1244  	return e.GetString(
  1245  		func() string { return e.GetConfig().GetBundledCA(host) },
  1246  		func() string {
  1247  			ret, ok := GetBundledCAsFromHost(host)
  1248  			if !ok {
  1249  				return ""
  1250  			}
  1251  			return string(ret)
  1252  		},
  1253  	)
  1254  }
  1255  
  1256  func (e *Env) GetUserCacheMaxAge() time.Duration {
  1257  	return e.GetDuration(UserCacheMaxAge,
  1258  		func() (time.Duration, bool) { return e.cmd.GetUserCacheMaxAge() },
  1259  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_USER_CACHE_MAX_AGE") },
  1260  		func() (time.Duration, bool) { return e.GetConfig().GetUserCacheMaxAge() },
  1261  	)
  1262  }
  1263  
  1264  func (e *Env) GetAPITimeout() time.Duration {
  1265  	return e.GetDuration(HTTPDefaultTimeout,
  1266  		func() (time.Duration, bool) { return e.cmd.GetAPITimeout() },
  1267  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_API_TIMEOUT") },
  1268  		func() (time.Duration, bool) { return e.GetConfig().GetAPITimeout() },
  1269  	)
  1270  }
  1271  
  1272  func (e *Env) GetScraperTimeout() time.Duration {
  1273  	return e.GetDuration(HTTPDefaultScraperTimeout,
  1274  		func() (time.Duration, bool) { return e.cmd.GetScraperTimeout() },
  1275  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_SCRAPER_TIMEOUT") },
  1276  		func() (time.Duration, bool) { return e.GetConfig().GetScraperTimeout() },
  1277  	)
  1278  }
  1279  
  1280  func (e *Env) GetLocalTrackMaxAge() time.Duration {
  1281  	return e.GetDuration(LocalTrackMaxAge,
  1282  		func() (time.Duration, bool) { return e.cmd.GetLocalTrackMaxAge() },
  1283  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_LOCAL_TRACK_MAX_AGE") },
  1284  		func() (time.Duration, bool) { return e.GetConfig().GetLocalTrackMaxAge() },
  1285  	)
  1286  }
  1287  func (e *Env) GetProofCacheSize() int {
  1288  	return e.GetInt(ProofCacheSize,
  1289  		e.cmd.GetProofCacheSize,
  1290  		func() (int, bool) { return e.getEnvInt("KEYBASE_PROOF_CACHE_SIZE") },
  1291  		e.GetConfig().GetProofCacheSize,
  1292  	)
  1293  }
  1294  
  1295  func (e *Env) GetProofCacheLongDur() time.Duration {
  1296  	return e.GetDuration(ProofCacheLongDur,
  1297  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PROOF_CACHE_LONG_DUR") },
  1298  		e.GetConfig().GetProofCacheLongDur,
  1299  	)
  1300  }
  1301  
  1302  func (e *Env) GetProofCacheMediumDur() time.Duration {
  1303  	return e.GetDuration(ProofCacheMediumDur,
  1304  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PROOF_CACHE_MEDIUM_DUR") },
  1305  		e.GetConfig().GetProofCacheMediumDur,
  1306  	)
  1307  }
  1308  
  1309  func (e *Env) GetProofCacheShortDur() time.Duration {
  1310  	return e.GetDuration(ProofCacheShortDur,
  1311  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_PROOF_CACHE_SHORT_DUR") },
  1312  		e.GetConfig().GetProofCacheShortDur,
  1313  	)
  1314  }
  1315  
  1316  func (e *Env) GetLinkCacheSize() int {
  1317  	return e.GetInt(LinkCacheSize,
  1318  		e.cmd.GetLinkCacheSize,
  1319  		func() (int, bool) { return e.getEnvInt("KEYBASE_LINK_CACHE_SIZE") },
  1320  		e.GetConfig().GetLinkCacheSize,
  1321  	)
  1322  }
  1323  
  1324  func (e *Env) GetUPAKCacheSize() int {
  1325  	return e.GetInt(UPAKCacheSize,
  1326  		e.cmd.GetUPAKCacheSize,
  1327  		func() (int, bool) { return e.getEnvInt("KEYBASE_UPAK_CACHE_SIZE") },
  1328  		e.GetConfig().GetUPAKCacheSize,
  1329  	)
  1330  }
  1331  
  1332  func (e *Env) GetUIDMapFullNameCacheSize() int {
  1333  	return e.GetInt(UIDMapFullNameCacheSize,
  1334  		e.cmd.GetUIDMapFullNameCacheSize,
  1335  		func() (int, bool) { return e.getEnvInt("KEYBASE_UID_MAP_FULL_NAME_CACHE_SIZE") },
  1336  		e.GetConfig().GetUIDMapFullNameCacheSize,
  1337  	)
  1338  }
  1339  
  1340  func (e *Env) GetLevelDBNumFiles() int {
  1341  	return e.GetInt(LevelDBNumFiles,
  1342  		e.cmd.GetLevelDBNumFiles,
  1343  		func() (int, bool) { return e.getEnvInt("KEYBASE_LEVELDB_NUM_FILES") },
  1344  		e.GetConfig().GetLevelDBNumFiles,
  1345  	)
  1346  }
  1347  
  1348  func (e *Env) GetLevelDBWriteBufferMB() int {
  1349  	return e.GetInt(LevelDBWriteBufferMB,
  1350  		e.cmd.GetLevelDBWriteBufferMB,
  1351  		func() (int, bool) { return e.getEnvInt("KEYBASE_LEVELDB_WRITE_BUFFER_MB") },
  1352  		e.GetConfig().GetLevelDBWriteBufferMB,
  1353  	)
  1354  }
  1355  
  1356  func (e *Env) GetLinkCacheCleanDur() time.Duration {
  1357  	return e.GetDuration(LinkCacheCleanDur,
  1358  		func() (time.Duration, bool) { return e.getEnvDuration("KEYBASE_LINK_CACHE_CLEAN_DUR") },
  1359  		e.GetConfig().GetLinkCacheCleanDur,
  1360  	)
  1361  }
  1362  
  1363  func (e *Env) GetPayloadCacheSize() int {
  1364  	return e.GetInt(PayloadCacheSize,
  1365  		e.cmd.GetPayloadCacheSize,
  1366  		func() (int, bool) { return e.getEnvInt("KEYBASE_PAYLOAD_CACHE_SIZE") },
  1367  		e.GetConfig().GetPayloadCacheSize,
  1368  	)
  1369  }
  1370  
  1371  func (e *Env) GetEmailOrUsername() string {
  1372  	un := e.GetUsername().String()
  1373  	if len(un) > 0 {
  1374  		return un
  1375  	}
  1376  	em := e.GetEmail()
  1377  	return em
  1378  }
  1379  
  1380  func (e *Env) GetRunMode() RunMode {
  1381  	// If testing production run mode, then use it:
  1382  	if e.Test.UseProductionRunMode {
  1383  		return ProductionRunMode
  1384  	}
  1385  
  1386  	var ret RunMode
  1387  
  1388  	pick := func(m RunMode, err error) {
  1389  		if ret == NoRunMode && err == nil {
  1390  			ret = m
  1391  		}
  1392  	}
  1393  
  1394  	pick(e.cmd.GetRunMode())
  1395  	pick(StringToRunMode(os.Getenv("KEYBASE_RUN_MODE")))
  1396  	pick(e.GetConfig().GetRunMode())
  1397  	pick(DefaultRunMode, nil)
  1398  
  1399  	// If we aren't running in devel or staging and we're testing. Let's run in devel.
  1400  	if e.Test.Devel && ret != DevelRunMode && ret != StagingRunMode {
  1401  		return DevelRunMode
  1402  	}
  1403  
  1404  	return ret
  1405  }
  1406  
  1407  func (e *Env) GetAppType() AppType {
  1408  	switch {
  1409  	case e.cmd.GetAppType() != NoAppType:
  1410  		return e.cmd.GetAppType()
  1411  	case StringToAppType(os.Getenv("KEYBASE_APP_TYPE")) != NoAppType:
  1412  		return StringToAppType(os.Getenv("KEYBASE_APP_TYPE"))
  1413  	case e.GetConfig().GetAppType() != NoAppType:
  1414  		return e.GetConfig().GetAppType()
  1415  	default:
  1416  		return NoAppType
  1417  	}
  1418  }
  1419  
  1420  func (e *Env) IsMobileExtension() bool {
  1421  	return e.GetBool(false,
  1422  		func() (bool, bool) { return e.cmd.IsMobileExtension() },
  1423  		func() (bool, bool) { return e.getEnvBool("KEYBASE_MOBILE_EXTENSION") },
  1424  		func() (bool, bool) { return e.GetConfig().IsMobileExtension() },
  1425  	)
  1426  }
  1427  
  1428  func (e *Env) GetSlowGregorConn() bool {
  1429  	return e.GetBool(false,
  1430  		func() (bool, bool) { return e.cmd.GetSlowGregorConn() },
  1431  		func() (bool, bool) { return e.getEnvBool("KEYBASE_SLOW_GREGOR_CONN") },
  1432  		func() (bool, bool) { return e.GetConfig().GetSlowGregorConn() },
  1433  	)
  1434  }
  1435  
  1436  func (e *Env) GetReadDeletedSigChain() bool {
  1437  	return e.GetBool(false,
  1438  		func() (bool, bool) { return e.cmd.GetReadDeletedSigChain() },
  1439  		func() (bool, bool) { return e.getEnvBool("KEYBASE_READ_DELETED_SIGCHAIN") },
  1440  		func() (bool, bool) { return e.GetConfig().GetReadDeletedSigChain() },
  1441  	)
  1442  }
  1443  
  1444  func (e *Env) GetFeatureFlags() FeatureFlags {
  1445  	var ret FeatureFlags
  1446  	pick := func(f FeatureFlags, err error) {
  1447  		if ret.Empty() && err == nil {
  1448  			ret = f
  1449  		}
  1450  	}
  1451  	if e.Test.EnvironmentFeatureFlags != nil {
  1452  		pick(e.Test.EnvironmentFeatureFlags, nil)
  1453  	}
  1454  	pick(e.cmd.GetFeatureFlags())
  1455  	pick(StringToFeatureFlags(os.Getenv("KEYBASE_FEATURES")), nil)
  1456  	pick(e.GetConfig().GetFeatureFlags())
  1457  	return ret
  1458  }
  1459  
  1460  func (e *Env) GetUID() keybase1.UID { return e.GetConfig().GetUID() }
  1461  
  1462  func (e *Env) GetStringList(list ...(func() []string)) []string {
  1463  	for _, f := range list {
  1464  		if res := f(); res != nil {
  1465  			return res
  1466  		}
  1467  	}
  1468  	return []string{}
  1469  }
  1470  
  1471  func (e *Env) GetMerkleKIDs() []keybase1.KID {
  1472  	slist := e.GetStringList(
  1473  		func() []string { return e.cmd.GetMerkleKIDs() },
  1474  		func() []string { return e.getEnvPath("KEYBASE_MERKLE_KIDS") },
  1475  		func() []string { return e.GetConfig().GetMerkleKIDs() },
  1476  		func() []string {
  1477  			ret := MerkleProdKIDs
  1478  			if e.GetRunMode() == DevelRunMode || e.GetRunMode() == StagingRunMode {
  1479  				ret = append(ret, MerkleTestKIDs...)
  1480  				ret = append(ret, MerkleStagingKIDs...)
  1481  			}
  1482  			return ret
  1483  		},
  1484  	)
  1485  
  1486  	if slist == nil {
  1487  		return nil
  1488  	}
  1489  	var ret []keybase1.KID
  1490  	for _, s := range slist {
  1491  		ret = append(ret, keybase1.KIDFromString(s))
  1492  	}
  1493  
  1494  	return ret
  1495  }
  1496  
  1497  func (e *Env) GetCodeSigningKIDs() []keybase1.KID {
  1498  	slist := e.GetStringList(
  1499  		func() []string { return e.cmd.GetCodeSigningKIDs() },
  1500  		func() []string { return e.getEnvPath("KEYBASE_CODE_SIGNING_KIDS") },
  1501  		func() []string { return e.GetConfig().GetCodeSigningKIDs() },
  1502  		func() []string {
  1503  			ret := CodeSigningProdKIDs
  1504  			if e.GetRunMode() == DevelRunMode || e.GetRunMode() == StagingRunMode {
  1505  				ret = append(ret, CodeSigningTestKIDs...)
  1506  				ret = append(ret, CodeSigningStagingKIDs...)
  1507  			}
  1508  			return ret
  1509  		},
  1510  	)
  1511  
  1512  	if slist == nil {
  1513  		return nil
  1514  	}
  1515  	var ret []keybase1.KID
  1516  	for _, s := range slist {
  1517  		ret = append(ret, keybase1.KIDFromString(s))
  1518  	}
  1519  
  1520  	return ret
  1521  }
  1522  
  1523  func (e *Env) GetGpg() string {
  1524  	return e.GetString(
  1525  		func() string { return e.Test.GPG },
  1526  		func() string { return e.cmd.GetGpg() },
  1527  		func() string { return os.Getenv("GPG") },
  1528  		func() string { return e.GetConfig().GetGpg() },
  1529  	)
  1530  }
  1531  
  1532  func (e *Env) GetGpgOptions() []string {
  1533  	return e.GetStringList(
  1534  		func() []string { return e.Test.GPGOptions },
  1535  		func() []string { return e.cmd.GetGpgOptions() },
  1536  		func() []string { return e.GetConfig().GetGpgOptions() },
  1537  	)
  1538  }
  1539  
  1540  func (e *Env) GetSecretKeyringTemplate() string {
  1541  	return e.GetString(
  1542  		func() string { return e.cmd.GetSecretKeyringTemplate() },
  1543  		func() string { return os.Getenv("KEYBASE_SECRET_KEYRING_TEMPLATE") },
  1544  		func() string { return e.GetConfig().GetSecretKeyringTemplate() },
  1545  		func() string { return filepath.Join(e.GetConfigDir(), SecretKeyringTemplate) },
  1546  	)
  1547  }
  1548  
  1549  func (e *Env) GetLocalRPCDebug() string {
  1550  	return e.GetString(
  1551  		func() string { return e.cmd.GetLocalRPCDebug() },
  1552  		func() string { return os.Getenv("KEYBASE_LOCAL_RPC_DEBUG") },
  1553  		func() string { return e.GetConfig().GetLocalRPCDebug() },
  1554  	)
  1555  }
  1556  
  1557  func (e *Env) GetDoLogForward() bool {
  1558  	return e.GetLocalRPCDebug() == ""
  1559  }
  1560  
  1561  func (e *Env) GetTimers() string {
  1562  	return e.GetString(
  1563  		func() string { return e.cmd.GetTimers() },
  1564  		func() string { return os.Getenv("KEYBASE_TIMERS") },
  1565  		func() string { return e.GetConfig().GetTimers() },
  1566  	)
  1567  }
  1568  
  1569  func (e *Env) GetConvSourceType() string {
  1570  	return e.GetString(
  1571  		func() string { return os.Getenv("KEYBASE_CONV_SOURCE_TYPE") },
  1572  		func() string { return "hybrid" },
  1573  	)
  1574  }
  1575  
  1576  func (e *Env) GetInboxSourceType() string {
  1577  	return e.GetString(
  1578  		func() string { return os.Getenv("KEYBASE_INBOX_SOURCE_TYPE") },
  1579  		func() string { return "hybrid" },
  1580  	)
  1581  }
  1582  
  1583  func (e *Env) GetChatInboxSourceLocalizeThreads() int {
  1584  	return e.GetInt(
  1585  		10,
  1586  		e.cmd.GetChatInboxSourceLocalizeThreads,
  1587  		func() (int, bool) { return e.getEnvInt("KEYBASE_INBOX_SOURCE_LOCALIZE_THREADS") },
  1588  		e.GetConfig().GetChatInboxSourceLocalizeThreads,
  1589  	)
  1590  }
  1591  
  1592  // GetChatMemberType returns the default member type for new conversations.
  1593  func (e *Env) GetChatMemberType() string {
  1594  	return e.GetString(
  1595  		func() string { return os.Getenv("KEYBASE_CHAT_MEMBER_TYPE") },
  1596  		func() string { return "impteam" },
  1597  	)
  1598  }
  1599  
  1600  func (e *Env) GetAvatarSource() string {
  1601  	return e.GetString(
  1602  		func() string { return os.Getenv("KEYBASE_AVATAR_SOURCE") },
  1603  		func() string { return "full" },
  1604  	)
  1605  }
  1606  
  1607  func (e *Env) GetDeviceID() keybase1.DeviceID {
  1608  	return e.GetConfig().GetDeviceID()
  1609  }
  1610  
  1611  func (e *Env) GetDeviceIDForUsername(u NormalizedUsername) keybase1.DeviceID {
  1612  	return e.GetConfig().GetDeviceIDForUsername(u)
  1613  }
  1614  
  1615  func (e *Env) GetDeviceIDForUID(u keybase1.UID) keybase1.DeviceID {
  1616  	return e.GetConfig().GetDeviceIDForUID(u)
  1617  }
  1618  
  1619  func (e *Env) GetUsernameForUID(u keybase1.UID) NormalizedUsername {
  1620  	return e.GetConfig().GetUsernameForUID(u)
  1621  }
  1622  
  1623  func (e *Env) GetInstallID() (ret InstallID) {
  1624  	if rdr := e.GetUpdaterConfig(); rdr != nil {
  1625  		ret = rdr.GetInstallID()
  1626  	}
  1627  	return ret
  1628  }
  1629  
  1630  func (e *Env) GetEffectiveLogFile() (filename string, ok bool) {
  1631  	logFile := e.GetLogFile()
  1632  	if logFile != "" {
  1633  		return logFile, true
  1634  	}
  1635  
  1636  	filePrefix := e.GetLogPrefix()
  1637  	if filePrefix != "" {
  1638  		filePrefix += time.Now().Format("20060102T150405.999999999Z0700")
  1639  		logFile = filePrefix + ".log"
  1640  		return logFile, true
  1641  	}
  1642  
  1643  	return e.GetDefaultLogFile(), e.GetUseDefaultLogFile()
  1644  }
  1645  
  1646  func (e *Env) GetLogFile() string {
  1647  	return e.GetString(
  1648  		func() string { return e.cmd.GetLogFile() },
  1649  		func() string { return os.Getenv("KEYBASE_LOG_FILE") },
  1650  	)
  1651  }
  1652  
  1653  func (e *Env) GetEKLogFile() string {
  1654  	return e.GetString(
  1655  		func() string { return e.cmd.GetEKLogFile() },
  1656  		func() string { return os.Getenv("KEYBASE_EK_LOG_FILE") },
  1657  		func() string { return filepath.Join(e.GetLogDir(), EKLogFileName) },
  1658  	)
  1659  }
  1660  
  1661  func (e *Env) GetPerfLogFile() string {
  1662  	return e.GetString(
  1663  		func() string { return e.cmd.GetPerfLogFile() },
  1664  		func() string { return os.Getenv("KEYBASE_PERF_LOG_FILE") },
  1665  		func() string { return filepath.Join(e.GetLogDir(), PerfLogFileName) },
  1666  	)
  1667  }
  1668  
  1669  func (e *Env) GetGUILogFile() string {
  1670  	return e.GetString(
  1671  		func() string { return e.cmd.GetGUILogFile() },
  1672  		func() string { return os.Getenv("KEYBASE_GUI_LOG_FILE") },
  1673  		func() string { return filepath.Join(e.GetLogDir(), GUILogFileName) },
  1674  	)
  1675  }
  1676  
  1677  func (e *Env) GetUseDefaultLogFile() bool {
  1678  	return e.GetBool(false,
  1679  		e.cmd.GetUseDefaultLogFile,
  1680  		func() (bool, bool) { return e.getEnvBool("KEYBASE_USE_DEFAULT_LOG_FILE") },
  1681  	)
  1682  }
  1683  
  1684  func (e *Env) GetLogPrefix() string {
  1685  	return e.cmd.GetLogPrefix()
  1686  }
  1687  
  1688  func (e *Env) GetDefaultLogFile() string {
  1689  	return filepath.Join(e.GetLogDir(), ServiceLogFileName)
  1690  }
  1691  
  1692  func (e *Env) GetTorMode() TorMode {
  1693  	var ret TorMode
  1694  
  1695  	pick := func(m TorMode, err error) {
  1696  		if ret == TorNone && err == nil {
  1697  			ret = m
  1698  		}
  1699  	}
  1700  
  1701  	pick(e.cmd.GetTorMode())
  1702  	pick(StringToTorMode(os.Getenv("KEYBASE_TOR_MODE")))
  1703  	pick(e.GetConfig().GetTorMode())
  1704  
  1705  	return ret
  1706  }
  1707  
  1708  func (e *Env) GetTorHiddenAddress() string {
  1709  	return e.GetString(
  1710  		func() string { return e.cmd.GetTorHiddenAddress() },
  1711  		func() string { return os.Getenv("KEYBASE_TOR_HIDDEN_ADDRESS") },
  1712  		func() string { return e.GetConfig().GetTorHiddenAddress() },
  1713  		func() string { return TorServerURI },
  1714  	)
  1715  }
  1716  
  1717  func (e *Env) GetTorProxy() string {
  1718  	return e.GetString(
  1719  		func() string { return e.cmd.GetTorProxy() },
  1720  		func() string { return os.Getenv("KEYBASE_TOR_PROXY") },
  1721  		func() string { return e.GetConfig().GetTorProxy() },
  1722  		func() string { return TorProxy },
  1723  	)
  1724  }
  1725  
  1726  func (e *Env) GetStoredSecretAccessGroup() string {
  1727  	var override = e.GetBool(
  1728  		false,
  1729  		func() (bool, bool) { return e.GetConfig().GetSecurityAccessGroupOverride() },
  1730  	)
  1731  
  1732  	if override {
  1733  		return ""
  1734  	}
  1735  	return "99229SGT5K.group.keybase"
  1736  }
  1737  
  1738  func (e *Env) GetStoredSecretServiceBaseName() string {
  1739  	var serviceName string
  1740  	switch e.GetRunMode() {
  1741  	case DevelRunMode:
  1742  		serviceName = "keybase-devel"
  1743  	case StagingRunMode:
  1744  		serviceName = "keybase-staging"
  1745  	case ProductionRunMode:
  1746  		serviceName = "keybase"
  1747  	default:
  1748  		panic("Invalid run mode")
  1749  	}
  1750  	if e.Test.Devel {
  1751  		// Append DevelName so that tests won't clobber each
  1752  		// other's keychain entries on shutdown.
  1753  		serviceName += "-test"
  1754  	}
  1755  	return serviceName
  1756  }
  1757  
  1758  func (e *Env) GetStoredSecretServiceName() string {
  1759  	serviceName := e.GetStoredSecretServiceBaseName()
  1760  	if e.Test.Devel {
  1761  		// Append DevelName so that tests won't clobber each
  1762  		// other's keychain entries on shutdown.
  1763  		serviceName += fmt.Sprintf("(%s)", e.Test.DevelName)
  1764  	}
  1765  	return serviceName
  1766  }
  1767  
  1768  type AppConfig struct {
  1769  	NullConfiguration
  1770  	DownloadsDir                   string
  1771  	HomeDir                        string
  1772  	MobileSharedHomeDir            string
  1773  	LogFile                        string
  1774  	EKLogFile                      string
  1775  	PerfLogFile                    string
  1776  	GUILogFile                     string
  1777  	UseDefaultLogFile              bool
  1778  	RunMode                        RunMode
  1779  	Debug                          bool
  1780  	LocalRPCDebug                  string
  1781  	ServerURI                      string
  1782  	VDebugSetting                  string
  1783  	SecurityAccessGroupOverride    bool
  1784  	ChatInboxSourceLocalizeThreads int
  1785  	MobileExtension                bool
  1786  	AttachmentHTTPStartPort        int
  1787  	AttachmentDisableMulti         bool
  1788  	LinkCacheSize                  int
  1789  	UPAKCacheSize                  int
  1790  	PayloadCacheSize               int
  1791  	ProofCacheSize                 int
  1792  	DisableTeamAuditor             bool
  1793  	DisableMerkleAuditor           bool
  1794  	DisableTeamBoxAuditor          bool
  1795  	DisableEKBackgroundKeygen      bool
  1796  	LevelDBWriteBufferMB           int
  1797  	LevelDBNumFiles                int
  1798  }
  1799  
  1800  var _ CommandLine = AppConfig{}
  1801  
  1802  func (c AppConfig) GetLogFile() string {
  1803  	return c.LogFile
  1804  }
  1805  
  1806  func (c AppConfig) GetEKLogFile() string {
  1807  	return c.EKLogFile
  1808  }
  1809  
  1810  func (c AppConfig) GetPerfLogFile() string {
  1811  	return c.PerfLogFile
  1812  }
  1813  
  1814  func (c AppConfig) GetGUILogFile() string {
  1815  	return c.GUILogFile
  1816  }
  1817  
  1818  func (c AppConfig) GetUseDefaultLogFile() (bool, bool) {
  1819  	return c.UseDefaultLogFile, true
  1820  }
  1821  
  1822  func (c AppConfig) GetDebug() (bool, bool) {
  1823  	return c.Debug, c.Debug
  1824  }
  1825  
  1826  func (c AppConfig) GetLocalRPCDebug() string {
  1827  	return c.LocalRPCDebug
  1828  }
  1829  
  1830  func (c AppConfig) GetRunMode() (RunMode, error) {
  1831  	return c.RunMode, nil
  1832  }
  1833  
  1834  func (c AppConfig) GetDownloadsDir() string {
  1835  	return c.DownloadsDir
  1836  }
  1837  
  1838  func (c AppConfig) GetHome() string {
  1839  	return c.HomeDir
  1840  }
  1841  
  1842  func (c AppConfig) GetMobileSharedHome() string {
  1843  	return c.MobileSharedHomeDir
  1844  }
  1845  
  1846  func (c AppConfig) GetServerURI() (string, error) {
  1847  	return c.ServerURI, nil
  1848  }
  1849  
  1850  func (c AppConfig) GetSecurityAccessGroupOverride() (bool, bool) {
  1851  	return c.SecurityAccessGroupOverride, c.SecurityAccessGroupOverride
  1852  }
  1853  
  1854  func (c AppConfig) GetAppType() AppType {
  1855  	return MobileAppType
  1856  }
  1857  
  1858  func (c AppConfig) IsMobileExtension() (bool, bool) {
  1859  	return c.MobileExtension, true
  1860  }
  1861  
  1862  func (c AppConfig) GetSlowGregorConn() (bool, bool) {
  1863  	return false, false
  1864  }
  1865  
  1866  func (c AppConfig) GetReadDeletedSigChain() (bool, bool) {
  1867  	return false, false
  1868  }
  1869  
  1870  func (c AppConfig) GetVDebugSetting() string {
  1871  	return c.VDebugSetting
  1872  }
  1873  
  1874  func (c AppConfig) GetChatInboxSourceLocalizeThreads() (int, bool) {
  1875  	return c.ChatInboxSourceLocalizeThreads, true
  1876  }
  1877  
  1878  func (c AppConfig) GetLevelDBWriteBufferMB() (int, bool) {
  1879  	if c.LevelDBWriteBufferMB > 0 {
  1880  		return c.LevelDBWriteBufferMB, true
  1881  	}
  1882  	return LevelDBWriteBufferMBMobile, true
  1883  }
  1884  
  1885  func (c AppConfig) GetLevelDBNumFiles() (int, bool) {
  1886  	if c.LevelDBNumFiles > 0 {
  1887  		return c.LevelDBNumFiles, true
  1888  	}
  1889  	return LevelDBNumFiles, true
  1890  }
  1891  
  1892  func (c AppConfig) GetAttachmentHTTPStartPort() (int, bool) {
  1893  	if c.AttachmentHTTPStartPort != 0 {
  1894  		return c.AttachmentHTTPStartPort, true
  1895  	}
  1896  	return 0, false
  1897  }
  1898  
  1899  func (c AppConfig) GetLinkCacheSize() (int, bool) {
  1900  	if c.LinkCacheSize != 0 {
  1901  		return c.LinkCacheSize, true
  1902  	}
  1903  	return 0, false
  1904  }
  1905  
  1906  func (c AppConfig) GetUPAKCacheSize() (int, bool) {
  1907  	if c.UPAKCacheSize != 0 {
  1908  		return c.UPAKCacheSize, true
  1909  	}
  1910  	return 0, false
  1911  }
  1912  
  1913  func (c AppConfig) GetPayloadCacheSize() (int, bool) {
  1914  	if c.PayloadCacheSize != 0 {
  1915  		return c.PayloadCacheSize, true
  1916  	}
  1917  	return 0, false
  1918  }
  1919  
  1920  func (c AppConfig) GetProofCacheSize() (int, bool) {
  1921  	if c.ProofCacheSize != 0 {
  1922  		return c.ProofCacheSize, true
  1923  	}
  1924  	return 0, false
  1925  }
  1926  
  1927  func (c AppConfig) GetDisableTeamAuditor() (bool, bool) {
  1928  	return c.DisableTeamAuditor, true
  1929  }
  1930  
  1931  func (c AppConfig) GetDisableMerkleAuditor() (bool, bool) {
  1932  	return c.DisableMerkleAuditor, true
  1933  }
  1934  
  1935  func (c AppConfig) GetDisableTeamBoxAuditor() (bool, bool) {
  1936  	return c.DisableTeamBoxAuditor, true
  1937  }
  1938  
  1939  func (c AppConfig) GetDisableEKBackgroundKeygen() (bool, bool) {
  1940  	return c.DisableEKBackgroundKeygen, true
  1941  }
  1942  
  1943  func (c AppConfig) GetAttachmentDisableMulti() (bool, bool) {
  1944  	return c.AttachmentDisableMulti, true
  1945  }
  1946  
  1947  func (e *Env) GetUpdatePreferenceAuto() (bool, bool) {
  1948  	return e.GetConfig().GetUpdatePreferenceAuto()
  1949  }
  1950  
  1951  func (e *Env) GetUpdatePreferenceSkip() string {
  1952  	return e.GetConfig().GetUpdatePreferenceSkip()
  1953  }
  1954  
  1955  func (e *Env) GetUpdatePreferenceSnoozeUntil() keybase1.Time {
  1956  	return e.GetConfig().GetUpdatePreferenceSnoozeUntil()
  1957  }
  1958  
  1959  func (e *Env) GetUpdateLastChecked() keybase1.Time {
  1960  	return e.GetConfig().GetUpdateLastChecked()
  1961  }
  1962  
  1963  func (e *Env) SetUpdatePreferenceAuto(b bool) error {
  1964  	return e.GetConfigWriter().SetUpdatePreferenceAuto(b)
  1965  }
  1966  
  1967  func (e *Env) SetUpdatePreferenceSkip(v string) error {
  1968  	return e.GetConfigWriter().SetUpdatePreferenceSkip(v)
  1969  }
  1970  
  1971  func (e *Env) SetUpdatePreferenceSnoozeUntil(t keybase1.Time) error {
  1972  	return e.GetConfigWriter().SetUpdatePreferenceSnoozeUntil(t)
  1973  }
  1974  
  1975  func (e *Env) SetUpdateLastChecked(t keybase1.Time) error {
  1976  	return e.GetConfigWriter().SetUpdateLastChecked(t)
  1977  }
  1978  
  1979  func (e *Env) GetUpdateURL() string {
  1980  	return e.GetConfig().GetUpdateURL()
  1981  }
  1982  
  1983  func (e *Env) GetUpdateDisabled() (bool, bool) {
  1984  	return e.GetConfig().GetUpdateDisabled()
  1985  }
  1986  
  1987  func (e *Env) GetVDebugSetting() string {
  1988  	return e.GetString(
  1989  		func() string { return e.cmd.GetVDebugSetting() },
  1990  		func() string { return os.Getenv("KEYBASE_VDEBUG") },
  1991  		func() string { return e.GetConfig().GetVDebugSetting() },
  1992  		func() string { return "" },
  1993  	)
  1994  }
  1995  
  1996  func (e *Env) GetRunModeAsString() string {
  1997  	return string(e.GetRunMode())
  1998  }
  1999  
  2000  // GetServiceInfoPath returns path to info file written by the Keybase service after startup
  2001  func (e *Env) GetServiceInfoPath() string {
  2002  	return filepath.Join(e.GetRuntimeDir(), "keybased.info")
  2003  }
  2004  
  2005  // GetKBFSInfoPath returns path to info file written by the KBFS service after startup
  2006  func (e *Env) GetKBFSInfoPath() string {
  2007  	return filepath.Join(e.GetRuntimeDir(), "kbfs.info")
  2008  }
  2009  
  2010  func (e *Env) GetUpdateDefaultInstructions() (string, error) {
  2011  	return PlatformSpecificUpgradeInstructionsString()
  2012  }
  2013  
  2014  func (e *Env) RunningInCI() bool {
  2015  	return e.GetBool(false,
  2016  		func() (bool, bool) { return e.getEnvBool("KEYBASE_RUN_CI") },
  2017  	)
  2018  }
  2019  
  2020  func (e *Env) WantsSystemd() bool {
  2021  	isNonstandard, isNonstandardErr := e.HomeFinder.IsNonstandardHome()
  2022  	return (e.GetRunMode() == ProductionRunMode && e.ModelessWantsSystemd() && (isNonstandardErr != nil || !isNonstandard))
  2023  }
  2024  
  2025  func (e *Env) ModelessWantsSystemd() bool {
  2026  	return (systemd.IsRunningSystemd() &&
  2027  		os.Getenv("KEYBASE_SYSTEMD") != "0")
  2028  }
  2029  
  2030  func (e *Env) ForceSecretStoreFile() bool {
  2031  	// By default use system-provided secret store (like MacOS Keychain), but
  2032  	// allow users to fall back to file-based store for testing and debugging.
  2033  	return e.GetBool(false,
  2034  		func() (bool, bool) { return e.getEnvBool("KEYBASE_SECRET_STORE_FILE") },
  2035  		func() (bool, bool) { return e.GetConfig().GetForceSecretStoreFile() },
  2036  	)
  2037  }
  2038  
  2039  func (e *Env) GetRuntimeStatsEnabled() bool {
  2040  	return e.GetBool(false,
  2041  		func() (bool, bool) { return e.getEnvBool("KEYBASE_RUNTIME_STATS_ENABLED") },
  2042  		func() (bool, bool) { return e.GetConfig().GetRuntimeStatsEnabled() },
  2043  	)
  2044  }
  2045  
  2046  func (e *Env) GetRememberPassphrase(username NormalizedUsername) bool {
  2047  	return e.GetBool(true,
  2048  		func() (bool, bool) { return e.cmd.GetRememberPassphrase(username) },
  2049  		func() (bool, bool) { return e.GetConfig().GetRememberPassphrase(username) },
  2050  	)
  2051  }
  2052  
  2053  func GetPlatformString() string {
  2054  	if IsIPad {
  2055  		return "ipad"
  2056  	}
  2057  	if isIOS {
  2058  		return "ios"
  2059  	}
  2060  	platform := runtime.GOOS
  2061  	if platform == "darwin" && runtime.GOARCH == "arm64" {
  2062  		platform = "darwin-arm64"
  2063  	}
  2064  	return platform
  2065  }
  2066  
  2067  func IsMobilePlatform() bool {
  2068  	s := GetPlatformString()
  2069  	return (s == "ios" || s == "android" || s == "ipad")
  2070  }
  2071  
  2072  func IsAndroid() bool {
  2073  	return GetPlatformString() == "android"
  2074  }
  2075  
  2076  func (e *Env) AllowPTrace() bool {
  2077  	return e.GetBool(false,
  2078  		func() (bool, bool) { return e.getEnvBool("KEYBASE_ALLOW_PTRACE") },
  2079  	)
  2080  }
  2081  
  2082  func (e *Env) GetLogFileConfig(filename string) *logger.LogFileConfig {
  2083  	var maxKeepFiles int
  2084  	var maxSize int64
  2085  
  2086  	if e.GetAppType() == MobileAppType && !e.GetFeatureFlags().Admin(e.GetUID()) {
  2087  		maxKeepFiles = 2
  2088  		maxSize = 16 * opt.MiB
  2089  	} else {
  2090  		maxKeepFiles = 3
  2091  		maxSize = 128 * opt.MiB
  2092  	}
  2093  
  2094  	return &logger.LogFileConfig{
  2095  		Path:         filename,
  2096  		MaxAge:       30 * 24 * time.Hour, // 30 days
  2097  		MaxSize:      maxSize,
  2098  		MaxKeepFiles: maxKeepFiles,
  2099  	}
  2100  }
  2101  func (e *Env) GetForceLinuxKeyring() bool {
  2102  	return e.GetBool(false,
  2103  		func() (bool, bool) { return e.cmd.GetForceLinuxKeyring() },
  2104  		func() (bool, bool) { return e.getEnvBool("KEYBASE_FORCE_LINUX_KEYRING") },
  2105  		func() (bool, bool) { return e.GetConfig().GetForceLinuxKeyring() })
  2106  }