1// Copyright 2015 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4package libkb 5 6import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "sync" 11 "time" 12 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 jsonw "github.com/keybase/go-jsonw" 15) 16 17type UserConfigWrapper struct { 18 userConfig *UserConfig 19 sync.Mutex 20} 21 22type JSONConfigFile struct { 23 *JSONFile 24 userConfigWrapper *UserConfigWrapper 25} 26 27var _ (ConfigReader) = (*JSONConfigFile)(nil) 28 29func NewJSONConfigFile(g *GlobalContext, s string) *JSONConfigFile { 30 return &JSONConfigFile{NewJSONFile(g, s, "config"), &UserConfigWrapper{}} 31} 32 33// Check looks inside the JSON file to see if any fields are poorly specified 34func (f *JSONConfigFile) Check() error { 35 return PickFirstError( 36 // Feel free to add others here.. 37 func() error { 38 _, err := f.GetRunMode() 39 return err 40 }(), 41 ) 42} 43 44func (f *JSONConfigFile) GetDurationAtPath(p string) (time.Duration, bool) { 45 s, ok := f.GetStringAtPath(p) 46 if !ok { 47 return 0, false 48 } 49 d, err := time.ParseDuration(s) 50 if err != nil { 51 f.G().Log.Warning("invalid time duration in config file: %s => %s", p, s) 52 return 0, false 53 } 54 return d, true 55} 56 57func (f *JSONConfigFile) GetTopLevelString(s string) (ret string) { 58 var e error 59 f.jw.AtKey(s).GetStringVoid(&ret, &e) 60 f.G().VDL.Log(VLog1, "Config: mapping %q -> %q", s, ret) 61 return 62} 63 64func (f *JSONConfigFile) GetTopLevelBool(s string) (res, isSet bool) { 65 if w := f.jw.AtKey(s); !w.IsNil() { 66 isSet = true 67 var e error 68 w.GetBoolVoid(&res, &e) 69 } 70 return 71} 72 73func (f *JSONConfigFile) GetUserConfig() (*UserConfig, error) { 74 f.userConfigWrapper.Lock() 75 defer f.userConfigWrapper.Unlock() 76 return f.getUserConfigWithLock() 77} 78 79// GetUserConfig looks for the `current_user` field to see if there's 80// a corresponding user object in the `users` table. There really should be. 81func (f *JSONConfigFile) getUserConfigWithLock() (ret *UserConfig, err error) { 82 var s string 83 if ret = f.userConfigWrapper.userConfig; ret != nil { 84 return 85 } 86 if s, err = f.jw.AtKey("current_user").GetString(); err != nil { 87 return 88 } 89 nu := NewNormalizedUsername(s) 90 if ret, err = f.GetUserConfigForUsername(nu); err != nil { 91 return 92 } else if ret != nil { 93 f.userConfigWrapper.userConfig = ret 94 } else { 95 err = ConfigError{f.filename, 96 fmt.Sprintf("Didn't find a UserConfig for %s", s)} 97 } 98 return 99} 100 101func (f *JSONConfigFile) GetDeviceIDForUsername(nu NormalizedUsername) keybase1.DeviceID { 102 f.userConfigWrapper.Lock() 103 defer f.userConfigWrapper.Unlock() 104 ret, err := f.GetUserConfigForUsername(nu) 105 var empty keybase1.DeviceID 106 if err != nil { 107 return empty 108 } 109 return ret.GetDeviceID() 110} 111 112func (f *JSONConfigFile) GetPassphraseStateForUsername(nu NormalizedUsername) (ret *keybase1.PassphraseState) { 113 f.userConfigWrapper.Lock() 114 defer f.userConfigWrapper.Unlock() 115 userConfig, err := f.GetUserConfigForUsername(nu) 116 if err != nil || userConfig == nil { 117 return nil 118 } 119 return userConfig.GetPassphraseState() 120} 121 122func (f *JSONConfigFile) GetDeviceIDForUID(u keybase1.UID) keybase1.DeviceID { 123 f.userConfigWrapper.Lock() 124 defer f.userConfigWrapper.Unlock() 125 ret, err := f.GetUserConfigForUID(u) 126 var empty keybase1.DeviceID 127 if err != nil || ret == nil { 128 return empty 129 } 130 return ret.GetDeviceID() 131} 132 133func (f *JSONConfigFile) GetUsernameForUID(u keybase1.UID) NormalizedUsername { 134 f.userConfigWrapper.Lock() 135 defer f.userConfigWrapper.Unlock() 136 ret, err := f.GetUserConfigForUID(u) 137 var empty NormalizedUsername 138 if err != nil || ret == nil { 139 return empty 140 } 141 return ret.GetUsername() 142} 143 144func (f *JSONConfigFile) GetUIDForUsername(n NormalizedUsername) keybase1.UID { 145 f.userConfigWrapper.Lock() 146 defer f.userConfigWrapper.Unlock() 147 ret, err := f.GetUserConfigForUsername(n) 148 var empty keybase1.UID 149 if err != nil || ret == nil { 150 return empty 151 } 152 return ret.GetUID() 153} 154 155func (f *JSONConfigFile) SwitchUser(nu NormalizedUsername) error { 156 f.userConfigWrapper.Lock() 157 defer f.userConfigWrapper.Unlock() 158 159 if cu := f.getCurrentUser(); cu.Eq(nu) { 160 f.G().Log.Debug("| Already configured as user=%s", nu) 161 return nil 162 } 163 164 var err error 165 var val *jsonw.Wrapper 166 if f.jw.AtKey("users").AtKey(nu.String()).IsNil() { 167 val = jsonw.NewNil() 168 err = UserNotFoundError{Msg: nu.String()} 169 } else { 170 val = jsonw.NewString(nu.String()) 171 } 172 173 setKeyErr := f.jw.SetKey("current_user", val) 174 if err == nil { 175 err = setKeyErr 176 } 177 f.userConfigWrapper.userConfig = nil 178 saveErr := f.Save() 179 if err == nil { 180 err = saveErr 181 } 182 return err 183} 184 185// NukeUser deletes the given user from the config file, or if 186// the given user is empty, deletes the current user from the 187// config file. 188func (f *JSONConfigFile) NukeUser(nu NormalizedUsername) error { 189 f.userConfigWrapper.Lock() 190 defer f.userConfigWrapper.Unlock() 191 192 if cu := f.getCurrentUser(); nu.IsNil() || cu.Eq(nu) { 193 err := f.jw.DeleteValueAtPath("current_user") 194 f.userConfigWrapper.userConfig = nil 195 if err != nil { 196 return err 197 } 198 if nu.IsNil() { 199 nu = cu 200 } 201 } 202 203 if !f.jw.AtKey("users").AtKey(nu.String()).IsNil() { 204 err := f.jw.DeleteValueAtPath("users." + nu.String()) 205 if err != nil { 206 return err 207 } 208 } 209 210 return f.Save() 211} 212 213// GetUserConfigForUsername sees if there's a UserConfig object for the given 214// username previously stored. 215func (f *JSONConfigFile) GetUserConfigForUsername(nu NormalizedUsername) (*UserConfig, error) { 216 if uc := f.copyUserConfigIfForUsername(nu); uc != nil { 217 return uc, nil 218 } 219 return ImportUserConfigFromJSONWrapper(f.jw.AtKey("users").AtKey(nu.String())) 220} 221 222func (f *JSONConfigFile) copyUserConfigIfForUsername(u NormalizedUsername) *UserConfig { 223 if f.userConfigWrapper == nil || f.userConfigWrapper.userConfig == nil { 224 return nil 225 } 226 if f.userConfigWrapper.userConfig.GetUsername().IsNil() { 227 return nil 228 } 229 if f.userConfigWrapper.userConfig.GetUsername().Eq(u) { 230 tmp := *f.userConfigWrapper.userConfig 231 return &tmp 232 } 233 return nil 234} 235 236func (f *JSONConfigFile) copyUserConfigIfForUID(u keybase1.UID) *UserConfig { 237 if f.userConfigWrapper == nil || f.userConfigWrapper.userConfig == nil { 238 return nil 239 } 240 if f.userConfigWrapper.userConfig.GetUID().IsNil() { 241 return nil 242 } 243 if f.userConfigWrapper.userConfig.GetUID().Equal(u) { 244 tmp := *f.userConfigWrapper.userConfig 245 return &tmp 246 } 247 return nil 248} 249 250// GetUserConfigForUID sees if there's a UserConfig object for the given UIDs previously stored. 251func (f *JSONConfigFile) GetUserConfigForUID(u keybase1.UID) (*UserConfig, error) { 252 253 if uc := f.copyUserConfigIfForUID(u); uc != nil { 254 return uc, nil 255 } 256 257 d := f.jw.AtKey("users") 258 keys, _ := d.Keys() 259 for _, key := range keys { 260 uc, err := f.GetUserConfigForUsername(NewNormalizedUsername(key)) 261 if err == nil && uc != nil && uc.GetUID().Equal(u) { 262 return uc, nil 263 } 264 } 265 return nil, nil 266} 267 268func (f *JSONConfigFile) GetAllUserConfigs() (current *UserConfig, others []UserConfig, err error) { 269 270 currentUsername, allUsernames, err := f.GetAllUsernames() 271 if err != nil { 272 return nil, nil, err 273 } 274 275 if !currentUsername.IsNil() { 276 current, _ = f.GetUserConfigForUsername(currentUsername) 277 } 278 279 for _, u := range allUsernames { 280 tmp, err := f.GetUserConfigForUsername(u) 281 if err == nil && tmp != nil { 282 others = append(others, *tmp) 283 } 284 } 285 286 return current, others, nil 287} 288 289func (f *JSONConfigFile) GetAllUsernames() (current NormalizedUsername, others []NormalizedUsername, err error) { 290 current = f.getCurrentUser() 291 uw := f.jw.AtKey("users") 292 if uw.IsNil() { 293 return 294 } 295 keys, e := uw.Keys() 296 if e != nil { 297 err = e 298 return 299 } 300 for _, k := range keys { 301 u := uw.AtKey(k) 302 if u == nil { 303 continue 304 } 305 name, e := u.AtKey("name").GetString() 306 if e != nil { 307 err = e 308 return 309 } 310 nu := NewNormalizedUsername(name) 311 if !nu.Eq(current) { 312 others = append(others, nu) 313 } 314 } 315 return 316} 317 318// SetDeviceID sets the device field of the UserConfig object 319func (f *JSONConfigFile) SetDeviceID(did keybase1.DeviceID) (err error) { 320 f.userConfigWrapper.Lock() 321 defer f.userConfigWrapper.Unlock() 322 323 f.G().Log.Debug("| Setting DeviceID to %v\n", did) 324 var u *UserConfig 325 if u, err = f.getUserConfigWithLock(); err != nil { 326 } else if u == nil { 327 err = NoUserConfigError{} 328 } else { 329 u.SetDevice(did) 330 err = f.setUserConfigWithLock(u, true) 331 } 332 return 333} 334 335func (f *JSONConfigFile) getCurrentUser() NormalizedUsername { 336 s, _ := f.jw.AtKey("current_user").GetString() 337 return NormalizedUsername(s) 338} 339 340// SetUserConfig writes this UserConfig to the config file and updates the 341// currently active UserConfig in memory. If the given UserConfig is nil, then 342// just empty everything out and clear the `current_user` field. Note that 343// we never actually overwrite users.<username>, we just write it if it 344// doesn't already exist, and we update the `current_user` pointer. 345func (f *JSONConfigFile) SetUserConfig(u *UserConfig, overwrite bool) error { 346 f.userConfigWrapper.Lock() 347 defer f.userConfigWrapper.Unlock() 348 return f.setUserConfigWithLock(u, overwrite) 349} 350 351func (f *JSONConfigFile) setUserConfigWithLock(u *UserConfig, overwrite bool) error { 352 353 if u == nil { 354 f.G().Log.Debug("| SetUserConfig(nil)") 355 err := f.jw.DeleteKey("current_user") 356 if err != nil { 357 return err 358 } 359 f.userConfigWrapper.userConfig = nil 360 return f.Save() 361 } 362 363 if u.IsOneshot() { 364 f.userConfigWrapper.userConfig = u 365 return nil 366 } 367 368 parent := f.jw.AtKey("users") 369 un := u.GetUsername() 370 f.G().Log.Debug("| SetUserConfig(%s)", un) 371 if parent.IsNil() { 372 parent = jsonw.NewDictionary() 373 err := f.jw.SetKey("users", parent) 374 if err != nil { 375 return err 376 } 377 } 378 if parent.AtKey(un.String()).IsNil() || overwrite { 379 uWrapper, err := jsonw.NewObjectWrapper(*u) 380 if err != nil { 381 return err 382 } 383 err = parent.SetKey(un.String(), uWrapper) 384 if err != nil { 385 return err 386 } 387 f.userConfigWrapper.userConfig = u 388 } 389 390 if !f.getCurrentUser().Eq(un) { 391 err := f.jw.SetKey("current_user", jsonw.NewString(un.String())) 392 if err != nil { 393 return err 394 } 395 f.userConfigWrapper.userConfig = nil 396 } 397 398 return f.Save() 399} 400 401func (f *JSONConfigFile) Reset() { 402 f.jw = jsonw.NewDictionary() 403 _ = f.Save() 404} 405 406func (f *JSONConfigFile) GetHome() string { 407 return f.GetTopLevelString("home") 408} 409func (f *JSONConfigFile) GetMobileSharedHome() string { 410 return f.GetTopLevelString("mobile_shared_home") 411} 412func (f *JSONConfigFile) GetServerURI() (string, error) { 413 return f.GetTopLevelString("server"), nil 414} 415func (f *JSONConfigFile) GetConfigFilename() string { 416 return f.GetTopLevelString("config_file") 417} 418func (f *JSONConfigFile) GetUpdaterConfigFilename() string { 419 return f.GetTopLevelString("updater_config_file") 420} 421func (f *JSONConfigFile) GetGUIConfigFilename() string { 422 return f.GetTopLevelString("gui_config_file") 423} 424func (f *JSONConfigFile) GetDeviceCloneStateFilename() string { 425 return f.GetTopLevelString("device_clone_state_file") 426} 427func (f *JSONConfigFile) GetSecretKeyringTemplate() string { 428 return f.GetTopLevelString("secret_keyring") 429} 430func (f *JSONConfigFile) GetSessionFilename() string { 431 return f.GetTopLevelString("session_file") 432} 433func (f *JSONConfigFile) GetDbFilename() string { 434 return f.GetTopLevelString("db") 435} 436func (f *JSONConfigFile) GetChatDbFilename() string { 437 return f.GetTopLevelString("chat_db") 438} 439func (f *JSONConfigFile) GetPvlKitFilename() string { 440 return f.GetTopLevelString("pvl_kit") 441} 442func (f *JSONConfigFile) GetParamProofKitFilename() string { 443 return f.GetTopLevelString("paramproof_kit") 444} 445func (f *JSONConfigFile) GetExternalURLKitFilename() string { 446 return f.GetTopLevelString("externalurl_kit") 447} 448func (f *JSONConfigFile) GetProveBypass() (bool, bool) { 449 return f.GetBoolAtPath("prove_bypass") 450} 451func (f *JSONConfigFile) GetPinentry() string { 452 res, _ := f.GetStringAtPath("pinentry.path") 453 return res 454} 455func (f *JSONConfigFile) GetGpg() string { 456 res, _ := f.GetStringAtPath("gpg.command") 457 return res 458} 459func (f *JSONConfigFile) GetLocalRPCDebug() string { 460 return f.GetTopLevelString("local_rpc_debug") 461} 462func (f *JSONConfigFile) GetTimers() string { 463 return f.GetTopLevelString("timers") 464} 465func (f *JSONConfigFile) GetGpgOptions() []string { 466 var ret []string 467 if f.jw == nil { 468 // noop 469 } else if v := f.jw.AtPath("gpg.options"); v == nil { 470 // noop 471 } else if l, e := v.Len(); e != nil || l == 0 { 472 // noop 473 } else { 474 ret = make([]string, 0, l) 475 for i := 0; i < l; i++ { 476 if s, e := v.AtIndex(i).GetString(); e == nil { 477 ret = append(ret, s) 478 } 479 } 480 } 481 return ret 482} 483func (f *JSONConfigFile) GetRunMode() (ret RunMode, err error) { 484 ret = NoRunMode 485 if s, isSet := f.GetStringAtPath("run_mode"); isSet { 486 ret, err = StringToRunMode(s) 487 } 488 return ret, err 489} 490func (f *JSONConfigFile) GetFeatureFlags() (ret FeatureFlags, err error) { 491 if s, isSet := f.GetStringAtPath("features"); isSet { 492 ret = StringToFeatureFlags(s) 493 } 494 return ret, err 495} 496func (f *JSONConfigFile) GetNoPinentry() (bool, bool) { 497 return f.GetBoolAtPath("pinentry.disabled") 498} 499func (f *JSONConfigFile) GetUsername() (ret NormalizedUsername) { 500 if uc, _ := f.GetUserConfig(); uc != nil { 501 ret = uc.GetUsername() 502 } 503 return ret 504} 505func (f *JSONConfigFile) GetUID() (ret keybase1.UID) { 506 if uc, _ := f.GetUserConfig(); uc != nil { 507 ret = uc.GetUID() 508 } 509 return ret 510} 511func (f *JSONConfigFile) GetDeviceID() (ret keybase1.DeviceID) { 512 if uc, _ := f.GetUserConfig(); uc != nil { 513 ret = uc.GetDeviceID() 514 } 515 return ret 516} 517 518func (f *JSONConfigFile) GetPassphraseState() (ret *keybase1.PassphraseState) { 519 if uc, _ := f.GetUserConfig(); uc != nil { 520 ret = uc.GetPassphraseState() 521 } 522 return ret 523} 524 525func (f *JSONConfigFile) SetPassphraseState(passphraseState keybase1.PassphraseState) (err error) { 526 f.userConfigWrapper.Lock() 527 defer f.userConfigWrapper.Unlock() 528 529 f.G().Log.Debug("| Setting PassphraseState to %v\n", passphraseState) 530 var u *UserConfig 531 if u, err = f.getUserConfigWithLock(); err != nil { 532 } else if u == nil { 533 err = NoUserConfigError{} 534 } else { 535 u.SetPassphraseState(passphraseState) 536 err = f.setUserConfigWithLock(u, true) 537 } 538 return 539} 540 541func (f *JSONConfigFile) GetTorMode() (ret TorMode, err error) { 542 if s, isSet := f.GetStringAtPath("tor.mode"); isSet { 543 ret, err = StringToTorMode(s) 544 } 545 return ret, err 546} 547 548func (f *JSONConfigFile) GetTorHiddenAddress() string { 549 s, _ := f.GetStringAtPath("tor.hidden_address") 550 return s 551} 552func (f *JSONConfigFile) GetTorProxy() string { 553 s, _ := f.GetStringAtPath("tor.proxy") 554 return s 555} 556 557func (f *JSONConfigFile) GetProxy() string { 558 return f.GetTopLevelString("proxy") 559} 560func (f *JSONConfigFile) GetProxyType() string { 561 return f.GetTopLevelString("proxy-type") 562} 563func (f *JSONConfigFile) IsCertPinningEnabled() bool { 564 res, isSet := f.GetTopLevelBool("disable-cert-pinning") 565 if !isSet { 566 // Enable SSL pinning if the flag is not set 567 return true 568 } 569 return !res 570} 571func (f *JSONConfigFile) GetDebug() (bool, bool) { 572 return f.GetTopLevelBool("debug") 573} 574func (f *JSONConfigFile) GetDebugJourneycard() (bool, bool) { 575 return f.GetTopLevelBool("debug_journeycard") 576} 577func (f *JSONConfigFile) GetDisplayRawUntrustedOutput() (bool, bool) { 578 return f.GetTopLevelBool("display_raw_untrusted_output") 579} 580func (f *JSONConfigFile) GetVDebugSetting() string { 581 return f.GetTopLevelString("vdebug") 582} 583func (f *JSONConfigFile) GetAutoFork() (bool, bool) { 584 return f.GetTopLevelBool("auto_fork") 585} 586 587func (f *JSONConfigFile) GetRememberPassphrase(username NormalizedUsername) (bool, bool) { 588 const legacyRememberPassphraseKey = "remember_passphrase" 589 590 if username.IsNil() { 591 return f.GetTopLevelBool(legacyRememberPassphraseKey) 592 } 593 if m, ok := f.jw.AtKey("remember_passphrase_map").GetDataOrNil().(map[string]interface{}); ok { 594 if ret, mOk := m[username.String()]; mOk { 595 if boolRet, boolOk := ret.(bool); boolOk { 596 return boolRet, true 597 } 598 } 599 } 600 return f.GetTopLevelBool(legacyRememberPassphraseKey) 601} 602func (f *JSONConfigFile) GetStayLoggedOut() (bool, bool) { 603 return f.GetBoolAtPath("stay_logged_out") 604} 605func (f *JSONConfigFile) SetStayLoggedOut(stayLoggedOut bool) error { 606 return f.SetBoolAtPath("stay_logged_out", stayLoggedOut) 607} 608func (f *JSONConfigFile) GetLogFormat() string { 609 return f.GetTopLevelString("log_format") 610} 611func (f *JSONConfigFile) GetStandalone() (bool, bool) { 612 return f.GetTopLevelBool("standalone") 613} 614func (f *JSONConfigFile) GetGregorURI() string { 615 s, _ := f.GetStringAtPath("push.server_uri") 616 return s 617} 618func (f *JSONConfigFile) GetGregorDisabled() (bool, bool) { 619 return f.GetBoolAtPath("push.disabled") 620} 621func (f *JSONConfigFile) GetSecretStorePrimingDisabled() (bool, bool) { 622 // SecretStorePrimingDisabled is only for tests 623 return false, false 624} 625func (f *JSONConfigFile) GetBGIdentifierDisabled() (bool, bool) { 626 return f.GetBoolAtPath("bg_identifier.disabled") 627} 628func (f *JSONConfigFile) GetGregorSaveInterval() (time.Duration, bool) { 629 return f.GetDurationAtPath("push.save_interval") 630} 631 632func (f *JSONConfigFile) GetGregorPingInterval() (time.Duration, bool) { 633 return f.GetDurationAtPath("push.ping_interval") 634} 635 636func (f *JSONConfigFile) GetGregorPingTimeout() (time.Duration, bool) { 637 return f.GetDurationAtPath("push.ping_timeout") 638} 639 640func (f *JSONConfigFile) GetChatDelivererInterval() (time.Duration, bool) { 641 return f.GetDurationAtPath("chat.deliverer_interval") 642} 643 644func (f *JSONConfigFile) getCacheSize(w string) (int, bool) { 645 return f.jw.AtPathGetInt(w) 646} 647 648func (f *JSONConfigFile) GetUserCacheMaxAge() (time.Duration, bool) { 649 return f.GetDurationAtPath("cache.maxage.users") 650} 651func (f *JSONConfigFile) GetAPITimeout() (time.Duration, bool) { 652 return f.GetDurationAtPath("timeouts.api") 653} 654func (f *JSONConfigFile) GetScraperTimeout() (time.Duration, bool) { 655 return f.GetDurationAtPath("timeouts.scraper") 656} 657func (f *JSONConfigFile) GetProofCacheSize() (int, bool) { 658 return f.getCacheSize("cache.limits.proofs") 659} 660 661func (f *JSONConfigFile) GetProofCacheLongDur() (time.Duration, bool) { 662 return f.GetDurationAtPath("cache.long_duration.proofs") 663} 664 665func (f *JSONConfigFile) GetProofCacheMediumDur() (time.Duration, bool) { 666 return f.GetDurationAtPath("cache.medium_duration.proofs") 667} 668 669func (f *JSONConfigFile) GetProofCacheShortDur() (time.Duration, bool) { 670 return f.GetDurationAtPath("cache.short_duration.proofs") 671} 672 673func (f *JSONConfigFile) GetLinkCacheSize() (int, bool) { 674 return f.getCacheSize("cache.limits.links") 675} 676 677func (f *JSONConfigFile) GetLinkCacheCleanDur() (time.Duration, bool) { 678 return f.GetDurationAtPath("cache.clean_duration.links") 679} 680 681func (f *JSONConfigFile) GetUPAKCacheSize() (int, bool) { 682 return f.getCacheSize("cache.limits.upak") 683} 684 685func (f *JSONConfigFile) GetUIDMapFullNameCacheSize() (int, bool) { 686 return f.getCacheSize("cache.limits.uid_map_full_name") 687} 688 689func (f *JSONConfigFile) GetPayloadCacheSize() (int, bool) { 690 return f.getCacheSize("cache.limits.payloads") 691} 692 693func (f *JSONConfigFile) GetLevelDBNumFiles() (int, bool) { 694 return f.GetIntAtPath("leveldb.num_files") 695} 696 697func (f *JSONConfigFile) GetLevelDBWriteBufferMB() (int, bool) { 698 return f.GetIntAtPath("leveldb.write_buffer_mb") 699} 700 701func (f *JSONConfigFile) GetChatInboxSourceLocalizeThreads() (int, bool) { 702 return f.GetIntAtPath("chat.inboxsource.localizethreads") 703} 704 705func (f *JSONConfigFile) getStringArray(v *jsonw.Wrapper) []string { 706 n, err := v.Len() 707 if err != nil { 708 return nil 709 } 710 711 if n == 0 { 712 return nil 713 } 714 715 ret := make([]string, n) 716 for i := 0; i < n; i++ { 717 s, err := v.AtIndex(i).GetString() 718 if err != nil { 719 return nil 720 } 721 ret[i] = s 722 } 723 return ret 724} 725 726func (f *JSONConfigFile) GetMerkleKIDs() []string { 727 if f.jw == nil { 728 return nil 729 } 730 731 v, err := f.jw.AtKey("keys").AtKey("merkle").ToArray() 732 if err != nil || v == nil { 733 return nil 734 } 735 736 return f.getStringArray(v) 737} 738 739func (f *JSONConfigFile) GetCodeSigningKIDs() []string { 740 if f.jw == nil { 741 return nil 742 } 743 744 v, err := f.jw.AtKey("keys").AtKey("codesigning").ToArray() 745 if err != nil || v == nil { 746 return nil 747 } 748 return f.getStringArray(v) 749} 750 751func (f *JSONConfigFile) GetGpgHome() (ret string) { 752 ret, _ = f.GetStringAtPath("gpg.home") 753 return ret 754} 755 756func (f *JSONConfigFile) GetBundledCA(host string) (ret string) { 757 var err error 758 f.jw.AtKey("bundled_ca").AtKey(host).GetStringVoid(&ret, &err) 759 if err == nil { 760 f.G().Log.Debug("Read bundled CA for %s", host) 761 } 762 return ret 763} 764 765func (f *JSONConfigFile) GetSocketFile() string { 766 return f.GetTopLevelString("socket_file") 767} 768func (f *JSONConfigFile) GetPidFile() string { 769 return f.GetTopLevelString("pid_file") 770} 771 772func (f *JSONConfigFile) GetProxyCACerts() (ret []string, err error) { 773 jw := f.jw.AtKey("proxy_ca_certs") 774 if l, e := jw.Len(); e == nil { 775 for i := 0; i < l; i++ { 776 s, e2 := jw.AtIndex(i).GetString() 777 if e2 != nil { 778 err = ConfigError{f.filename, 779 fmt.Sprintf("Error reading proxy CA file @ index %d: %s", i, e2)} 780 return 781 } 782 783 ret = append(ret, s) 784 } 785 } else if s, e := jw.GetString(); e == nil { 786 ret = strings.Split(s, ":") 787 } else if !jw.IsNil() { 788 err = ConfigError{f.filename, fmt.Sprintf("Can't read Proxy CA certs: %s", e)} 789 } 790 return 791} 792 793func (f *JSONConfigFile) GetLogFile() string { 794 return f.GetTopLevelString("log_file") 795} 796func (f *JSONConfigFile) GetEKLogFile() string { 797 return f.GetTopLevelString("ek_log_file") 798} 799func (f *JSONConfigFile) GetPerfLogFile() string { 800 return f.GetTopLevelString("perf_log_file") 801} 802func (f *JSONConfigFile) GetGUILogFile() string { 803 return f.GetTopLevelString("gui_log_file") 804} 805 806func (f *JSONConfigFile) GetUseDefaultLogFile() (bool, bool) { 807 return f.GetTopLevelBool("use_default_log_file") 808} 809 810func (f *JSONConfigFile) GetUseRootConfigFile() (bool, bool) { 811 return false, false 812} 813 814func (f *JSONConfigFile) GetLogPrefix() string { 815 return f.GetTopLevelString("log_prefix") 816} 817 818func (f *JSONConfigFile) GetSecurityAccessGroupOverride() (bool, bool) { 819 return false, false 820} 821 822func (f *JSONConfigFile) GetUpdatePreferenceAuto() (bool, bool) { 823 return f.GetBoolAtPath("updates.auto") 824} 825 826func (f *JSONConfigFile) GetUpdatePreferenceSnoozeUntil() keybase1.Time { 827 return f.GetTimeAtPath("updates.snooze") 828} 829 830func (f *JSONConfigFile) GetUpdateLastChecked() keybase1.Time { 831 return f.GetTimeAtPath("updates.last_checked") 832} 833 834func (f *JSONConfigFile) GetUpdatePreferenceSkip() string { 835 s, _ := f.GetStringAtPath("updates.skip") 836 return s 837} 838 839func (f *JSONConfigFile) SetUpdatePreferenceAuto(b bool) error { 840 return f.SetBoolAtPath("updates.auto", b) 841} 842 843func (f *JSONConfigFile) SetUpdatePreferenceSkip(v string) error { 844 return f.SetStringAtPath("updates.skip", v) 845} 846 847func (f *JSONConfigFile) SetUpdatePreferenceSnoozeUntil(t keybase1.Time) error { 848 return f.SetTimeAtPath("updates.snooze", t) 849} 850 851func (f *JSONConfigFile) SetUpdateLastChecked(t keybase1.Time) error { 852 return f.SetTimeAtPath("updates.last_checked", t) 853} 854 855func (f *JSONConfigFile) GetUpdateURL() string { 856 s, _ := f.GetStringAtPath("updates.url") 857 return s 858} 859 860func (f *JSONConfigFile) GetUpdateDisabled() (bool, bool) { 861 return f.GetBoolAtPath("updates.disabled") 862} 863 864func (f *JSONConfigFile) GetTimeAtPath(path string) keybase1.Time { 865 var ret keybase1.Time 866 s, _ := f.GetStringAtPath(path) 867 if len(s) == 0 { 868 return ret 869 } 870 u, err := strconv.ParseUint(s, 10, 64) 871 if err != nil { 872 return ret 873 } 874 ret = keybase1.Time(u) 875 return ret 876} 877 878func (f *JSONConfigFile) SetTimeAtPath(path string, t keybase1.Time) error { 879 if t == keybase1.Time(0) { 880 return f.SetNullAtPath(path) 881 } 882 return f.SetStringAtPath(path, fmt.Sprintf("%d", t)) 883} 884 885func (f *JSONConfigFile) GetLocalTrackMaxAge() (time.Duration, bool) { 886 return f.GetDurationAtPath("local_track_max_age") 887} 888 889func (f *JSONConfigFile) GetMountDir() string { 890 return f.GetTopLevelString("mountdir") 891} 892 893func (f *JSONConfigFile) GetMountDirDefault() string { 894 return f.GetTopLevelString("mountdirdefault") 895} 896 897func bug3964path(un NormalizedUsername) string { 898 return fmt.Sprintf("maintenance.%s.bug_3964_repair_time", un) 899} 900 901func (f *JSONConfigFile) GetBug3964RepairTime(un NormalizedUsername) (time.Time, error) { 902 if un == "" { 903 return time.Time{}, NoUserConfigError{} 904 } 905 s, _ := f.GetStringAtPath(bug3964path(un)) 906 if s == "" { 907 return time.Time{}, nil 908 } 909 i, err := strconv.ParseUint(s, 10, 64) 910 if err != nil { 911 return time.Time{}, err 912 } 913 return keybase1.FromTime(keybase1.Time(i)), nil 914} 915 916func (f *JSONConfigFile) SetBug3964RepairTime(un NormalizedUsername, t time.Time) (err error) { 917 return f.SetStringAtPath(bug3964path(un), fmt.Sprintf("%d", int64(keybase1.ToTime(t)))) 918} 919 920func (f *JSONConfigFile) GetAppType() AppType { 921 return AppType(f.GetTopLevelString("app_type")) 922} 923 924func (f *JSONConfigFile) IsMobileExtension() (bool, bool) { 925 return f.GetBoolAtPath("mobile_extension") 926} 927 928func (f *JSONConfigFile) GetSlowGregorConn() (bool, bool) { 929 return f.GetBoolAtPath("slow_gregor_conn") 930} 931 932func (f *JSONConfigFile) GetReadDeletedSigChain() (bool, bool) { 933 return f.GetBoolAtPath("read_deleted_sigchain") 934} 935 936func (f *JSONConfigFile) SetRememberPassphrase(username NormalizedUsername, remember bool) error { 937 if username.IsNil() { 938 return f.SetBoolAtPath("remember_passphrase", remember) 939 } 940 return f.SetBoolAtPath(fmt.Sprintf("remember_passphrase_map.%s", username.String()), remember) 941} 942 943func (f *JSONConfigFile) GetAttachmentHTTPStartPort() (int, bool) { 944 return f.GetIntAtPath("attachment_httpsrv_port") 945} 946 947func (f *JSONConfigFile) GetAttachmentDisableMulti() (bool, bool) { 948 return f.GetBoolAtPath("attachment_disable_multi") 949} 950 951func (f *JSONConfigFile) GetDisableTeamAuditor() (bool, bool) { 952 return f.GetBoolAtPath("disable_team_auditor") 953} 954 955func (f *JSONConfigFile) GetDisableTeamBoxAuditor() (bool, bool) { 956 return f.GetBoolAtPath("disable_team_box_auditor") 957} 958 959func (f *JSONConfigFile) GetDisableEKBackgroundKeygen() (bool, bool) { 960 return f.GetBoolAtPath("disable_ek_background_keygen") 961} 962 963func (f *JSONConfigFile) GetDisableMerkleAuditor() (bool, bool) { 964 return f.GetBoolAtPath("disable_merkle_auditor") 965} 966 967func (f *JSONConfigFile) GetDisableSearchIndexer() (bool, bool) { 968 return f.GetBoolAtPath("disable_search_indexer") 969} 970 971func (f *JSONConfigFile) GetDisableBgConvLoader() (bool, bool) { 972 return f.GetBoolAtPath("disable_bg_conv_loader") 973} 974 975func (f *JSONConfigFile) GetEnableBotLiteMode() (bool, bool) { 976 return f.GetBoolAtPath("enable_bot_lite_mode") 977} 978 979func (f *JSONConfigFile) GetExtraNetLogging() (bool, bool) { 980 return f.GetBoolAtPath("extra_net_logging") 981} 982 983func (f *JSONConfigFile) GetForceLinuxKeyring() (bool, bool) { 984 return f.GetBoolAtPath("force_linux_keyring") 985} 986 987func (f *JSONConfigFile) GetForceSecretStoreFile() (bool, bool) { 988 return f.GetBoolAtPath("force_less_safe_secret_store_file") 989} 990 991func (f *JSONConfigFile) GetRuntimeStatsEnabled() (bool, bool) { 992 return f.GetBoolAtPath("runtime_stats_enabled") 993} 994 995func (f *JSONConfigFile) GetAndroidInstallReferrerChecked() bool { 996 val, isSet := f.GetBoolAtPath("android_install_referrer_checked") 997 // default to false when value is not set 998 return isSet && val 999} 1000 1001func (f *JSONConfigFile) SetAndroidInstallReferrerChecked(b bool) error { 1002 return f.SetBoolAtPath("android_install_referrer_checked", b) 1003} 1004