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 58KB

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