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

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