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