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.

accounts.go 60KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096
  1. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "bytes"
  6. "crypto/x509"
  7. "encoding/json"
  8. "fmt"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. "sync"
  13. "sync/atomic"
  14. "time"
  15. "unicode"
  16. "github.com/oragono/oragono/irc/connection_limits"
  17. "github.com/oragono/oragono/irc/email"
  18. "github.com/oragono/oragono/irc/migrations"
  19. "github.com/oragono/oragono/irc/modes"
  20. "github.com/oragono/oragono/irc/passwd"
  21. "github.com/oragono/oragono/irc/utils"
  22. "github.com/tidwall/buntdb"
  23. )
  24. const (
  25. keyAccountExists = "account.exists %s"
  26. keyAccountVerified = "account.verified %s"
  27. keyAccountUnregistered = "account.unregistered %s"
  28. keyAccountCallback = "account.callback %s"
  29. keyAccountVerificationCode = "account.verificationcode %s"
  30. keyAccountName = "account.name %s" // stores the 'preferred name' of the account, not casemapped
  31. keyAccountRegTime = "account.registered.time %s"
  32. keyAccountCredentials = "account.credentials %s"
  33. keyAccountAdditionalNicks = "account.additionalnicks %s"
  34. keyAccountSettings = "account.settings %s"
  35. keyAccountVHost = "account.vhost %s"
  36. keyCertToAccount = "account.creds.certfp %s"
  37. keyAccountChannels = "account.channels %s" // channels registered to the account
  38. keyAccountJoinedChannels = "account.joinedto %s" // channels a persistent client has joined
  39. keyAccountLastSeen = "account.lastseen %s"
  40. keyAccountModes = "account.modes %s" // user modes for the always-on client as a string
  41. keyAccountRealname = "account.realname %s" // client realname stored as string
  42. keyVHostQueueAcctToId = "vhostQueue %s"
  43. vhostRequestIdx = "vhostQueue"
  44. maxCertfpsPerAccount = 5
  45. )
  46. // everything about accounts is persistent; therefore, the database is the authoritative
  47. // source of truth for all account information. anything on the heap is just a cache
  48. type AccountManager struct {
  49. // XXX these are up here so they can be aligned to a 64-bit boundary, please forgive me
  50. // autoincrementing ID for vhost requests:
  51. vhostRequestID uint64
  52. vhostRequestPendingCount uint64
  53. sync.RWMutex // tier 2
  54. serialCacheUpdateMutex sync.Mutex // tier 3
  55. vHostUpdateMutex sync.Mutex // tier 3
  56. server *Server
  57. // track clients logged in to accounts
  58. accountToClients map[string][]*Client
  59. nickToAccount map[string]string
  60. skeletonToAccount map[string]string
  61. accountToMethod map[string]NickEnforcementMethod
  62. registerThrottle connection_limits.GenericThrottle
  63. }
  64. func (am *AccountManager) Initialize(server *Server) {
  65. am.accountToClients = make(map[string][]*Client)
  66. am.nickToAccount = make(map[string]string)
  67. am.skeletonToAccount = make(map[string]string)
  68. am.accountToMethod = make(map[string]NickEnforcementMethod)
  69. am.server = server
  70. config := server.Config()
  71. am.buildNickToAccountIndex(config)
  72. am.initVHostRequestQueue(config)
  73. am.createAlwaysOnClients(config)
  74. am.resetRegisterThrottle(config)
  75. }
  76. func (am *AccountManager) resetRegisterThrottle(config *Config) {
  77. am.Lock()
  78. defer am.Unlock()
  79. am.registerThrottle = connection_limits.GenericThrottle{
  80. Duration: config.Accounts.Registration.Throttling.Duration,
  81. Limit: config.Accounts.Registration.Throttling.MaxAttempts,
  82. }
  83. }
  84. func (am *AccountManager) touchRegisterThrottle() (throttled bool) {
  85. am.Lock()
  86. defer am.Unlock()
  87. throttled, _ = am.registerThrottle.Touch()
  88. return
  89. }
  90. func (am *AccountManager) createAlwaysOnClients(config *Config) {
  91. if config.Accounts.Multiclient.AlwaysOn == PersistentDisabled {
  92. return
  93. }
  94. verifiedPrefix := fmt.Sprintf(keyAccountVerified, "")
  95. am.serialCacheUpdateMutex.Lock()
  96. defer am.serialCacheUpdateMutex.Unlock()
  97. var accounts []string
  98. am.server.store.View(func(tx *buntdb.Tx) error {
  99. err := tx.AscendGreaterOrEqual("", verifiedPrefix, func(key, value string) bool {
  100. if !strings.HasPrefix(key, verifiedPrefix) {
  101. return false
  102. }
  103. account := strings.TrimPrefix(key, verifiedPrefix)
  104. accounts = append(accounts, account)
  105. return true
  106. })
  107. return err
  108. })
  109. for _, accountName := range accounts {
  110. account, err := am.LoadAccount(accountName)
  111. if err == nil && account.Verified &&
  112. persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, account.Settings.AlwaysOn) {
  113. am.server.AddAlwaysOnClient(
  114. account,
  115. am.loadChannels(accountName),
  116. am.loadLastSeen(accountName),
  117. am.loadModes(accountName),
  118. am.loadRealname(accountName),
  119. )
  120. }
  121. }
  122. }
  123. func (am *AccountManager) buildNickToAccountIndex(config *Config) {
  124. if !config.Accounts.NickReservation.Enabled {
  125. return
  126. }
  127. nickToAccount := make(map[string]string)
  128. skeletonToAccount := make(map[string]string)
  129. accountToMethod := make(map[string]NickEnforcementMethod)
  130. existsPrefix := fmt.Sprintf(keyAccountExists, "")
  131. am.serialCacheUpdateMutex.Lock()
  132. defer am.serialCacheUpdateMutex.Unlock()
  133. err := am.server.store.View(func(tx *buntdb.Tx) error {
  134. err := tx.AscendGreaterOrEqual("", existsPrefix, func(key, value string) bool {
  135. if !strings.HasPrefix(key, existsPrefix) {
  136. return false
  137. }
  138. account := strings.TrimPrefix(key, existsPrefix)
  139. if _, err := tx.Get(fmt.Sprintf(keyAccountVerified, account)); err == nil {
  140. nickToAccount[account] = account
  141. accountName, err := tx.Get(fmt.Sprintf(keyAccountName, account))
  142. if err != nil {
  143. am.server.logger.Error("internal", "missing account name for", account)
  144. } else {
  145. skeleton, _ := Skeleton(accountName)
  146. skeletonToAccount[skeleton] = account
  147. }
  148. }
  149. if rawNicks, err := tx.Get(fmt.Sprintf(keyAccountAdditionalNicks, account)); err == nil {
  150. additionalNicks := unmarshalReservedNicks(rawNicks)
  151. for _, nick := range additionalNicks {
  152. cfnick, _ := CasefoldName(nick)
  153. nickToAccount[cfnick] = account
  154. skeleton, _ := Skeleton(nick)
  155. skeletonToAccount[skeleton] = account
  156. }
  157. }
  158. if rawPrefs, err := tx.Get(fmt.Sprintf(keyAccountSettings, account)); err == nil {
  159. var prefs AccountSettings
  160. err := json.Unmarshal([]byte(rawPrefs), &prefs)
  161. if err == nil && prefs.NickEnforcement != NickEnforcementOptional {
  162. accountToMethod[account] = prefs.NickEnforcement
  163. } else if err != nil {
  164. am.server.logger.Error("internal", "corrupt account creds", account)
  165. }
  166. }
  167. return true
  168. })
  169. return err
  170. })
  171. if config.Accounts.NickReservation.Method == NickEnforcementStrict {
  172. unregisteredPrefix := fmt.Sprintf(keyAccountUnregistered, "")
  173. am.server.store.View(func(tx *buntdb.Tx) error {
  174. tx.AscendGreaterOrEqual("", unregisteredPrefix, func(key, value string) bool {
  175. if !strings.HasPrefix(key, unregisteredPrefix) {
  176. return false
  177. }
  178. account := strings.TrimPrefix(key, unregisteredPrefix)
  179. accountName := value
  180. nickToAccount[account] = account
  181. skeleton, _ := Skeleton(accountName)
  182. skeletonToAccount[skeleton] = account
  183. return true
  184. })
  185. return nil
  186. })
  187. }
  188. if err != nil {
  189. am.server.logger.Error("internal", "couldn't read reserved nicks", err.Error())
  190. } else {
  191. am.Lock()
  192. am.nickToAccount = nickToAccount
  193. am.skeletonToAccount = skeletonToAccount
  194. am.accountToMethod = accountToMethod
  195. am.Unlock()
  196. }
  197. }
  198. func (am *AccountManager) initVHostRequestQueue(config *Config) {
  199. if !config.Accounts.VHosts.Enabled {
  200. return
  201. }
  202. am.vHostUpdateMutex.Lock()
  203. defer am.vHostUpdateMutex.Unlock()
  204. // the db maps the account name to the autoincrementing integer ID of its request
  205. // create an numerically ordered index on ID, so we can list the oldest requests
  206. // finally, collect the integer id of the newest request and the total request count
  207. var total uint64
  208. var lastIDStr string
  209. err := am.server.store.Update(func(tx *buntdb.Tx) error {
  210. err := tx.CreateIndex(vhostRequestIdx, fmt.Sprintf(keyVHostQueueAcctToId, "*"), buntdb.IndexInt)
  211. if err != nil {
  212. return err
  213. }
  214. return tx.Descend(vhostRequestIdx, func(key, value string) bool {
  215. if lastIDStr == "" {
  216. lastIDStr = value
  217. }
  218. total++
  219. return true
  220. })
  221. })
  222. if err != nil {
  223. am.server.logger.Error("internal", "could not create vhost queue index", err.Error())
  224. }
  225. lastID, _ := strconv.ParseUint(lastIDStr, 10, 64)
  226. am.server.logger.Debug("services", fmt.Sprintf("vhost queue length is %d, autoincrementing id is %d", total, lastID))
  227. atomic.StoreUint64(&am.vhostRequestID, lastID)
  228. atomic.StoreUint64(&am.vhostRequestPendingCount, total)
  229. }
  230. func (am *AccountManager) NickToAccount(nick string) string {
  231. cfnick, err := CasefoldName(nick)
  232. if err != nil {
  233. return ""
  234. }
  235. skel, err := Skeleton(nick)
  236. if err != nil {
  237. return ""
  238. }
  239. am.RLock()
  240. defer am.RUnlock()
  241. account := am.nickToAccount[cfnick]
  242. if account != "" {
  243. return account
  244. }
  245. return am.skeletonToAccount[skel]
  246. }
  247. // given an account, combine stored enforcement method with the config settings
  248. // to compute the actual enforcement method
  249. func configuredEnforcementMethod(config *Config, storedMethod NickEnforcementMethod) (result NickEnforcementMethod) {
  250. if !config.Accounts.NickReservation.Enabled {
  251. return NickEnforcementNone
  252. }
  253. result = storedMethod
  254. // if they don't have a custom setting, or customization is disabled, use the default
  255. if result == NickEnforcementOptional || !config.Accounts.NickReservation.AllowCustomEnforcement {
  256. result = config.Accounts.NickReservation.Method
  257. }
  258. if result == NickEnforcementOptional {
  259. // enforcement was explicitly enabled neither in the config or by the user
  260. result = NickEnforcementNone
  261. }
  262. return
  263. }
  264. // Given a nick, looks up the account that owns it and the method (none/timeout/strict)
  265. // used to enforce ownership.
  266. func (am *AccountManager) EnforcementStatus(cfnick, skeleton string) (account string, method NickEnforcementMethod) {
  267. config := am.server.Config()
  268. if !config.Accounts.NickReservation.Enabled {
  269. return "", NickEnforcementNone
  270. }
  271. am.RLock()
  272. defer am.RUnlock()
  273. finalEnforcementMethod := func(account_ string) (result NickEnforcementMethod) {
  274. storedMethod := am.accountToMethod[account_]
  275. return configuredEnforcementMethod(config, storedMethod)
  276. }
  277. nickAccount := am.nickToAccount[cfnick]
  278. skelAccount := am.skeletonToAccount[skeleton]
  279. if nickAccount == "" && skelAccount == "" {
  280. return "", NickEnforcementNone
  281. } else if nickAccount != "" && (skelAccount == nickAccount || skelAccount == "") {
  282. return nickAccount, finalEnforcementMethod(nickAccount)
  283. } else if skelAccount != "" && nickAccount == "" {
  284. return skelAccount, finalEnforcementMethod(skelAccount)
  285. } else {
  286. // nickAccount != skelAccount and both are nonempty:
  287. // two people have competing claims on (this casefolding of) this nick!
  288. nickMethod := finalEnforcementMethod(nickAccount)
  289. skelMethod := finalEnforcementMethod(skelAccount)
  290. switch {
  291. case skelMethod == NickEnforcementNone:
  292. return nickAccount, nickMethod
  293. case nickMethod == NickEnforcementNone:
  294. return skelAccount, skelMethod
  295. default:
  296. // nobody can use this nick
  297. return "!", NickEnforcementStrict
  298. }
  299. }
  300. }
  301. // Sets a custom enforcement method for an account and stores it in the database.
  302. func (am *AccountManager) SetEnforcementStatus(account string, method NickEnforcementMethod) (finalSettings AccountSettings, err error) {
  303. config := am.server.Config()
  304. if !(config.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.AllowCustomEnforcement) {
  305. err = errFeatureDisabled
  306. return
  307. }
  308. setter := func(in AccountSettings) (out AccountSettings, err error) {
  309. out = in
  310. out.NickEnforcement = method
  311. return out, nil
  312. }
  313. _, err = am.ModifyAccountSettings(account, setter)
  314. if err != nil {
  315. return
  316. }
  317. // this update of the data plane is racey, but it's probably fine
  318. am.Lock()
  319. defer am.Unlock()
  320. if method == NickEnforcementOptional {
  321. delete(am.accountToMethod, account)
  322. } else {
  323. am.accountToMethod[account] = method
  324. }
  325. return
  326. }
  327. func (am *AccountManager) AccountToClients(account string) (result []*Client) {
  328. cfaccount, err := CasefoldName(account)
  329. if err != nil {
  330. return
  331. }
  332. am.RLock()
  333. defer am.RUnlock()
  334. return am.accountToClients[cfaccount]
  335. }
  336. func (am *AccountManager) Register(client *Client, account string, callbackNamespace string, callbackValue string, passphrase string, certfp string) error {
  337. casefoldedAccount, err := CasefoldName(account)
  338. skeleton, skerr := Skeleton(account)
  339. if err != nil || skerr != nil || account == "" || account == "*" {
  340. return errAccountCreation
  341. }
  342. if restrictedCasefoldedNicks.Has(casefoldedAccount) || restrictedSkeletons.Has(skeleton) {
  343. return errAccountAlreadyRegistered
  344. }
  345. config := am.server.Config()
  346. // final "is registration allowed" check:
  347. if !(config.Accounts.Registration.Enabled || callbackNamespace == "admin") || am.server.Defcon() <= 4 {
  348. return errFeatureDisabled
  349. }
  350. if client != nil && client.Account() != "" {
  351. return errAccountAlreadyLoggedIn
  352. }
  353. if client != nil && am.touchRegisterThrottle() {
  354. am.server.logger.Warning("accounts", "global registration throttle exceeded by client", client.Nick())
  355. return errLimitExceeded
  356. }
  357. // if nick reservation is enabled, don't let people reserve nicknames
  358. // that they would not be eligible to take, e.g.,
  359. // 1. a nickname that someone else is currently holding
  360. // 2. a nickname confusable with an existing reserved nickname
  361. // this has a lot of weird edge cases because of force-guest-format
  362. // and the possibility of registering a nickname on an "unregistered connection"
  363. // (i.e., pre-handshake).
  364. if client != nil && config.Accounts.NickReservation.Enabled {
  365. _, nickAcquireError, _ := am.server.clients.SetNick(client, nil, account, true)
  366. if !(nickAcquireError == nil || nickAcquireError == errNoop) {
  367. return errAccountMustHoldNick
  368. }
  369. }
  370. // can't register a guest nickname
  371. if config.Accounts.NickReservation.guestRegexpFolded.MatchString(casefoldedAccount) {
  372. return errAccountAlreadyRegistered
  373. }
  374. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  375. unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
  376. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  377. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  378. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  379. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  380. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  381. certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
  382. var creds AccountCredentials
  383. creds.Version = 1
  384. err = creds.SetPassphrase(passphrase, am.server.Config().Accounts.Registration.BcryptCost)
  385. if err != nil {
  386. return err
  387. }
  388. creds.AddCertfp(certfp)
  389. credStr, err := creds.Serialize()
  390. if err != nil {
  391. return err
  392. }
  393. registeredTimeStr := strconv.FormatInt(time.Now().UnixNano(), 10)
  394. callbackSpec := fmt.Sprintf("%s:%s", callbackNamespace, callbackValue)
  395. var setOptions *buntdb.SetOptions
  396. ttl := time.Duration(config.Accounts.Registration.VerifyTimeout)
  397. if ttl != 0 {
  398. setOptions = &buntdb.SetOptions{Expires: true, TTL: ttl}
  399. }
  400. err = func() error {
  401. am.serialCacheUpdateMutex.Lock()
  402. defer am.serialCacheUpdateMutex.Unlock()
  403. // can't register an account with the same name as a registered nick
  404. if am.NickToAccount(account) != "" {
  405. return errAccountAlreadyRegistered
  406. }
  407. return am.server.store.Update(func(tx *buntdb.Tx) error {
  408. if _, err := tx.Get(unregisteredKey); err == nil {
  409. return errAccountAlreadyUnregistered
  410. }
  411. _, err = am.loadRawAccount(tx, casefoldedAccount)
  412. if err != errAccountDoesNotExist {
  413. return errAccountAlreadyRegistered
  414. }
  415. if certfp != "" {
  416. // make sure certfp doesn't already exist because that'd be silly
  417. _, err := tx.Get(certFPKey)
  418. if err != buntdb.ErrNotFound {
  419. return errCertfpAlreadyExists
  420. }
  421. }
  422. tx.Set(accountKey, "1", setOptions)
  423. tx.Set(accountNameKey, account, setOptions)
  424. tx.Set(registeredTimeKey, registeredTimeStr, setOptions)
  425. tx.Set(credentialsKey, credStr, setOptions)
  426. tx.Set(callbackKey, callbackSpec, setOptions)
  427. if certfp != "" {
  428. tx.Set(certFPKey, casefoldedAccount, setOptions)
  429. }
  430. return nil
  431. })
  432. }()
  433. if err != nil {
  434. return err
  435. }
  436. code, err := am.dispatchCallback(client, account, callbackNamespace, callbackValue)
  437. if err != nil {
  438. am.Unregister(casefoldedAccount, true)
  439. return errCallbackFailed
  440. } else {
  441. return am.server.store.Update(func(tx *buntdb.Tx) error {
  442. _, _, err = tx.Set(verificationCodeKey, code, setOptions)
  443. return err
  444. })
  445. }
  446. }
  447. // validatePassphrase checks whether a passphrase is allowed by our rules
  448. func validatePassphrase(passphrase string) error {
  449. // sanity check the length
  450. if len(passphrase) == 0 || len(passphrase) > 300 {
  451. return errAccountBadPassphrase
  452. }
  453. // we use * as a placeholder in some places, if it's gotten this far then fail
  454. if passphrase == "*" {
  455. return errAccountBadPassphrase
  456. }
  457. // for now, just enforce that spaces are not allowed
  458. for _, r := range passphrase {
  459. if unicode.IsSpace(r) {
  460. return errAccountBadPassphrase
  461. }
  462. }
  463. return nil
  464. }
  465. // changes the password for an account
  466. func (am *AccountManager) setPassword(account string, password string, hasPrivs bool) (err error) {
  467. cfAccount, err := CasefoldName(account)
  468. if err != nil {
  469. return errAccountDoesNotExist
  470. }
  471. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  472. var credStr string
  473. am.server.store.View(func(tx *buntdb.Tx) error {
  474. // no need to check verification status here or below;
  475. // you either need to be auth'ed to the account or be an oper to do this
  476. credStr, err = tx.Get(credKey)
  477. return nil
  478. })
  479. if err != nil {
  480. return errAccountDoesNotExist
  481. }
  482. var creds AccountCredentials
  483. err = json.Unmarshal([]byte(credStr), &creds)
  484. if err != nil {
  485. return err
  486. }
  487. if !hasPrivs && creds.Empty() {
  488. return errCredsExternallyManaged
  489. }
  490. err = creds.SetPassphrase(password, am.server.Config().Accounts.Registration.BcryptCost)
  491. if err != nil {
  492. return err
  493. }
  494. if creds.Empty() && !hasPrivs {
  495. return errEmptyCredentials
  496. }
  497. newCredStr, err := creds.Serialize()
  498. if err != nil {
  499. return err
  500. }
  501. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  502. curCredStr, err := tx.Get(credKey)
  503. if credStr != curCredStr {
  504. return errCASFailed
  505. }
  506. _, _, err = tx.Set(credKey, newCredStr, nil)
  507. return err
  508. })
  509. return err
  510. }
  511. func (am *AccountManager) saveChannels(account string, channels []string) {
  512. channelsStr := strings.Join(channels, ",")
  513. key := fmt.Sprintf(keyAccountJoinedChannels, account)
  514. am.server.store.Update(func(tx *buntdb.Tx) error {
  515. tx.Set(key, channelsStr, nil)
  516. return nil
  517. })
  518. }
  519. func (am *AccountManager) loadChannels(account string) (channels []string) {
  520. key := fmt.Sprintf(keyAccountJoinedChannels, account)
  521. var channelsStr string
  522. am.server.store.View(func(tx *buntdb.Tx) error {
  523. channelsStr, _ = tx.Get(key)
  524. return nil
  525. })
  526. if channelsStr != "" {
  527. return strings.Split(channelsStr, ",")
  528. }
  529. return
  530. }
  531. func (am *AccountManager) saveModes(account string, uModes modes.Modes) {
  532. modeStr := uModes.String()
  533. key := fmt.Sprintf(keyAccountModes, account)
  534. am.server.store.Update(func(tx *buntdb.Tx) error {
  535. tx.Set(key, modeStr, nil)
  536. return nil
  537. })
  538. }
  539. func (am *AccountManager) loadModes(account string) (uModes modes.Modes) {
  540. key := fmt.Sprintf(keyAccountModes, account)
  541. var modeStr string
  542. am.server.store.View(func(tx *buntdb.Tx) error {
  543. modeStr, _ = tx.Get(key)
  544. return nil
  545. })
  546. for _, m := range modeStr {
  547. uModes = append(uModes, modes.Mode(m))
  548. }
  549. return
  550. }
  551. func (am *AccountManager) saveLastSeen(account string, lastSeen map[string]time.Time) {
  552. key := fmt.Sprintf(keyAccountLastSeen, account)
  553. var val string
  554. if len(lastSeen) != 0 {
  555. text, _ := json.Marshal(lastSeen)
  556. val = string(text)
  557. }
  558. am.server.store.Update(func(tx *buntdb.Tx) error {
  559. if val != "" {
  560. tx.Set(key, val, nil)
  561. } else {
  562. tx.Delete(key)
  563. }
  564. return nil
  565. })
  566. }
  567. func (am *AccountManager) loadLastSeen(account string) (lastSeen map[string]time.Time) {
  568. key := fmt.Sprintf(keyAccountLastSeen, account)
  569. var lsText string
  570. am.server.store.Update(func(tx *buntdb.Tx) error {
  571. lsText, _ = tx.Get(key)
  572. return nil
  573. })
  574. if lsText == "" {
  575. return nil
  576. }
  577. err := json.Unmarshal([]byte(lsText), &lastSeen)
  578. if err != nil {
  579. return nil
  580. }
  581. return
  582. }
  583. func (am *AccountManager) saveRealname(account string, realname string) {
  584. key := fmt.Sprintf(keyAccountRealname, account)
  585. am.server.store.Update(func(tx *buntdb.Tx) error {
  586. if realname != "" {
  587. tx.Set(key, realname, nil)
  588. } else {
  589. tx.Delete(key)
  590. }
  591. return nil
  592. })
  593. }
  594. func (am *AccountManager) loadRealname(account string) (realname string) {
  595. key := fmt.Sprintf(keyAccountRealname, account)
  596. am.server.store.Update(func(tx *buntdb.Tx) error {
  597. realname, _ = tx.Get(key)
  598. return nil
  599. })
  600. return
  601. }
  602. func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasPrivs bool) (err error) {
  603. certfp, err = utils.NormalizeCertfp(certfp)
  604. if err != nil {
  605. return err
  606. }
  607. cfAccount, err := CasefoldName(account)
  608. if err != nil {
  609. return errAccountDoesNotExist
  610. }
  611. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  612. var credStr string
  613. am.server.store.View(func(tx *buntdb.Tx) error {
  614. credStr, err = tx.Get(credKey)
  615. return nil
  616. })
  617. if err != nil {
  618. return errAccountDoesNotExist
  619. }
  620. var creds AccountCredentials
  621. err = json.Unmarshal([]byte(credStr), &creds)
  622. if err != nil {
  623. return err
  624. }
  625. if !hasPrivs && creds.Empty() {
  626. return errCredsExternallyManaged
  627. }
  628. if add {
  629. err = creds.AddCertfp(certfp)
  630. } else {
  631. err = creds.RemoveCertfp(certfp)
  632. }
  633. if err != nil {
  634. return err
  635. }
  636. if creds.Empty() && !hasPrivs {
  637. return errEmptyCredentials
  638. }
  639. newCredStr, err := creds.Serialize()
  640. if err != nil {
  641. return err
  642. }
  643. certfpKey := fmt.Sprintf(keyCertToAccount, certfp)
  644. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  645. curCredStr, err := tx.Get(credKey)
  646. if credStr != curCredStr {
  647. return errCASFailed
  648. }
  649. if add {
  650. _, err = tx.Get(certfpKey)
  651. if err != buntdb.ErrNotFound {
  652. return errCertfpAlreadyExists
  653. }
  654. tx.Set(certfpKey, cfAccount, nil)
  655. } else {
  656. tx.Delete(certfpKey)
  657. }
  658. _, _, err = tx.Set(credKey, newCredStr, nil)
  659. return err
  660. })
  661. return err
  662. }
  663. func (am *AccountManager) dispatchCallback(client *Client, account string, callbackNamespace string, callbackValue string) (string, error) {
  664. if callbackNamespace == "*" || callbackNamespace == "none" || callbackNamespace == "admin" {
  665. return "", nil
  666. } else if callbackNamespace == "mailto" {
  667. return am.dispatchMailtoCallback(client, account, callbackValue)
  668. } else {
  669. return "", fmt.Errorf("Callback not implemented: %s", callbackNamespace)
  670. }
  671. }
  672. func (am *AccountManager) dispatchMailtoCallback(client *Client, account string, callbackValue string) (code string, err error) {
  673. config := am.server.Config().Accounts.Registration.EmailVerification
  674. code = utils.GenerateSecretToken()
  675. subject := config.VerifyMessageSubject
  676. if subject == "" {
  677. subject = fmt.Sprintf(client.t("Verify your account on %s"), am.server.name)
  678. }
  679. var message bytes.Buffer
  680. fmt.Fprintf(&message, "From: %s\r\n", config.Sender)
  681. fmt.Fprintf(&message, "To: %s\r\n", callbackValue)
  682. if config.DKIM.Domain != "" {
  683. fmt.Fprintf(&message, "Message-ID: <%s@%s>\r\n", utils.GenerateSecretKey(), config.DKIM.Domain)
  684. }
  685. fmt.Fprintf(&message, "Date: %s\r\n", time.Now().UTC().Format(time.RFC1123Z))
  686. fmt.Fprintf(&message, "Subject: %s\r\n", subject)
  687. message.WriteString("\r\n") // blank line: end headers, begin message body
  688. fmt.Fprintf(&message, client.t("Account: %s"), account)
  689. message.WriteString("\r\n")
  690. fmt.Fprintf(&message, client.t("Verification code: %s"), code)
  691. message.WriteString("\r\n")
  692. message.WriteString("\r\n")
  693. message.WriteString(client.t("To verify your account, issue the following command:"))
  694. message.WriteString("\r\n")
  695. fmt.Fprintf(&message, "/MSG NickServ VERIFY %s %s\r\n", account, code)
  696. err = email.SendMail(config, callbackValue, message.Bytes())
  697. if err != nil {
  698. am.server.logger.Error("internal", "Failed to dispatch e-mail to", callbackValue, err.Error())
  699. }
  700. return
  701. }
  702. func (am *AccountManager) Verify(client *Client, account string, code string) error {
  703. casefoldedAccount, err := CasefoldName(account)
  704. var skeleton string
  705. if err != nil || account == "" || account == "*" {
  706. return errAccountVerificationFailed
  707. }
  708. if client != nil && client.Account() != "" {
  709. return errAccountAlreadyLoggedIn
  710. }
  711. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  712. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  713. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  714. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  715. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  716. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  717. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  718. var raw rawClientAccount
  719. func() {
  720. am.serialCacheUpdateMutex.Lock()
  721. defer am.serialCacheUpdateMutex.Unlock()
  722. // do a final check for confusability (in case someone already verified
  723. // a confusable identifier):
  724. var unfoldedName string
  725. err = am.server.store.View(func(tx *buntdb.Tx) error {
  726. unfoldedName, err = tx.Get(accountNameKey)
  727. return err
  728. })
  729. if err != nil {
  730. err = errAccountDoesNotExist
  731. return
  732. }
  733. skeleton, err = Skeleton(unfoldedName)
  734. if err != nil {
  735. err = errAccountDoesNotExist
  736. return
  737. }
  738. err = func() error {
  739. am.RLock()
  740. defer am.RUnlock()
  741. if _, ok := am.skeletonToAccount[skeleton]; ok {
  742. return errConfusableIdentifier
  743. }
  744. return nil
  745. }()
  746. if err != nil {
  747. return
  748. }
  749. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  750. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  751. if err == errAccountDoesNotExist {
  752. return errAccountDoesNotExist
  753. } else if err != nil {
  754. return errAccountVerificationFailed
  755. } else if raw.Verified {
  756. return errAccountAlreadyVerified
  757. }
  758. // actually verify the code
  759. // a stored code of "" means a none callback / no code required
  760. success := false
  761. storedCode, err := tx.Get(verificationCodeKey)
  762. if err == nil {
  763. // this is probably unnecessary
  764. if storedCode == "" || utils.SecretTokensMatch(storedCode, code) {
  765. success = true
  766. }
  767. }
  768. if !success {
  769. return errAccountVerificationInvalidCode
  770. }
  771. // verify the account
  772. tx.Set(verifiedKey, "1", nil)
  773. // don't need the code anymore
  774. tx.Delete(verificationCodeKey)
  775. // re-set all other keys, removing the TTL
  776. tx.Set(accountKey, "1", nil)
  777. tx.Set(accountNameKey, raw.Name, nil)
  778. tx.Set(registeredTimeKey, raw.RegisteredAt, nil)
  779. tx.Set(callbackKey, raw.Callback, nil)
  780. tx.Set(credentialsKey, raw.Credentials, nil)
  781. var creds AccountCredentials
  782. // XXX we shouldn't do (de)serialization inside the txn,
  783. // but this is like 2 usec on my system
  784. json.Unmarshal([]byte(raw.Credentials), &creds)
  785. for _, cert := range creds.Certfps {
  786. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  787. tx.Set(certFPKey, casefoldedAccount, nil)
  788. }
  789. return nil
  790. })
  791. if err == nil {
  792. am.Lock()
  793. am.nickToAccount[casefoldedAccount] = casefoldedAccount
  794. am.skeletonToAccount[skeleton] = casefoldedAccount
  795. am.Unlock()
  796. }
  797. }()
  798. if err != nil {
  799. return err
  800. }
  801. nick := "[server admin]"
  802. if client != nil {
  803. nick = client.Nick()
  804. }
  805. am.server.logger.Info("accounts", "client", nick, "registered account", account)
  806. raw.Verified = true
  807. clientAccount, err := am.deserializeRawAccount(raw, casefoldedAccount)
  808. if err != nil {
  809. return err
  810. }
  811. if client != nil {
  812. am.Login(client, clientAccount)
  813. if client.AlwaysOn() {
  814. client.markDirty(IncludeRealname)
  815. }
  816. }
  817. // we may need to do nick enforcement here:
  818. _, method := am.EnforcementStatus(casefoldedAccount, skeleton)
  819. if method == NickEnforcementStrict {
  820. currentClient := am.server.clients.Get(casefoldedAccount)
  821. if currentClient != nil && currentClient != client && currentClient.Account() != casefoldedAccount {
  822. am.server.RandomlyRename(currentClient)
  823. }
  824. }
  825. return nil
  826. }
  827. // register and verify an account, for internal use
  828. func (am *AccountManager) SARegister(account, passphrase string) (err error) {
  829. err = am.Register(nil, account, "admin", "", passphrase, "")
  830. if err == nil {
  831. err = am.Verify(nil, account, "")
  832. }
  833. return
  834. }
  835. func marshalReservedNicks(nicks []string) string {
  836. return strings.Join(nicks, ",")
  837. }
  838. func unmarshalReservedNicks(nicks string) (result []string) {
  839. if nicks == "" {
  840. return
  841. }
  842. return strings.Split(nicks, ",")
  843. }
  844. func (am *AccountManager) SetNickReserved(client *Client, nick string, saUnreserve bool, reserve bool) error {
  845. cfnick, err := CasefoldName(nick)
  846. skeleton, skerr := Skeleton(nick)
  847. // garbage nick, or garbage options, or disabled
  848. nrconfig := am.server.Config().Accounts.NickReservation
  849. if err != nil || skerr != nil || cfnick == "" || (reserve && saUnreserve) || !nrconfig.Enabled {
  850. return errAccountNickReservationFailed
  851. }
  852. // the cache is in sync with the DB while we hold serialCacheUpdateMutex
  853. am.serialCacheUpdateMutex.Lock()
  854. defer am.serialCacheUpdateMutex.Unlock()
  855. // find the affected account, which is usually the client's:
  856. account := client.Account()
  857. if saUnreserve {
  858. // unless this is a sadrop:
  859. account := func() string {
  860. am.RLock()
  861. defer am.RUnlock()
  862. return am.nickToAccount[cfnick]
  863. }()
  864. if account == "" {
  865. // nothing to do
  866. return nil
  867. }
  868. }
  869. if account == "" {
  870. return errAccountNotLoggedIn
  871. }
  872. am.Lock()
  873. accountForNick := am.nickToAccount[cfnick]
  874. var accountForSkeleton string
  875. if reserve {
  876. accountForSkeleton = am.skeletonToAccount[skeleton]
  877. }
  878. am.Unlock()
  879. if reserve && (accountForNick != "" || accountForSkeleton != "") {
  880. return errNicknameReserved
  881. } else if !reserve && !saUnreserve && accountForNick != account {
  882. return errNicknameReserved
  883. } else if !reserve && cfnick == account {
  884. return errAccountCantDropPrimaryNick
  885. }
  886. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, account)
  887. unverifiedAccountKey := fmt.Sprintf(keyAccountExists, cfnick)
  888. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  889. if reserve {
  890. // unverified accounts don't show up in NickToAccount yet (which is intentional),
  891. // however you shouldn't be able to reserve a nick out from under them
  892. _, err := tx.Get(unverifiedAccountKey)
  893. if err == nil {
  894. return errNicknameReserved
  895. }
  896. }
  897. rawNicks, err := tx.Get(nicksKey)
  898. if err != nil && err != buntdb.ErrNotFound {
  899. return err
  900. }
  901. nicks := unmarshalReservedNicks(rawNicks)
  902. if reserve {
  903. if len(nicks) >= nrconfig.AdditionalNickLimit {
  904. return errAccountTooManyNicks
  905. }
  906. nicks = append(nicks, nick)
  907. } else {
  908. // compute (original reserved nicks) minus cfnick
  909. var newNicks []string
  910. for _, reservedNick := range nicks {
  911. cfreservednick, _ := CasefoldName(reservedNick)
  912. if cfreservednick != cfnick {
  913. newNicks = append(newNicks, reservedNick)
  914. } else {
  915. // found the original, unfolded version of the nick we're dropping;
  916. // recompute the true skeleton from it
  917. skeleton, _ = Skeleton(reservedNick)
  918. }
  919. }
  920. nicks = newNicks
  921. }
  922. marshaledNicks := marshalReservedNicks(nicks)
  923. _, _, err = tx.Set(nicksKey, string(marshaledNicks), nil)
  924. return err
  925. })
  926. if err == errAccountTooManyNicks || err == errNicknameReserved {
  927. return err
  928. } else if err != nil {
  929. return errAccountNickReservationFailed
  930. }
  931. // success
  932. am.Lock()
  933. defer am.Unlock()
  934. if reserve {
  935. am.nickToAccount[cfnick] = account
  936. am.skeletonToAccount[skeleton] = account
  937. } else {
  938. delete(am.nickToAccount, cfnick)
  939. delete(am.skeletonToAccount, skeleton)
  940. }
  941. return nil
  942. }
  943. func (am *AccountManager) checkPassphrase(accountName, passphrase string) (account ClientAccount, err error) {
  944. account, err = am.LoadAccount(accountName)
  945. if err != nil {
  946. return
  947. }
  948. if !account.Verified {
  949. err = errAccountUnverified
  950. return
  951. }
  952. switch account.Credentials.Version {
  953. case 0:
  954. err = am.checkLegacyPassphrase(migrations.CheckOragonoPassphraseV0, accountName, account.Credentials.PassphraseHash, passphrase)
  955. case 1:
  956. if passwd.CompareHashAndPassword(account.Credentials.PassphraseHash, []byte(passphrase)) != nil {
  957. err = errAccountInvalidCredentials
  958. }
  959. case -1:
  960. err = am.checkLegacyPassphrase(migrations.CheckAthemePassphrase, accountName, account.Credentials.PassphraseHash, passphrase)
  961. case -2:
  962. err = am.checkLegacyPassphrase(migrations.CheckAnopePassphrase, accountName, account.Credentials.PassphraseHash, passphrase)
  963. default:
  964. err = errAccountInvalidCredentials
  965. }
  966. return
  967. }
  968. func (am *AccountManager) checkLegacyPassphrase(check migrations.PassphraseCheck, account string, hash []byte, passphrase string) (err error) {
  969. err = check(hash, []byte(passphrase))
  970. if err != nil {
  971. if err == migrations.ErrHashInvalid {
  972. am.server.logger.Error("internal", "invalid legacy credentials for account", account)
  973. }
  974. return errAccountInvalidCredentials
  975. }
  976. // re-hash the passphrase with the latest algorithm
  977. err = am.setPassword(account, passphrase, true)
  978. if err != nil {
  979. am.server.logger.Error("internal", "could not upgrade user password", err.Error())
  980. }
  981. return nil
  982. }
  983. func (am *AccountManager) loadWithAutocreation(accountName string, autocreate bool) (account ClientAccount, err error) {
  984. account, err = am.LoadAccount(accountName)
  985. if err == errAccountDoesNotExist && autocreate {
  986. err = am.SARegister(accountName, "")
  987. if err != nil {
  988. return
  989. }
  990. account, err = am.LoadAccount(accountName)
  991. }
  992. return
  993. }
  994. func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) (err error) {
  995. // XXX check this now, so we don't allow a redundant login for an always-on client
  996. // even for a brief period. the other potential source of nick-account conflicts
  997. // is from force-nick-equals-account, but those will be caught later by
  998. // fixupNickEqualsAccount and if there is a conflict, they will be logged out.
  999. if client.registered {
  1000. if clientAlready := am.server.clients.Get(accountName); clientAlready != nil && clientAlready.AlwaysOn() {
  1001. return errNickAccountMismatch
  1002. }
  1003. }
  1004. if throttled, remainingTime := client.checkLoginThrottle(); throttled {
  1005. return &ThrottleError{remainingTime}
  1006. }
  1007. var account ClientAccount
  1008. defer func() {
  1009. if err == nil {
  1010. am.Login(client, account)
  1011. }
  1012. }()
  1013. config := am.server.Config()
  1014. if config.Accounts.AuthScript.Enabled {
  1015. var output AuthScriptOutput
  1016. output, err = CheckAuthScript(am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
  1017. AuthScriptInput{AccountName: accountName, Passphrase: passphrase, IP: client.IP().String()})
  1018. if err != nil {
  1019. am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
  1020. } else if output.Success {
  1021. if output.AccountName != "" {
  1022. accountName = output.AccountName
  1023. }
  1024. account, err = am.loadWithAutocreation(accountName, config.Accounts.AuthScript.Autocreate)
  1025. return
  1026. }
  1027. }
  1028. account, err = am.checkPassphrase(accountName, passphrase)
  1029. return err
  1030. }
  1031. // AllNicks returns the uncasefolded nicknames for all accounts, including additional (grouped) nicks.
  1032. func (am *AccountManager) AllNicks() (result []string) {
  1033. accountNamePrefix := fmt.Sprintf(keyAccountName, "")
  1034. accountAdditionalNicksPrefix := fmt.Sprintf(keyAccountAdditionalNicks, "")
  1035. am.server.store.View(func(tx *buntdb.Tx) error {
  1036. // Account names
  1037. err := tx.AscendGreaterOrEqual("", accountNamePrefix, func(key, value string) bool {
  1038. if !strings.HasPrefix(key, accountNamePrefix) {
  1039. return false
  1040. }
  1041. result = append(result, value)
  1042. return true
  1043. })
  1044. if err != nil {
  1045. return err
  1046. }
  1047. // Additional nicks
  1048. return tx.AscendGreaterOrEqual("", accountAdditionalNicksPrefix, func(key, value string) bool {
  1049. if !strings.HasPrefix(key, accountAdditionalNicksPrefix) {
  1050. return false
  1051. }
  1052. additionalNicks := unmarshalReservedNicks(value)
  1053. for _, additionalNick := range additionalNicks {
  1054. result = append(result, additionalNick)
  1055. }
  1056. return true
  1057. })
  1058. })
  1059. sort.Strings(result)
  1060. return
  1061. }
  1062. func (am *AccountManager) LoadAccount(accountName string) (result ClientAccount, err error) {
  1063. casefoldedAccount, err := CasefoldName(accountName)
  1064. if err != nil {
  1065. err = errAccountDoesNotExist
  1066. return
  1067. }
  1068. var raw rawClientAccount
  1069. am.server.store.View(func(tx *buntdb.Tx) error {
  1070. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  1071. return nil
  1072. })
  1073. if err != nil {
  1074. return
  1075. }
  1076. result, err = am.deserializeRawAccount(raw, casefoldedAccount)
  1077. return
  1078. }
  1079. // look up the unfolded version of an account name, possibly after deletion
  1080. func (am *AccountManager) AccountToAccountName(account string) (result string) {
  1081. casefoldedAccount, err := CasefoldName(account)
  1082. if err != nil {
  1083. return
  1084. }
  1085. unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
  1086. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1087. am.server.store.View(func(tx *buntdb.Tx) error {
  1088. if name, err := tx.Get(accountNameKey); err == nil {
  1089. result = name
  1090. return nil
  1091. }
  1092. if name, err := tx.Get(unregisteredKey); err == nil {
  1093. result = name
  1094. }
  1095. return nil
  1096. })
  1097. return
  1098. }
  1099. func (am *AccountManager) deserializeRawAccount(raw rawClientAccount, cfName string) (result ClientAccount, err error) {
  1100. result.Name = raw.Name
  1101. result.NameCasefolded = cfName
  1102. regTimeInt, _ := strconv.ParseInt(raw.RegisteredAt, 10, 64)
  1103. result.RegisteredAt = time.Unix(0, regTimeInt).UTC()
  1104. e := json.Unmarshal([]byte(raw.Credentials), &result.Credentials)
  1105. if e != nil {
  1106. am.server.logger.Error("internal", "could not unmarshal credentials", e.Error())
  1107. err = errAccountDoesNotExist
  1108. return
  1109. }
  1110. result.AdditionalNicks = unmarshalReservedNicks(raw.AdditionalNicks)
  1111. result.Verified = raw.Verified
  1112. if raw.VHost != "" {
  1113. e := json.Unmarshal([]byte(raw.VHost), &result.VHost)
  1114. if e != nil {
  1115. am.server.logger.Warning("internal", "could not unmarshal vhost for account", result.Name, e.Error())
  1116. // pretend they have no vhost and move on
  1117. }
  1118. }
  1119. if raw.Settings != "" {
  1120. e := json.Unmarshal([]byte(raw.Settings), &result.Settings)
  1121. if e != nil {
  1122. am.server.logger.Warning("internal", "could not unmarshal settings for account", result.Name, e.Error())
  1123. }
  1124. }
  1125. return
  1126. }
  1127. func (am *AccountManager) loadRawAccount(tx *buntdb.Tx, casefoldedAccount string) (result rawClientAccount, err error) {
  1128. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  1129. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1130. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  1131. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  1132. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  1133. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  1134. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  1135. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  1136. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1137. _, e := tx.Get(accountKey)
  1138. if e == buntdb.ErrNotFound {
  1139. err = errAccountDoesNotExist
  1140. return
  1141. }
  1142. result.Name, _ = tx.Get(accountNameKey)
  1143. result.RegisteredAt, _ = tx.Get(registeredTimeKey)
  1144. result.Credentials, _ = tx.Get(credentialsKey)
  1145. result.Callback, _ = tx.Get(callbackKey)
  1146. result.AdditionalNicks, _ = tx.Get(nicksKey)
  1147. result.VHost, _ = tx.Get(vhostKey)
  1148. result.Settings, _ = tx.Get(settingsKey)
  1149. if _, e = tx.Get(verifiedKey); e == nil {
  1150. result.Verified = true
  1151. }
  1152. return
  1153. }
  1154. func (am *AccountManager) Suspend(accountName string) (err error) {
  1155. account, err := CasefoldName(accountName)
  1156. if err != nil {
  1157. return errAccountDoesNotExist
  1158. }
  1159. existsKey := fmt.Sprintf(keyAccountExists, account)
  1160. verifiedKey := fmt.Sprintf(keyAccountVerified, account)
  1161. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1162. _, err := tx.Get(existsKey)
  1163. if err != nil {
  1164. return errAccountDoesNotExist
  1165. }
  1166. _, err = tx.Delete(verifiedKey)
  1167. return err
  1168. })
  1169. if err == errAccountDoesNotExist {
  1170. return err
  1171. } else if err != nil {
  1172. am.server.logger.Error("internal", "couldn't persist suspension", account, err.Error())
  1173. } // keep going
  1174. am.Lock()
  1175. clients := am.accountToClients[account]
  1176. delete(am.accountToClients, account)
  1177. am.Unlock()
  1178. am.killClients(clients)
  1179. return nil
  1180. }
  1181. func (am *AccountManager) killClients(clients []*Client) {
  1182. for _, client := range clients {
  1183. client.Logout()
  1184. client.Quit(client.t("You are no longer authorized to be on this server"), nil)
  1185. client.destroy(nil)
  1186. }
  1187. }
  1188. func (am *AccountManager) Unsuspend(account string) (err error) {
  1189. cfaccount, err := CasefoldName(account)
  1190. if err != nil {
  1191. return errAccountDoesNotExist
  1192. }
  1193. existsKey := fmt.Sprintf(keyAccountExists, cfaccount)
  1194. verifiedKey := fmt.Sprintf(keyAccountVerified, cfaccount)
  1195. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1196. _, err := tx.Get(existsKey)
  1197. if err != nil {
  1198. return errAccountDoesNotExist
  1199. }
  1200. tx.Set(verifiedKey, "1", nil)
  1201. return nil
  1202. })
  1203. if err != nil {
  1204. return errAccountDoesNotExist
  1205. }
  1206. return nil
  1207. }
  1208. func (am *AccountManager) Unregister(account string, erase bool) error {
  1209. config := am.server.Config()
  1210. casefoldedAccount, err := CasefoldName(account)
  1211. if err != nil {
  1212. return errAccountDoesNotExist
  1213. }
  1214. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  1215. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1216. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  1217. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  1218. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  1219. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  1220. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  1221. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  1222. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1223. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  1224. vhostQueueKey := fmt.Sprintf(keyVHostQueueAcctToId, casefoldedAccount)
  1225. channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
  1226. joinedChannelsKey := fmt.Sprintf(keyAccountJoinedChannels, casefoldedAccount)
  1227. lastSeenKey := fmt.Sprintf(keyAccountLastSeen, casefoldedAccount)
  1228. unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
  1229. modesKey := fmt.Sprintf(keyAccountModes, casefoldedAccount)
  1230. realnameKey := fmt.Sprintf(keyAccountRealname, casefoldedAccount)
  1231. var clients []*Client
  1232. defer func() {
  1233. am.killClients(clients)
  1234. }()
  1235. var registeredChannels []string
  1236. // on our way out, unregister all the account's channels and delete them from the db
  1237. defer func() {
  1238. for _, channelName := range registeredChannels {
  1239. err := am.server.channels.SetUnregistered(channelName, casefoldedAccount)
  1240. if err != nil {
  1241. am.server.logger.Error("internal", "couldn't unregister channel", channelName, err.Error())
  1242. }
  1243. }
  1244. }()
  1245. var credText string
  1246. var rawNicks string
  1247. am.serialCacheUpdateMutex.Lock()
  1248. defer am.serialCacheUpdateMutex.Unlock()
  1249. var accountName string
  1250. var channelsStr string
  1251. keepProtections := false
  1252. am.server.store.Update(func(tx *buntdb.Tx) error {
  1253. // get the unfolded account name; for an active account, this is
  1254. // stored under accountNameKey, for an unregistered account under unregisteredKey
  1255. accountName, _ = tx.Get(accountNameKey)
  1256. if accountName == "" {
  1257. accountName, _ = tx.Get(unregisteredKey)
  1258. }
  1259. if erase {
  1260. tx.Delete(unregisteredKey)
  1261. } else {
  1262. if _, err := tx.Get(verifiedKey); err == nil {
  1263. tx.Set(unregisteredKey, accountName, nil)
  1264. keepProtections = true
  1265. }
  1266. }
  1267. tx.Delete(accountKey)
  1268. tx.Delete(accountNameKey)
  1269. tx.Delete(verifiedKey)
  1270. tx.Delete(registeredTimeKey)
  1271. tx.Delete(callbackKey)
  1272. tx.Delete(verificationCodeKey)
  1273. tx.Delete(settingsKey)
  1274. rawNicks, _ = tx.Get(nicksKey)
  1275. tx.Delete(nicksKey)
  1276. credText, err = tx.Get(credentialsKey)
  1277. tx.Delete(credentialsKey)
  1278. tx.Delete(vhostKey)
  1279. channelsStr, _ = tx.Get(channelsKey)
  1280. tx.Delete(channelsKey)
  1281. tx.Delete(joinedChannelsKey)
  1282. tx.Delete(lastSeenKey)
  1283. tx.Delete(modesKey)
  1284. tx.Delete(realnameKey)
  1285. _, err := tx.Delete(vhostQueueKey)
  1286. am.decrementVHostQueueCount(casefoldedAccount, err)
  1287. return nil
  1288. })
  1289. if err == nil {
  1290. var creds AccountCredentials
  1291. if err := json.Unmarshal([]byte(credText), &creds); err == nil {
  1292. for _, cert := range creds.Certfps {
  1293. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  1294. am.server.store.Update(func(tx *buntdb.Tx) error {
  1295. if account, err := tx.Get(certFPKey); err == nil && account == casefoldedAccount {
  1296. tx.Delete(certFPKey)
  1297. }
  1298. return nil
  1299. })
  1300. }
  1301. }
  1302. }
  1303. skeleton, _ := Skeleton(accountName)
  1304. additionalNicks := unmarshalReservedNicks(rawNicks)
  1305. registeredChannels = unmarshalRegisteredChannels(channelsStr)
  1306. am.Lock()
  1307. defer am.Unlock()
  1308. clients = am.accountToClients[casefoldedAccount]
  1309. delete(am.accountToClients, casefoldedAccount)
  1310. // protect the account name itself where applicable, but not any grouped nicks
  1311. if !(keepProtections && config.Accounts.NickReservation.Method == NickEnforcementStrict) {
  1312. delete(am.nickToAccount, casefoldedAccount)
  1313. delete(am.skeletonToAccount, skeleton)
  1314. }
  1315. for _, nick := range additionalNicks {
  1316. delete(am.nickToAccount, nick)
  1317. additionalSkel, _ := Skeleton(nick)
  1318. delete(am.skeletonToAccount, additionalSkel)
  1319. }
  1320. if err != nil && !erase {
  1321. return errAccountDoesNotExist
  1322. }
  1323. return nil
  1324. }
  1325. func unmarshalRegisteredChannels(channelsStr string) (result []string) {
  1326. if channelsStr != "" {
  1327. result = strings.Split(channelsStr, ",")
  1328. }
  1329. return
  1330. }
  1331. func (am *AccountManager) ChannelsForAccount(account string) (channels []string) {
  1332. cfaccount, err := CasefoldName(account)
  1333. if err != nil {
  1334. return
  1335. }
  1336. var channelStr string
  1337. key := fmt.Sprintf(keyAccountChannels, cfaccount)
  1338. am.server.store.View(func(tx *buntdb.Tx) error {
  1339. channelStr, _ = tx.Get(key)
  1340. return nil
  1341. })
  1342. return unmarshalRegisteredChannels(channelStr)
  1343. }
  1344. func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp string, peerCerts []*x509.Certificate, authzid string) (err error) {
  1345. if certfp == "" {
  1346. return errAccountInvalidCredentials
  1347. }
  1348. var clientAccount ClientAccount
  1349. defer func() {
  1350. if err != nil {
  1351. return
  1352. } else if !clientAccount.Verified {
  1353. err = errAccountUnverified
  1354. return
  1355. }
  1356. // TODO(#1109) clean this check up?
  1357. if client.registered {
  1358. if clientAlready := am.server.clients.Get(clientAccount.Name); clientAlready != nil && clientAlready.AlwaysOn() {
  1359. err = errNickAccountMismatch
  1360. return
  1361. }
  1362. }
  1363. am.Login(client, clientAccount)
  1364. return
  1365. }()
  1366. config := am.server.Config()
  1367. if config.Accounts.AuthScript.Enabled {
  1368. var output AuthScriptOutput
  1369. output, err = CheckAuthScript(am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
  1370. AuthScriptInput{Certfp: certfp, IP: client.IP().String(), peerCerts: peerCerts})
  1371. if err != nil {
  1372. am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
  1373. } else if output.Success && output.AccountName != "" {
  1374. clientAccount, err = am.loadWithAutocreation(output.AccountName, config.Accounts.AuthScript.Autocreate)
  1375. return
  1376. }
  1377. }
  1378. var account string
  1379. certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
  1380. err = am.server.store.View(func(tx *buntdb.Tx) error {
  1381. account, _ = tx.Get(certFPKey)
  1382. if account == "" {
  1383. return errAccountInvalidCredentials
  1384. }
  1385. return nil
  1386. })
  1387. if err != nil {
  1388. return err
  1389. }
  1390. if authzid != "" && authzid != account {
  1391. return errAuthzidAuthcidMismatch
  1392. }
  1393. // ok, we found an account corresponding to their certificate
  1394. clientAccount, err = am.LoadAccount(account)
  1395. return err
  1396. }
  1397. type settingsMunger func(input AccountSettings) (output AccountSettings, err error)
  1398. func (am *AccountManager) ModifyAccountSettings(account string, munger settingsMunger) (newSettings AccountSettings, err error) {
  1399. casefoldedAccount, err := CasefoldName(account)
  1400. if err != nil {
  1401. return newSettings, errAccountDoesNotExist
  1402. }
  1403. // TODO implement this in general via a compare-and-swap API
  1404. accountData, err := am.LoadAccount(casefoldedAccount)
  1405. if err != nil {
  1406. return
  1407. } else if !accountData.Verified {
  1408. return newSettings, errAccountUnverified
  1409. }
  1410. newSettings, err = munger(accountData.Settings)
  1411. if err != nil {
  1412. return
  1413. }
  1414. text, err := json.Marshal(newSettings)
  1415. if err != nil {
  1416. return
  1417. }
  1418. key := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1419. serializedValue := string(text)
  1420. err = am.server.store.Update(func(tx *buntdb.Tx) (err error) {
  1421. _, _, err = tx.Set(key, serializedValue, nil)
  1422. return
  1423. })
  1424. if err != nil {
  1425. err = errAccountUpdateFailed
  1426. return
  1427. }
  1428. // success, push new settings into the client objects
  1429. am.Lock()
  1430. defer am.Unlock()
  1431. for _, client := range am.accountToClients[casefoldedAccount] {
  1432. client.SetAccountSettings(newSettings)
  1433. }
  1434. return
  1435. }
  1436. // represents someone's status in hostserv
  1437. type VHostInfo struct {
  1438. ApprovedVHost string
  1439. Enabled bool
  1440. RequestedVHost string
  1441. RejectedVHost string
  1442. RejectionReason string
  1443. LastRequestTime time.Time
  1444. }
  1445. // pair type, <VHostInfo, accountName>
  1446. type PendingVHostRequest struct {
  1447. VHostInfo
  1448. Account string
  1449. }
  1450. type vhostThrottleExceeded struct {
  1451. timeRemaining time.Duration
  1452. }
  1453. func (vhe *vhostThrottleExceeded) Error() string {
  1454. return fmt.Sprintf("Wait at least %v and try again", vhe.timeRemaining)
  1455. }
  1456. func (vh *VHostInfo) checkThrottle(cooldown time.Duration) (err error) {
  1457. if cooldown == 0 {
  1458. return nil
  1459. }
  1460. now := time.Now().UTC()
  1461. elapsed := now.Sub(vh.LastRequestTime)
  1462. if elapsed > cooldown {
  1463. // success
  1464. vh.LastRequestTime = now
  1465. return nil
  1466. } else {
  1467. return &vhostThrottleExceeded{timeRemaining: cooldown - elapsed}
  1468. }
  1469. }
  1470. // callback type implementing the actual business logic of vhost operations
  1471. type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
  1472. func (am *AccountManager) VHostSet(account string, vhost string) (result VHostInfo, err error) {
  1473. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1474. output = input
  1475. output.Enabled = true
  1476. output.ApprovedVHost = vhost
  1477. return
  1478. }
  1479. return am.performVHostChange(account, munger)
  1480. }
  1481. func (am *AccountManager) VHostRequest(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
  1482. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1483. output = input
  1484. // you can update your existing request, but if you were approved or rejected,
  1485. // you can't spam a new request
  1486. if output.RequestedVHost == "" {
  1487. err = output.checkThrottle(cooldown)
  1488. }
  1489. if err != nil {
  1490. return
  1491. }
  1492. output.RequestedVHost = vhost
  1493. output.RejectedVHost = ""
  1494. output.RejectionReason = ""
  1495. output.LastRequestTime = time.Now().UTC()
  1496. return
  1497. }
  1498. return am.performVHostChange(account, munger)
  1499. }
  1500. func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
  1501. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1502. output = input
  1503. output.Enabled = true
  1504. output.ApprovedVHost = input.RequestedVHost
  1505. output.RequestedVHost = ""
  1506. output.RejectionReason = ""
  1507. return
  1508. }
  1509. return am.performVHostChange(account, munger)
  1510. }
  1511. func (am *AccountManager) VHostReject(account string, reason string) (result VHostInfo, err error) {
  1512. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1513. output = input
  1514. output.RejectedVHost = output.RequestedVHost
  1515. output.RequestedVHost = ""
  1516. output.RejectionReason = reason
  1517. return
  1518. }
  1519. return am.performVHostChange(account, munger)
  1520. }
  1521. func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (result VHostInfo, err error) {
  1522. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1523. if input.ApprovedVHost == "" {
  1524. err = errNoVhost
  1525. return
  1526. }
  1527. output = input
  1528. output.Enabled = enabled
  1529. return
  1530. }
  1531. return am.performVHostChange(client.Account(), munger)
  1532. }
  1533. func (am *AccountManager) performVHostChange(account string, munger vhostMunger) (result VHostInfo, err error) {
  1534. account, err = CasefoldName(account)
  1535. if err != nil || account == "" {
  1536. err = errAccountDoesNotExist
  1537. return
  1538. }
  1539. if am.server.Defcon() <= 3 {
  1540. err = errFeatureDisabled
  1541. return
  1542. }
  1543. am.vHostUpdateMutex.Lock()
  1544. defer am.vHostUpdateMutex.Unlock()
  1545. clientAccount, err := am.LoadAccount(account)
  1546. if err != nil {
  1547. err = errAccountDoesNotExist
  1548. return
  1549. } else if !clientAccount.Verified {
  1550. err = errAccountUnverified
  1551. return
  1552. }
  1553. result, err = munger(clientAccount.VHost)
  1554. if err != nil {
  1555. return
  1556. }
  1557. vhtext, err := json.Marshal(result)
  1558. if err != nil {
  1559. err = errAccountUpdateFailed
  1560. return
  1561. }
  1562. vhstr := string(vhtext)
  1563. key := fmt.Sprintf(keyAccountVHost, account)
  1564. queueKey := fmt.Sprintf(keyVHostQueueAcctToId, account)
  1565. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1566. if _, _, err := tx.Set(key, vhstr, nil); err != nil {
  1567. return err
  1568. }
  1569. // update request queue
  1570. if clientAccount.VHost.RequestedVHost == "" && result.RequestedVHost != "" {
  1571. id := atomic.AddUint64(&am.vhostRequestID, 1)
  1572. if _, _, err = tx.Set(queueKey, strconv.FormatUint(id, 10), nil); err != nil {
  1573. return err
  1574. }
  1575. atomic.AddUint64(&am.vhostRequestPendingCount, 1)
  1576. } else if clientAccount.VHost.RequestedVHost != "" && result.RequestedVHost == "" {
  1577. _, err = tx.Delete(queueKey)
  1578. am.decrementVHostQueueCount(account, err)
  1579. }
  1580. return nil
  1581. })
  1582. if err != nil {
  1583. err = errAccountUpdateFailed
  1584. return
  1585. }
  1586. am.applyVhostToClients(account, result)
  1587. return result, nil
  1588. }
  1589. // XXX annoying helper method for keeping the queue count in sync with the DB
  1590. // `err` is the buntdb error returned from deleting the queue key
  1591. func (am *AccountManager) decrementVHostQueueCount(account string, err error) {
  1592. if err == nil {
  1593. // successfully deleted a queue entry, do a 2's complement decrement:
  1594. atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
  1595. } else if err != buntdb.ErrNotFound {
  1596. am.server.logger.Error("internal", "buntdb dequeue error", account, err.Error())
  1597. }
  1598. }
  1599. func (am *AccountManager) VHostListRequests(limit int) (requests []PendingVHostRequest, total int) {
  1600. am.vHostUpdateMutex.Lock()
  1601. defer am.vHostUpdateMutex.Unlock()
  1602. total = int(atomic.LoadUint64(&am.vhostRequestPendingCount))
  1603. prefix := fmt.Sprintf(keyVHostQueueAcctToId, "")
  1604. accounts := make([]string, 0, limit)
  1605. err := am.server.store.View(func(tx *buntdb.Tx) error {
  1606. return tx.Ascend(vhostRequestIdx, func(key, value string) bool {
  1607. accounts = append(accounts, strings.TrimPrefix(key, prefix))
  1608. return len(accounts) < limit
  1609. })
  1610. })
  1611. if err != nil {
  1612. am.server.logger.Error("internal", "couldn't traverse vhost queue", err.Error())
  1613. return
  1614. }
  1615. for _, account := range accounts {
  1616. accountInfo, err := am.LoadAccount(account)
  1617. if err == nil {
  1618. requests = append(requests, PendingVHostRequest{
  1619. Account: account,
  1620. VHostInfo: accountInfo.VHost,
  1621. })
  1622. } else {
  1623. am.server.logger.Error("internal", "corrupt account", account, err.Error())
  1624. }
  1625. }
  1626. return
  1627. }
  1628. func (am *AccountManager) applyVHostInfo(client *Client, info VHostInfo) {
  1629. // if hostserv is disabled in config, then don't grant vhosts
  1630. // that were previously approved while it was enabled
  1631. if !am.server.Config().Accounts.VHosts.Enabled {
  1632. return
  1633. }
  1634. vhost := ""
  1635. if info.Enabled {
  1636. vhost = info.ApprovedVHost
  1637. }
  1638. oldNickmask := client.NickMaskString()
  1639. updated := client.SetVHost(vhost)
  1640. if updated && client.Registered() {
  1641. // TODO: doing I/O here is kind of a kludge
  1642. client.sendChghost(oldNickmask, client.Hostname())
  1643. }
  1644. }
  1645. func (am *AccountManager) applyVhostToClients(account string, result VHostInfo) {
  1646. am.RLock()
  1647. clients := am.accountToClients[account]
  1648. am.RUnlock()
  1649. for _, client := range clients {
  1650. am.applyVHostInfo(client, result)
  1651. }
  1652. }
  1653. func (am *AccountManager) Login(client *Client, account ClientAccount) {
  1654. client.Login(account)
  1655. am.applyVHostInfo(client, account.VHost)
  1656. casefoldedAccount := client.Account()
  1657. am.Lock()
  1658. defer am.Unlock()
  1659. am.accountToClients[casefoldedAccount] = append(am.accountToClients[casefoldedAccount], client)
  1660. }
  1661. func (am *AccountManager) Logout(client *Client) {
  1662. am.Lock()
  1663. defer am.Unlock()
  1664. casefoldedAccount := client.Account()
  1665. if casefoldedAccount == "" {
  1666. return
  1667. }
  1668. client.Logout()
  1669. clients := am.accountToClients[casefoldedAccount]
  1670. if len(clients) <= 1 {
  1671. delete(am.accountToClients, casefoldedAccount)
  1672. return
  1673. }
  1674. remainingClients := make([]*Client, len(clients)-1)
  1675. remainingPos := 0
  1676. for currentPos := 0; currentPos < len(clients); currentPos++ {
  1677. if clients[currentPos] != client {
  1678. remainingClients[remainingPos] = clients[currentPos]
  1679. remainingPos++
  1680. }
  1681. }
  1682. am.accountToClients[casefoldedAccount] = remainingClients
  1683. }
  1684. var (
  1685. // EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
  1686. // This can be moved to some other data structure/place if we need to load/unload mechs later.
  1687. EnabledSaslMechanisms = map[string]func(*Server, *Client, string, []byte, *ResponseBuffer) bool{
  1688. "PLAIN": authPlainHandler,
  1689. "EXTERNAL": authExternalHandler,
  1690. }
  1691. )
  1692. type CredentialsVersion int
  1693. const (
  1694. CredentialsLegacy CredentialsVersion = 0
  1695. CredentialsSHA3Bcrypt CredentialsVersion = 1
  1696. // negative numbers for migration
  1697. CredentialsAtheme = -1
  1698. CredentialsAnope = -2
  1699. )
  1700. // AccountCredentials stores the various methods for verifying accounts.
  1701. type AccountCredentials struct {
  1702. Version CredentialsVersion
  1703. PassphraseHash []byte
  1704. Certfps []string
  1705. }
  1706. func (ac *AccountCredentials) Empty() bool {
  1707. return len(ac.PassphraseHash) == 0 && len(ac.Certfps) == 0
  1708. }
  1709. // helper to assemble the serialized JSON for an account's credentials
  1710. func (ac *AccountCredentials) Serialize() (result string, err error) {
  1711. ac.Version = 1
  1712. credText, err := json.Marshal(*ac)
  1713. if err != nil {
  1714. return "", err
  1715. }
  1716. return string(credText), nil
  1717. }
  1718. func (ac *AccountCredentials) SetPassphrase(passphrase string, bcryptCost uint) (err error) {
  1719. if passphrase == "" {
  1720. ac.PassphraseHash = nil
  1721. return nil
  1722. }
  1723. if validatePassphrase(passphrase) != nil {
  1724. return errAccountBadPassphrase
  1725. }
  1726. ac.PassphraseHash, err = passwd.GenerateFromPassword([]byte(passphrase), int(bcryptCost))
  1727. if err != nil {
  1728. return errAccountBadPassphrase
  1729. }
  1730. return nil
  1731. }
  1732. func (ac *AccountCredentials) AddCertfp(certfp string) (err error) {
  1733. // XXX we require that certfp is already normalized (rather than normalize here
  1734. // and pass back the normalized version as an additional return parameter);
  1735. // this is just a final sanity check:
  1736. if len(certfp) != 64 {
  1737. return utils.ErrInvalidCertfp
  1738. }
  1739. for _, current := range ac.Certfps {
  1740. if certfp == current {
  1741. return errNoop
  1742. }
  1743. }
  1744. if maxCertfpsPerAccount <= len(ac.Certfps) {
  1745. return errLimitExceeded
  1746. }
  1747. ac.Certfps = append(ac.Certfps, certfp)
  1748. return nil
  1749. }
  1750. func (ac *AccountCredentials) RemoveCertfp(certfp string) (err error) {
  1751. found := false
  1752. newList := make([]string, 0, len(ac.Certfps))
  1753. for _, current := range ac.Certfps {
  1754. if current == certfp {
  1755. found = true
  1756. } else {
  1757. newList = append(newList, current)
  1758. }
  1759. }
  1760. if !found {
  1761. // this is important because it prevents you from deleting someone else's
  1762. // fingerprint record
  1763. return errNoop
  1764. }
  1765. ac.Certfps = newList
  1766. return nil
  1767. }
  1768. type MulticlientAllowedSetting int
  1769. const (
  1770. MulticlientAllowedServerDefault MulticlientAllowedSetting = iota
  1771. MulticlientDisallowedByUser
  1772. MulticlientAllowedByUser
  1773. )
  1774. // controls whether/when clients without event-playback support see fake
  1775. // PRIVMSGs for JOINs
  1776. type ReplayJoinsSetting uint
  1777. const (
  1778. ReplayJoinsCommandsOnly = iota // replay in HISTORY or CHATHISTORY output
  1779. ReplayJoinsAlways // replay in HISTORY, CHATHISTORY, or autoreplay
  1780. ReplayJoinsNever // never replay
  1781. )
  1782. func replayJoinsSettingFromString(str string) (result ReplayJoinsSetting, err error) {
  1783. switch strings.ToLower(str) {
  1784. case "commands-only":
  1785. result = ReplayJoinsCommandsOnly
  1786. case "always":
  1787. result = ReplayJoinsAlways
  1788. case "never":
  1789. result = ReplayJoinsNever
  1790. default:
  1791. err = errInvalidParams
  1792. }
  1793. return
  1794. }
  1795. // XXX: AllowBouncer cannot be renamed AllowMulticlient because it is stored in
  1796. // persistent JSON blobs in the database
  1797. type AccountSettings struct {
  1798. AutoreplayLines *int
  1799. NickEnforcement NickEnforcementMethod
  1800. AllowBouncer MulticlientAllowedSetting
  1801. ReplayJoins ReplayJoinsSetting
  1802. AlwaysOn PersistentStatus
  1803. AutoreplayMissed bool
  1804. DMHistory HistoryStatus
  1805. AutoAway PersistentStatus
  1806. }
  1807. // ClientAccount represents a user account.
  1808. type ClientAccount struct {
  1809. // Name of the account.
  1810. Name string
  1811. NameCasefolded string
  1812. RegisteredAt time.Time
  1813. Credentials AccountCredentials
  1814. Verified bool
  1815. AdditionalNicks []string
  1816. VHost VHostInfo
  1817. Settings AccountSettings
  1818. }
  1819. // convenience for passing around raw serialized account data
  1820. type rawClientAccount struct {
  1821. Name string
  1822. RegisteredAt string
  1823. Credentials string
  1824. Callback string
  1825. Verified bool
  1826. AdditionalNicks string
  1827. VHost string
  1828. Settings string
  1829. }