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

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