Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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