You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

legacy.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright (c) 2018 Shivaram Lingamneni
  2. package irc
  3. import (
  4. "encoding/base64"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "strconv"
  9. "time"
  10. "github.com/tidwall/buntdb"
  11. "github.com/ergochat/ergo/irc/modes"
  12. )
  13. var (
  14. errInvalidPasswordHash = errors.New("invalid password hash")
  15. )
  16. // Decode a hashed passphrase as it would appear in a config file,
  17. // retaining compatibility with old versions of `oragono genpasswd`
  18. // that used to apply a redundant layer of base64
  19. func decodeLegacyPasswordHash(hash string) ([]byte, error) {
  20. // a correctly formatted bcrypt hash is 60 bytes of printable ASCII
  21. if len(hash) == 80 {
  22. // double-base64, remove the outer layer:
  23. return base64.StdEncoding.DecodeString(hash)
  24. } else if len(hash) == 60 {
  25. return []byte(hash), nil
  26. } else {
  27. return nil, errInvalidPasswordHash
  28. }
  29. }
  30. // legacy channel registration code
  31. const (
  32. keyChannelExists = "channel.exists %s"
  33. keyChannelName = "channel.name %s" // stores the 'preferred name' of the channel, not casemapped
  34. keyChannelRegTime = "channel.registered.time %s"
  35. keyChannelFounder = "channel.founder %s"
  36. keyChannelTopic = "channel.topic %s"
  37. keyChannelTopicSetBy = "channel.topic.setby %s"
  38. keyChannelTopicSetTime = "channel.topic.settime %s"
  39. keyChannelBanlist = "channel.banlist %s"
  40. keyChannelExceptlist = "channel.exceptlist %s"
  41. keyChannelInvitelist = "channel.invitelist %s"
  42. keyChannelPassword = "channel.key %s"
  43. keyChannelModes = "channel.modes %s"
  44. keyChannelAccountToUMode = "channel.accounttoumode %s"
  45. keyChannelUserLimit = "channel.userlimit %s"
  46. keyChannelSettings = "channel.settings %s"
  47. keyChannelForward = "channel.forward %s"
  48. keyChannelPurged = "channel.purged %s"
  49. )
  50. func deleteLegacyChannel(tx *buntdb.Tx, nameCasefolded string) {
  51. tx.Delete(fmt.Sprintf(keyChannelExists, nameCasefolded))
  52. tx.Delete(fmt.Sprintf(keyChannelName, nameCasefolded))
  53. tx.Delete(fmt.Sprintf(keyChannelRegTime, nameCasefolded))
  54. tx.Delete(fmt.Sprintf(keyChannelFounder, nameCasefolded))
  55. tx.Delete(fmt.Sprintf(keyChannelTopic, nameCasefolded))
  56. tx.Delete(fmt.Sprintf(keyChannelTopicSetBy, nameCasefolded))
  57. tx.Delete(fmt.Sprintf(keyChannelTopicSetTime, nameCasefolded))
  58. tx.Delete(fmt.Sprintf(keyChannelBanlist, nameCasefolded))
  59. tx.Delete(fmt.Sprintf(keyChannelExceptlist, nameCasefolded))
  60. tx.Delete(fmt.Sprintf(keyChannelInvitelist, nameCasefolded))
  61. tx.Delete(fmt.Sprintf(keyChannelPassword, nameCasefolded))
  62. tx.Delete(fmt.Sprintf(keyChannelModes, nameCasefolded))
  63. tx.Delete(fmt.Sprintf(keyChannelAccountToUMode, nameCasefolded))
  64. tx.Delete(fmt.Sprintf(keyChannelUserLimit, nameCasefolded))
  65. tx.Delete(fmt.Sprintf(keyChannelSettings, nameCasefolded))
  66. tx.Delete(fmt.Sprintf(keyChannelForward, nameCasefolded))
  67. }
  68. func loadLegacyChannel(tx *buntdb.Tx, nameCasefolded string) (info RegisteredChannel, err error) {
  69. channelKey := nameCasefolded
  70. // nice to have: do all JSON (de)serialization outside of the buntdb transaction
  71. _, dberr := tx.Get(fmt.Sprintf(keyChannelExists, channelKey))
  72. if dberr == buntdb.ErrNotFound {
  73. // chan does not already exist, return
  74. err = errNoSuchChannel
  75. return
  76. }
  77. // channel exists, load it
  78. name, _ := tx.Get(fmt.Sprintf(keyChannelName, channelKey))
  79. regTime, _ := tx.Get(fmt.Sprintf(keyChannelRegTime, channelKey))
  80. regTimeInt, _ := strconv.ParseInt(regTime, 10, 64)
  81. founder, _ := tx.Get(fmt.Sprintf(keyChannelFounder, channelKey))
  82. topic, _ := tx.Get(fmt.Sprintf(keyChannelTopic, channelKey))
  83. topicSetBy, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetBy, channelKey))
  84. var topicSetTime time.Time
  85. topicSetTimeStr, _ := tx.Get(fmt.Sprintf(keyChannelTopicSetTime, channelKey))
  86. if topicSetTimeInt, topicSetTimeErr := strconv.ParseInt(topicSetTimeStr, 10, 64); topicSetTimeErr == nil {
  87. topicSetTime = time.Unix(0, topicSetTimeInt).UTC()
  88. }
  89. password, _ := tx.Get(fmt.Sprintf(keyChannelPassword, channelKey))
  90. modeString, _ := tx.Get(fmt.Sprintf(keyChannelModes, channelKey))
  91. userLimitString, _ := tx.Get(fmt.Sprintf(keyChannelUserLimit, channelKey))
  92. forward, _ := tx.Get(fmt.Sprintf(keyChannelForward, channelKey))
  93. banlistString, _ := tx.Get(fmt.Sprintf(keyChannelBanlist, channelKey))
  94. exceptlistString, _ := tx.Get(fmt.Sprintf(keyChannelExceptlist, channelKey))
  95. invitelistString, _ := tx.Get(fmt.Sprintf(keyChannelInvitelist, channelKey))
  96. accountToUModeString, _ := tx.Get(fmt.Sprintf(keyChannelAccountToUMode, channelKey))
  97. settingsString, _ := tx.Get(fmt.Sprintf(keyChannelSettings, channelKey))
  98. modeSlice := make([]modes.Mode, len(modeString))
  99. for i, mode := range modeString {
  100. modeSlice[i] = modes.Mode(mode)
  101. }
  102. userLimit, _ := strconv.Atoi(userLimitString)
  103. var banlist map[string]MaskInfo
  104. _ = json.Unmarshal([]byte(banlistString), &banlist)
  105. var exceptlist map[string]MaskInfo
  106. _ = json.Unmarshal([]byte(exceptlistString), &exceptlist)
  107. var invitelist map[string]MaskInfo
  108. _ = json.Unmarshal([]byte(invitelistString), &invitelist)
  109. accountToUMode := make(map[string]modes.Mode)
  110. _ = json.Unmarshal([]byte(accountToUModeString), &accountToUMode)
  111. var settings ChannelSettings
  112. _ = json.Unmarshal([]byte(settingsString), &settings)
  113. info = RegisteredChannel{
  114. Name: name,
  115. RegisteredAt: time.Unix(0, regTimeInt).UTC(),
  116. Founder: founder,
  117. Topic: topic,
  118. TopicSetBy: topicSetBy,
  119. TopicSetTime: topicSetTime,
  120. Key: password,
  121. Modes: modeSlice,
  122. Bans: banlist,
  123. Excepts: exceptlist,
  124. Invites: invitelist,
  125. AccountToUMode: accountToUMode,
  126. UserLimit: int(userLimit),
  127. Settings: settings,
  128. Forward: forward,
  129. }
  130. return info, nil
  131. }