Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

accounts.go 67KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351
  1. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "crypto/rand"
  6. "crypto/x509"
  7. "encoding/json"
  8. "fmt"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. "sync"
  13. "time"
  14. "unicode"
  15. "github.com/ergochat/irc-go/ircutils"
  16. "github.com/tidwall/buntdb"
  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. )
  25. const (
  26. keyAccountExists = "account.exists %s"
  27. keyAccountVerified = "account.verified %s"
  28. keyAccountUnregistered = "account.unregistered %s"
  29. keyAccountVerificationCode = "account.verificationcode %s"
  30. keyAccountName = "account.name %s" // stores the 'preferred name' of the account, not casemapped
  31. keyAccountRegTime = "account.registered.time %s"
  32. keyAccountCredentials = "account.credentials %s"
  33. keyAccountAdditionalNicks = "account.additionalnicks %s"
  34. keyAccountSettings = "account.settings %s"
  35. keyAccountVHost = "account.vhost %s"
  36. keyCertToAccount = "account.creds.certfp %s"
  37. keyAccountChannels = "account.channels %s" // channels registered to the account
  38. 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. keyAccountPwReset = "account.pwreset %s"
  43. keyAccountEmailChange = "account.emailchange %s"
  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 && rawPrefs != "" {
  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 settings", account, err.Error())
  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. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  343. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  344. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  345. settingsKey := fmt.Sprintf(keyAccountSettings, 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. var settingsStr string
  359. if callbackNamespace == "mailto" {
  360. settings := AccountSettings{Email: callbackValue}
  361. j, err := json.Marshal(settings)
  362. if err == nil {
  363. settingsStr = string(j)
  364. }
  365. }
  366. registeredTimeStr := strconv.FormatInt(time.Now().UnixNano(), 10)
  367. var setOptions *buntdb.SetOptions
  368. ttl := time.Duration(config.Accounts.Registration.VerifyTimeout)
  369. if ttl != 0 {
  370. setOptions = &buntdb.SetOptions{Expires: true, TTL: ttl}
  371. }
  372. err = func() error {
  373. am.serialCacheUpdateMutex.Lock()
  374. defer am.serialCacheUpdateMutex.Unlock()
  375. // can't register an account with the same name as a registered nick
  376. if am.NickToAccount(account) != "" {
  377. return errAccountAlreadyRegistered
  378. }
  379. return am.server.store.Update(func(tx *buntdb.Tx) error {
  380. if _, err := tx.Get(unregisteredKey); err == nil {
  381. return errAccountAlreadyUnregistered
  382. }
  383. _, err = am.loadRawAccount(tx, casefoldedAccount)
  384. if err != errAccountDoesNotExist {
  385. return errAccountAlreadyRegistered
  386. }
  387. if certfp != "" {
  388. // make sure certfp doesn't already exist because that'd be silly
  389. _, err := tx.Get(certFPKey)
  390. if err != buntdb.ErrNotFound {
  391. return errCertfpAlreadyExists
  392. }
  393. }
  394. tx.Set(accountKey, "1", setOptions)
  395. tx.Set(accountNameKey, account, setOptions)
  396. tx.Set(registeredTimeKey, registeredTimeStr, setOptions)
  397. tx.Set(credentialsKey, credStr, setOptions)
  398. tx.Set(settingsKey, settingsStr, setOptions)
  399. if certfp != "" {
  400. tx.Set(certFPKey, casefoldedAccount, setOptions)
  401. }
  402. return nil
  403. })
  404. }()
  405. if err != nil {
  406. return err
  407. }
  408. code, err := am.dispatchCallback(client, account, callbackNamespace, callbackValue)
  409. if err != nil {
  410. am.Unregister(casefoldedAccount, true)
  411. return &registrationCallbackError{underlying: err}
  412. } else {
  413. am.server.logger.Info("accounts",
  414. fmt.Sprintf("nickname %s registered account %s, pending verification", client.Nick(), account))
  415. return am.server.store.Update(func(tx *buntdb.Tx) error {
  416. _, _, err = tx.Set(verificationCodeKey, code, setOptions)
  417. return err
  418. })
  419. }
  420. }
  421. type registrationCallbackError struct {
  422. underlying error
  423. }
  424. func (r *registrationCallbackError) Error() string {
  425. return `Account verification could not be sent`
  426. }
  427. func registrationCallbackErrorText(config *Config, client *Client, err error) string {
  428. if callbackErr, ok := err.(*registrationCallbackError); ok {
  429. // only expose a user-visible error if we are doing direct sending
  430. if config.Accounts.Registration.EmailVerification.DirectSendingEnabled() {
  431. errorText := ircutils.SanitizeText(callbackErr.underlying.Error(), 350)
  432. return fmt.Sprintf(client.t("Could not dispatch registration e-mail: %s"), errorText)
  433. } else {
  434. return client.t("Could not dispatch registration e-mail")
  435. }
  436. } else {
  437. return ""
  438. }
  439. }
  440. // ValidatePassphrase checks whether a passphrase is allowed by our rules
  441. func ValidatePassphrase(passphrase string) error {
  442. // sanity check the length
  443. if len(passphrase) == 0 || len(passphrase) > 300 {
  444. return errAccountBadPassphrase
  445. }
  446. // we use * as a placeholder in some places, if it's gotten this far then fail
  447. if passphrase == "*" {
  448. return errAccountBadPassphrase
  449. }
  450. // validate that the passphrase contains no spaces, and furthermore is valid as a
  451. // non-final IRC parameter. we already checked that it is nonempty:
  452. if passphrase[0] == ':' {
  453. return errAccountBadPassphrase
  454. }
  455. for _, r := range passphrase {
  456. if unicode.IsSpace(r) {
  457. return errAccountBadPassphrase
  458. }
  459. }
  460. return nil
  461. }
  462. // changes the password for an account
  463. func (am *AccountManager) setPassword(accountName string, password string, hasPrivs bool) (err error) {
  464. cfAccount, err := CasefoldName(accountName)
  465. if err != nil {
  466. return errAccountDoesNotExist
  467. }
  468. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  469. var credStr string
  470. am.server.store.View(func(tx *buntdb.Tx) error {
  471. // no need to check verification status here or below;
  472. // you either need to be auth'ed to the account or be an oper to do this
  473. credStr, err = tx.Get(credKey)
  474. return nil
  475. })
  476. if err != nil {
  477. return errAccountDoesNotExist
  478. }
  479. var creds AccountCredentials
  480. err = json.Unmarshal([]byte(credStr), &creds)
  481. if err != nil {
  482. return err
  483. }
  484. if !hasPrivs && creds.Empty() {
  485. return errCredsExternallyManaged
  486. }
  487. err = creds.SetPassphrase(password, am.server.Config().Accounts.Registration.BcryptCost)
  488. if err != nil {
  489. return err
  490. }
  491. if creds.Empty() && !hasPrivs {
  492. return errEmptyCredentials
  493. }
  494. newCredStr, err := creds.Serialize()
  495. if err != nil {
  496. return err
  497. }
  498. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  499. curCredStr, err := tx.Get(credKey)
  500. if credStr != curCredStr {
  501. return errCASFailed
  502. }
  503. _, _, err = tx.Set(credKey, newCredStr, nil)
  504. return err
  505. })
  506. return err
  507. }
  508. type alwaysOnChannelStatus struct {
  509. Modes string
  510. JoinTime int64
  511. }
  512. func (am *AccountManager) saveChannels(account string, channelToModes map[string]alwaysOnChannelStatus) {
  513. j, err := json.Marshal(channelToModes)
  514. if err != nil {
  515. am.server.logger.Error("internal", "couldn't marshal channel-to-modes", account, err.Error())
  516. return
  517. }
  518. jStr := string(j)
  519. key := fmt.Sprintf(keyAccountChannelToModes, account)
  520. am.server.store.Update(func(tx *buntdb.Tx) error {
  521. tx.Set(key, jStr, nil)
  522. return nil
  523. })
  524. }
  525. func (am *AccountManager) loadChannels(account string) (channelToModes map[string]alwaysOnChannelStatus) {
  526. key := fmt.Sprintf(keyAccountChannelToModes, account)
  527. var channelsStr string
  528. am.server.store.View(func(tx *buntdb.Tx) error {
  529. channelsStr, _ = tx.Get(key)
  530. return nil
  531. })
  532. if channelsStr == "" {
  533. return nil
  534. }
  535. err := json.Unmarshal([]byte(channelsStr), &channelToModes)
  536. if err != nil {
  537. am.server.logger.Error("internal", "couldn't marshal channel-to-modes", account, err.Error())
  538. return nil
  539. }
  540. return
  541. }
  542. func (am *AccountManager) saveModes(account string, uModes modes.Modes) {
  543. modeStr := uModes.String()
  544. key := fmt.Sprintf(keyAccountModes, account)
  545. am.server.store.Update(func(tx *buntdb.Tx) error {
  546. tx.Set(key, modeStr, nil)
  547. return nil
  548. })
  549. }
  550. func (am *AccountManager) loadModes(account string) (uModes modes.Modes) {
  551. key := fmt.Sprintf(keyAccountModes, account)
  552. var modeStr string
  553. am.server.store.View(func(tx *buntdb.Tx) error {
  554. modeStr, _ = tx.Get(key)
  555. return nil
  556. })
  557. for _, m := range modeStr {
  558. uModes = append(uModes, modes.Mode(m))
  559. }
  560. return
  561. }
  562. func (am *AccountManager) saveLastSeen(account string, lastSeen map[string]time.Time) {
  563. key := fmt.Sprintf(keyAccountLastSeen, account)
  564. var val string
  565. if len(lastSeen) != 0 {
  566. text, _ := json.Marshal(lastSeen)
  567. val = string(text)
  568. }
  569. err := am.server.store.Update(func(tx *buntdb.Tx) error {
  570. if val != "" {
  571. tx.Set(key, val, nil)
  572. } else {
  573. tx.Delete(key)
  574. }
  575. return nil
  576. })
  577. if err != nil {
  578. am.server.logger.Error("internal", "error persisting lastSeen", account, err.Error())
  579. }
  580. }
  581. func (am *AccountManager) loadLastSeen(account string) (lastSeen map[string]time.Time) {
  582. key := fmt.Sprintf(keyAccountLastSeen, account)
  583. var lsText string
  584. am.server.store.Update(func(tx *buntdb.Tx) error {
  585. lsText, _ = tx.Get(key)
  586. return nil
  587. })
  588. if lsText == "" {
  589. return nil
  590. }
  591. err := json.Unmarshal([]byte(lsText), &lastSeen)
  592. if err != nil {
  593. return nil
  594. }
  595. return
  596. }
  597. func (am *AccountManager) saveRealname(account string, realname string) {
  598. key := fmt.Sprintf(keyAccountRealname, account)
  599. am.server.store.Update(func(tx *buntdb.Tx) error {
  600. if realname != "" {
  601. tx.Set(key, realname, nil)
  602. } else {
  603. tx.Delete(key)
  604. }
  605. return nil
  606. })
  607. }
  608. func (am *AccountManager) loadRealname(account string) (realname string) {
  609. key := fmt.Sprintf(keyAccountRealname, account)
  610. am.server.store.Update(func(tx *buntdb.Tx) error {
  611. realname, _ = tx.Get(key)
  612. return nil
  613. })
  614. return
  615. }
  616. func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasPrivs bool) (err error) {
  617. certfp, err = utils.NormalizeCertfp(certfp)
  618. if err != nil {
  619. return err
  620. }
  621. cfAccount, err := CasefoldName(account)
  622. if err != nil {
  623. return errAccountDoesNotExist
  624. }
  625. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  626. var credStr string
  627. am.server.store.View(func(tx *buntdb.Tx) error {
  628. credStr, err = tx.Get(credKey)
  629. return nil
  630. })
  631. if err != nil {
  632. return errAccountDoesNotExist
  633. }
  634. var creds AccountCredentials
  635. err = json.Unmarshal([]byte(credStr), &creds)
  636. if err != nil {
  637. return err
  638. }
  639. if !hasPrivs && creds.Empty() {
  640. return errCredsExternallyManaged
  641. }
  642. if add {
  643. err = creds.AddCertfp(certfp)
  644. } else {
  645. err = creds.RemoveCertfp(certfp)
  646. }
  647. if err != nil {
  648. return err
  649. }
  650. if creds.Empty() && !hasPrivs {
  651. return errEmptyCredentials
  652. }
  653. newCredStr, err := creds.Serialize()
  654. if err != nil {
  655. return err
  656. }
  657. certfpKey := fmt.Sprintf(keyCertToAccount, certfp)
  658. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  659. curCredStr, err := tx.Get(credKey)
  660. if credStr != curCredStr {
  661. return errCASFailed
  662. }
  663. if add {
  664. _, err = tx.Get(certfpKey)
  665. if err != buntdb.ErrNotFound {
  666. return errCertfpAlreadyExists
  667. }
  668. tx.Set(certfpKey, cfAccount, nil)
  669. } else {
  670. tx.Delete(certfpKey)
  671. }
  672. _, _, err = tx.Set(credKey, newCredStr, nil)
  673. return err
  674. })
  675. return err
  676. }
  677. func (am *AccountManager) dispatchCallback(client *Client, account string, callbackNamespace string, callbackValue string) (string, error) {
  678. if callbackNamespace == "*" || callbackNamespace == "none" || callbackNamespace == "admin" {
  679. return "", nil
  680. } else if callbackNamespace == "mailto" {
  681. return am.dispatchMailtoCallback(client, account, callbackValue)
  682. } else {
  683. return "", fmt.Errorf("Callback not implemented: %s", callbackNamespace)
  684. }
  685. }
  686. func (am *AccountManager) dispatchMailtoCallback(client *Client, account string, callbackValue string) (code string, err error) {
  687. config := am.server.Config().Accounts.Registration.EmailVerification
  688. code = utils.GenerateSecretToken()
  689. subject := config.VerifyMessageSubject
  690. if subject == "" {
  691. subject = fmt.Sprintf(client.t("Verify your account on %s"), am.server.name)
  692. }
  693. message := email.ComposeMail(config, callbackValue, subject)
  694. fmt.Fprintf(&message, client.t("Account: %s"), account)
  695. message.WriteString("\r\n")
  696. fmt.Fprintf(&message, client.t("Verification code: %s"), code)
  697. message.WriteString("\r\n")
  698. message.WriteString("\r\n")
  699. message.WriteString(client.t("To verify your account, issue the following command:"))
  700. message.WriteString("\r\n")
  701. fmt.Fprintf(&message, "/MSG NickServ VERIFY %s %s\r\n", account, code)
  702. err = email.SendMail(config, callbackValue, message.Bytes())
  703. if err != nil {
  704. am.server.logger.Error("internal", "Failed to dispatch e-mail to", callbackValue, err.Error())
  705. }
  706. return
  707. }
  708. func (am *AccountManager) Verify(client *Client, account string, code string) error {
  709. casefoldedAccount, err := CasefoldName(account)
  710. var skeleton string
  711. if err != nil || account == "" || account == "*" {
  712. return errAccountVerificationFailed
  713. }
  714. if client != nil && client.Account() != "" {
  715. return errAccountAlreadyLoggedIn
  716. }
  717. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  718. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  719. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  720. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  721. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  722. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  723. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  724. var raw rawClientAccount
  725. func() {
  726. am.serialCacheUpdateMutex.Lock()
  727. defer am.serialCacheUpdateMutex.Unlock()
  728. // do a final check for confusability (in case someone already verified
  729. // a confusable identifier):
  730. var unfoldedName string
  731. err = am.server.store.View(func(tx *buntdb.Tx) error {
  732. unfoldedName, err = tx.Get(accountNameKey)
  733. return err
  734. })
  735. if err != nil {
  736. err = errAccountDoesNotExist
  737. return
  738. }
  739. skeleton, err = Skeleton(unfoldedName)
  740. if err != nil {
  741. err = errAccountDoesNotExist
  742. return
  743. }
  744. err = func() error {
  745. am.RLock()
  746. defer am.RUnlock()
  747. if _, ok := am.skeletonToAccount[skeleton]; ok {
  748. return errConfusableIdentifier
  749. }
  750. return nil
  751. }()
  752. if err != nil {
  753. return
  754. }
  755. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  756. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  757. if err == errAccountDoesNotExist {
  758. return errAccountDoesNotExist
  759. } else if err != nil {
  760. return errAccountVerificationFailed
  761. } else if raw.Verified {
  762. return errAccountAlreadyVerified
  763. }
  764. // actually verify the code
  765. // a stored code of "" means a none callback / no code required
  766. success := false
  767. storedCode, err := tx.Get(verificationCodeKey)
  768. if err == nil {
  769. // this is probably unnecessary
  770. if storedCode == "" || utils.SecretTokensMatch(storedCode, code) {
  771. success = true
  772. }
  773. }
  774. if !success {
  775. return errAccountVerificationInvalidCode
  776. }
  777. // verify the account
  778. tx.Set(verifiedKey, "1", nil)
  779. // don't need the code anymore
  780. tx.Delete(verificationCodeKey)
  781. // re-set all other keys, removing the TTL
  782. tx.Set(accountKey, "1", nil)
  783. tx.Set(accountNameKey, raw.Name, nil)
  784. tx.Set(registeredTimeKey, raw.RegisteredAt, nil)
  785. tx.Set(credentialsKey, raw.Credentials, nil)
  786. tx.Set(settingsKey, raw.Settings, nil)
  787. var creds AccountCredentials
  788. // XXX we shouldn't do (de)serialization inside the txn,
  789. // but this is like 2 usec on my system
  790. json.Unmarshal([]byte(raw.Credentials), &creds)
  791. for _, cert := range creds.Certfps {
  792. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  793. tx.Set(certFPKey, casefoldedAccount, nil)
  794. }
  795. return nil
  796. })
  797. if err == nil {
  798. am.Lock()
  799. am.nickToAccount[casefoldedAccount] = casefoldedAccount
  800. am.skeletonToAccount[skeleton] = casefoldedAccount
  801. am.Unlock()
  802. }
  803. }()
  804. if err != nil {
  805. return err
  806. }
  807. nick := "[server admin]"
  808. if client != nil {
  809. nick = client.Nick()
  810. }
  811. am.server.logger.Info("accounts", "client", nick, "registered account", account)
  812. raw.Verified = true
  813. clientAccount, err := am.deserializeRawAccount(raw, casefoldedAccount)
  814. if err != nil {
  815. return err
  816. }
  817. if client != nil {
  818. am.Login(client, clientAccount)
  819. if client.AlwaysOn() {
  820. client.markDirty(IncludeRealname)
  821. }
  822. }
  823. // we may need to do nick enforcement here:
  824. _, method := am.EnforcementStatus(casefoldedAccount, skeleton)
  825. if method == NickEnforcementStrict {
  826. currentClient := am.server.clients.Get(casefoldedAccount)
  827. if currentClient != nil && currentClient != client && currentClient.Account() != casefoldedAccount {
  828. am.server.RandomlyRename(currentClient)
  829. }
  830. }
  831. return nil
  832. }
  833. // register and verify an account, for internal use
  834. func (am *AccountManager) SARegister(account, passphrase string) (err error) {
  835. err = am.Register(nil, account, "admin", "", passphrase, "")
  836. if err == nil {
  837. err = am.Verify(nil, account, "")
  838. }
  839. return
  840. }
  841. type EmailChangeRecord struct {
  842. TimeCreated time.Time
  843. Code string
  844. Email string
  845. }
  846. func (am *AccountManager) NsSetEmail(client *Client, emailAddr string) (err error) {
  847. casefoldedAccount := client.Account()
  848. if casefoldedAccount == "" {
  849. return errAccountNotLoggedIn
  850. }
  851. if am.touchRegisterThrottle() {
  852. am.server.logger.Warning("accounts", "global registration throttle exceeded by client changing email", client.Nick())
  853. return errLimitExceeded
  854. }
  855. config := am.server.Config()
  856. if !config.Accounts.Registration.EmailVerification.Enabled {
  857. return errFeatureDisabled // redundant check, just in case
  858. }
  859. record := EmailChangeRecord{
  860. TimeCreated: time.Now().UTC(),
  861. Code: utils.GenerateSecretToken(),
  862. Email: emailAddr,
  863. }
  864. recordKey := fmt.Sprintf(keyAccountEmailChange, casefoldedAccount)
  865. recordBytes, _ := json.Marshal(record)
  866. recordVal := string(recordBytes)
  867. am.server.store.Update(func(tx *buntdb.Tx) error {
  868. tx.Set(recordKey, recordVal, nil)
  869. return nil
  870. })
  871. if err != nil {
  872. return err
  873. }
  874. message := email.ComposeMail(config.Accounts.Registration.EmailVerification,
  875. emailAddr,
  876. fmt.Sprintf(client.t("Verify your change of e-mail address on %s"), am.server.name))
  877. message.WriteString(fmt.Sprintf(client.t("To confirm your change of e-mail address on %s, issue the following command:"), am.server.name))
  878. message.WriteString("\r\n")
  879. fmt.Fprintf(&message, "/MSG NickServ VERIFYEMAIL %s\r\n", record.Code)
  880. err = email.SendMail(config.Accounts.Registration.EmailVerification, emailAddr, message.Bytes())
  881. if err == nil {
  882. am.server.logger.Info("services",
  883. fmt.Sprintf("email change verification sent for account %s", casefoldedAccount))
  884. return
  885. } else {
  886. am.server.logger.Error("internal", "Failed to dispatch e-mail change verification to", emailAddr, err.Error())
  887. return &registrationCallbackError{err}
  888. }
  889. }
  890. func (am *AccountManager) NsVerifyEmail(client *Client, code string) (err error) {
  891. casefoldedAccount := client.Account()
  892. if casefoldedAccount == "" {
  893. return errAccountNotLoggedIn
  894. }
  895. var record EmailChangeRecord
  896. success := false
  897. key := fmt.Sprintf(keyAccountEmailChange, casefoldedAccount)
  898. ttl := time.Duration(am.server.Config().Accounts.Registration.VerifyTimeout)
  899. am.server.store.Update(func(tx *buntdb.Tx) error {
  900. rawStr, err := tx.Get(key)
  901. if err == nil && rawStr != "" {
  902. err := json.Unmarshal([]byte(rawStr), &record)
  903. if err == nil {
  904. if (ttl == 0 || time.Since(record.TimeCreated) < ttl) && utils.SecretTokensMatch(record.Code, code) {
  905. success = true
  906. tx.Delete(key)
  907. }
  908. }
  909. }
  910. return nil
  911. })
  912. if !success {
  913. return errAccountVerificationInvalidCode
  914. }
  915. munger := func(in AccountSettings) (out AccountSettings, err error) {
  916. out = in
  917. out.Email = record.Email
  918. return
  919. }
  920. _, err = am.ModifyAccountSettings(casefoldedAccount, munger)
  921. return
  922. }
  923. func (am *AccountManager) NsSendpass(client *Client, accountName string) (err error) {
  924. config := am.server.Config()
  925. if !(config.Accounts.Registration.EmailVerification.Enabled && config.Accounts.Registration.EmailVerification.PasswordReset.Enabled) {
  926. return errFeatureDisabled
  927. }
  928. account, err := am.LoadAccount(accountName)
  929. if err != nil {
  930. return err
  931. }
  932. if !account.Verified {
  933. return errAccountUnverified
  934. }
  935. if account.Suspended != nil {
  936. return errAccountSuspended
  937. }
  938. if account.Settings.Email == "" {
  939. return errValidEmailRequired
  940. }
  941. record := PasswordResetRecord{
  942. TimeCreated: time.Now().UTC(),
  943. Code: utils.GenerateSecretToken(),
  944. }
  945. recordKey := fmt.Sprintf(keyAccountPwReset, account.NameCasefolded)
  946. recordBytes, _ := json.Marshal(record)
  947. recordVal := string(recordBytes)
  948. am.server.store.Update(func(tx *buntdb.Tx) error {
  949. recStr, recErr := tx.Get(recordKey)
  950. if recErr == nil && recStr != "" {
  951. var existing PasswordResetRecord
  952. jErr := json.Unmarshal([]byte(recStr), &existing)
  953. cooldown := time.Duration(config.Accounts.Registration.EmailVerification.PasswordReset.Cooldown)
  954. if jErr == nil && time.Since(existing.TimeCreated) < cooldown {
  955. err = errLimitExceeded
  956. return nil
  957. }
  958. }
  959. tx.Set(recordKey, recordVal, &buntdb.SetOptions{
  960. Expires: true,
  961. TTL: time.Duration(config.Accounts.Registration.EmailVerification.PasswordReset.Timeout),
  962. })
  963. return nil
  964. })
  965. if err != nil {
  966. return
  967. }
  968. subject := fmt.Sprintf(client.t("Reset your password on %s"), am.server.name)
  969. message := email.ComposeMail(config.Accounts.Registration.EmailVerification, account.Settings.Email, subject)
  970. fmt.Fprintf(&message, client.t("We received a request to reset your password on %[1]s for account: %[2]s"), am.server.name, account.Name)
  971. message.WriteString("\r\n")
  972. fmt.Fprintf(&message, client.t("If you did not initiate this request, you can safely ignore this message."))
  973. message.WriteString("\r\n")
  974. message.WriteString("\r\n")
  975. message.WriteString(client.t("Otherwise, to reset your password, issue the following command (replace `new_password` with your desired password):"))
  976. message.WriteString("\r\n")
  977. fmt.Fprintf(&message, "/MSG NickServ RESETPASS %s %s new_password\r\n", account.Name, record.Code)
  978. err = email.SendMail(config.Accounts.Registration.EmailVerification, account.Settings.Email, message.Bytes())
  979. if err == nil {
  980. am.server.logger.Info("services",
  981. fmt.Sprintf("client %s sent a password reset email for account %s", client.Nick(), account.Name))
  982. } else {
  983. am.server.logger.Error("internal", "Failed to dispatch e-mail to", account.Settings.Email, err.Error())
  984. }
  985. return
  986. }
  987. func (am *AccountManager) NsResetpass(client *Client, accountName, code, password string) (err error) {
  988. if ValidatePassphrase(password) != nil {
  989. return errAccountBadPassphrase
  990. }
  991. account, err := am.LoadAccount(accountName)
  992. if err != nil {
  993. return
  994. }
  995. if !account.Verified {
  996. return errAccountUnverified
  997. }
  998. if account.Suspended != nil {
  999. return errAccountSuspended
  1000. }
  1001. success := false
  1002. key := fmt.Sprintf(keyAccountPwReset, account.NameCasefolded)
  1003. am.server.store.Update(func(tx *buntdb.Tx) error {
  1004. rawStr, err := tx.Get(key)
  1005. if err == nil && rawStr != "" {
  1006. var record PasswordResetRecord
  1007. err := json.Unmarshal([]byte(rawStr), &record)
  1008. if err == nil && utils.SecretTokensMatch(record.Code, code) {
  1009. success = true
  1010. tx.Delete(key)
  1011. }
  1012. }
  1013. return nil
  1014. })
  1015. if success {
  1016. return am.setPassword(accountName, password, true)
  1017. } else {
  1018. return errAccountInvalidCredentials
  1019. }
  1020. }
  1021. type PasswordResetRecord struct {
  1022. TimeCreated time.Time
  1023. Code string
  1024. }
  1025. func marshalReservedNicks(nicks []string) string {
  1026. return strings.Join(nicks, ",")
  1027. }
  1028. func unmarshalReservedNicks(nicks string) (result []string) {
  1029. if nicks == "" {
  1030. return
  1031. }
  1032. return strings.Split(nicks, ",")
  1033. }
  1034. func (am *AccountManager) SetNickReserved(client *Client, nick string, saUnreserve bool, reserve bool) error {
  1035. cfnick, err := CasefoldName(nick)
  1036. skeleton, skerr := Skeleton(nick)
  1037. // garbage nick, or garbage options, or disabled
  1038. nrconfig := am.server.Config().Accounts.NickReservation
  1039. if err != nil || skerr != nil || cfnick == "" || (reserve && saUnreserve) || !nrconfig.Enabled {
  1040. return errAccountNickReservationFailed
  1041. }
  1042. // the cache is in sync with the DB while we hold serialCacheUpdateMutex
  1043. am.serialCacheUpdateMutex.Lock()
  1044. defer am.serialCacheUpdateMutex.Unlock()
  1045. // find the affected account, which is usually the client's:
  1046. account := client.Account()
  1047. if saUnreserve {
  1048. // unless this is a sadrop:
  1049. account := func() string {
  1050. am.RLock()
  1051. defer am.RUnlock()
  1052. return am.nickToAccount[cfnick]
  1053. }()
  1054. if account == "" {
  1055. // nothing to do
  1056. return nil
  1057. }
  1058. }
  1059. if account == "" {
  1060. return errAccountNotLoggedIn
  1061. }
  1062. am.Lock()
  1063. accountForNick := am.nickToAccount[cfnick]
  1064. var accountForSkeleton string
  1065. if reserve {
  1066. accountForSkeleton = am.skeletonToAccount[skeleton]
  1067. }
  1068. am.Unlock()
  1069. if reserve && (accountForNick != "" || accountForSkeleton != "") {
  1070. return errNicknameReserved
  1071. } else if !reserve && !saUnreserve && accountForNick != account {
  1072. return errNicknameReserved
  1073. } else if !reserve && cfnick == account {
  1074. return errAccountCantDropPrimaryNick
  1075. }
  1076. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, account)
  1077. unverifiedAccountKey := fmt.Sprintf(keyAccountExists, cfnick)
  1078. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1079. if reserve {
  1080. // unverified accounts don't show up in NickToAccount yet (which is intentional),
  1081. // however you shouldn't be able to reserve a nick out from under them
  1082. _, err := tx.Get(unverifiedAccountKey)
  1083. if err == nil {
  1084. return errNicknameReserved
  1085. }
  1086. }
  1087. rawNicks, err := tx.Get(nicksKey)
  1088. if err != nil && err != buntdb.ErrNotFound {
  1089. return err
  1090. }
  1091. nicks := unmarshalReservedNicks(rawNicks)
  1092. if reserve {
  1093. if len(nicks) >= nrconfig.AdditionalNickLimit {
  1094. return errAccountTooManyNicks
  1095. }
  1096. nicks = append(nicks, nick)
  1097. } else {
  1098. // compute (original reserved nicks) minus cfnick
  1099. var newNicks []string
  1100. for _, reservedNick := range nicks {
  1101. cfreservednick, _ := CasefoldName(reservedNick)
  1102. if cfreservednick != cfnick {
  1103. newNicks = append(newNicks, reservedNick)
  1104. } else {
  1105. // found the original, unfolded version of the nick we're dropping;
  1106. // recompute the true skeleton from it
  1107. skeleton, _ = Skeleton(reservedNick)
  1108. }
  1109. }
  1110. nicks = newNicks
  1111. }
  1112. marshaledNicks := marshalReservedNicks(nicks)
  1113. _, _, err = tx.Set(nicksKey, string(marshaledNicks), nil)
  1114. return err
  1115. })
  1116. if err == errAccountTooManyNicks || err == errNicknameReserved {
  1117. return err
  1118. } else if err != nil {
  1119. return errAccountNickReservationFailed
  1120. }
  1121. // success
  1122. am.Lock()
  1123. defer am.Unlock()
  1124. if reserve {
  1125. am.nickToAccount[cfnick] = account
  1126. am.skeletonToAccount[skeleton] = account
  1127. } else {
  1128. delete(am.nickToAccount, cfnick)
  1129. delete(am.skeletonToAccount, skeleton)
  1130. }
  1131. return nil
  1132. }
  1133. func (am *AccountManager) checkPassphrase(accountName, passphrase string) (account ClientAccount, err error) {
  1134. account, err = am.LoadAccount(accountName)
  1135. // #1476: if grouped nicks are allowed, attempt to interpret accountName as a grouped nick
  1136. if err == errAccountDoesNotExist && !am.server.Config().Accounts.NickReservation.ForceNickEqualsAccount {
  1137. cfnick, cfErr := CasefoldName(accountName)
  1138. if cfErr != nil {
  1139. return
  1140. }
  1141. accountName = func() string {
  1142. am.RLock()
  1143. defer am.RUnlock()
  1144. return am.nickToAccount[cfnick]
  1145. }()
  1146. if accountName != "" {
  1147. account, err = am.LoadAccount(accountName)
  1148. }
  1149. }
  1150. if err != nil {
  1151. return
  1152. }
  1153. if !account.Verified {
  1154. err = errAccountUnverified
  1155. return
  1156. } else if account.Suspended != nil {
  1157. err = errAccountSuspended
  1158. return
  1159. }
  1160. switch account.Credentials.Version {
  1161. case 0:
  1162. err = am.checkLegacyPassphrase(migrations.CheckOragonoPassphraseV0, accountName, account.Credentials.PassphraseHash, passphrase)
  1163. case 1:
  1164. if passwd.CompareHashAndPassword(account.Credentials.PassphraseHash, []byte(passphrase)) != nil {
  1165. err = errAccountInvalidCredentials
  1166. }
  1167. if err == nil && account.Credentials.SCRAMCreds.Iters == 0 {
  1168. // XXX: if the account was created prior to 2.8, it doesn't have SCRAM credentials;
  1169. // since we temporarily have access to a valid plaintext password, create them:
  1170. am.rehashPassword(account.Name, passphrase)
  1171. }
  1172. case -1:
  1173. err = am.checkLegacyPassphrase(migrations.CheckAthemePassphrase, accountName, account.Credentials.PassphraseHash, passphrase)
  1174. case -2:
  1175. err = am.checkLegacyPassphrase(migrations.CheckAnopePassphrase, accountName, account.Credentials.PassphraseHash, passphrase)
  1176. default:
  1177. err = errAccountInvalidCredentials
  1178. }
  1179. return
  1180. }
  1181. func (am *AccountManager) checkLegacyPassphrase(check migrations.PassphraseCheck, account string, hash []byte, passphrase string) (err error) {
  1182. err = check(hash, []byte(passphrase))
  1183. if err != nil {
  1184. if err == migrations.ErrHashInvalid {
  1185. am.server.logger.Error("internal", "invalid legacy credentials for account", account)
  1186. }
  1187. return errAccountInvalidCredentials
  1188. }
  1189. // re-hash the passphrase with the latest algorithm
  1190. am.rehashPassword(account, passphrase)
  1191. return nil
  1192. }
  1193. func (am *AccountManager) rehashPassword(accountName, passphrase string) {
  1194. err := am.setPassword(accountName, passphrase, true)
  1195. if err != nil {
  1196. am.server.logger.Error("internal", "could not upgrade user password", accountName, err.Error())
  1197. }
  1198. }
  1199. func (am *AccountManager) loadWithAutocreation(accountName string, autocreate bool) (account ClientAccount, err error) {
  1200. account, err = am.LoadAccount(accountName)
  1201. if err == errAccountDoesNotExist && autocreate {
  1202. err = am.SARegister(accountName, "")
  1203. if err != nil {
  1204. return
  1205. }
  1206. account, err = am.LoadAccount(accountName)
  1207. }
  1208. return
  1209. }
  1210. func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) (err error) {
  1211. // XXX check this now, so we don't allow a redundant login for an always-on client
  1212. // even for a brief period. the other potential source of nick-account conflicts
  1213. // is from force-nick-equals-account, but those will be caught later by
  1214. // fixupNickEqualsAccount and if there is a conflict, they will be logged out.
  1215. if client.registered {
  1216. if clientAlready := am.server.clients.Get(accountName); clientAlready != nil && clientAlready.AlwaysOn() {
  1217. return errNickAccountMismatch
  1218. }
  1219. }
  1220. if throttled, remainingTime := client.checkLoginThrottle(); throttled {
  1221. return &ThrottleError{remainingTime}
  1222. }
  1223. var account ClientAccount
  1224. defer func() {
  1225. if err == nil {
  1226. am.Login(client, account)
  1227. }
  1228. }()
  1229. config := am.server.Config()
  1230. if config.Accounts.AuthScript.Enabled {
  1231. var output AuthScriptOutput
  1232. output, err = CheckAuthScript(am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
  1233. AuthScriptInput{AccountName: accountName, Passphrase: passphrase, IP: client.IP().String()})
  1234. if err != nil {
  1235. am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
  1236. } else if output.Success {
  1237. if output.AccountName != "" {
  1238. accountName = output.AccountName
  1239. }
  1240. account, err = am.loadWithAutocreation(accountName, config.Accounts.AuthScript.Autocreate)
  1241. return
  1242. }
  1243. }
  1244. account, err = am.checkPassphrase(accountName, passphrase)
  1245. return err
  1246. }
  1247. // AllNicks returns the uncasefolded nicknames for all accounts, including additional (grouped) nicks.
  1248. func (am *AccountManager) AllNicks() (result []string) {
  1249. accountNamePrefix := fmt.Sprintf(keyAccountName, "")
  1250. accountAdditionalNicksPrefix := fmt.Sprintf(keyAccountAdditionalNicks, "")
  1251. am.server.store.View(func(tx *buntdb.Tx) error {
  1252. // Account names
  1253. err := tx.AscendGreaterOrEqual("", accountNamePrefix, func(key, value string) bool {
  1254. if !strings.HasPrefix(key, accountNamePrefix) {
  1255. return false
  1256. }
  1257. result = append(result, value)
  1258. return true
  1259. })
  1260. if err != nil {
  1261. return err
  1262. }
  1263. // Additional nicks
  1264. return tx.AscendGreaterOrEqual("", accountAdditionalNicksPrefix, func(key, value string) bool {
  1265. if !strings.HasPrefix(key, accountAdditionalNicksPrefix) {
  1266. return false
  1267. }
  1268. additionalNicks := unmarshalReservedNicks(value)
  1269. for _, additionalNick := range additionalNicks {
  1270. result = append(result, additionalNick)
  1271. }
  1272. return true
  1273. })
  1274. })
  1275. sort.Strings(result)
  1276. return
  1277. }
  1278. func (am *AccountManager) LoadAccount(accountName string) (result ClientAccount, err error) {
  1279. casefoldedAccount, err := CasefoldName(accountName)
  1280. if err != nil {
  1281. err = errAccountDoesNotExist
  1282. return
  1283. }
  1284. var raw rawClientAccount
  1285. am.server.store.View(func(tx *buntdb.Tx) error {
  1286. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  1287. return nil
  1288. })
  1289. if err != nil {
  1290. return
  1291. }
  1292. result, err = am.deserializeRawAccount(raw, casefoldedAccount)
  1293. return
  1294. }
  1295. // look up the unfolded version of an account name, possibly after deletion
  1296. func (am *AccountManager) AccountToAccountName(account string) (result string) {
  1297. casefoldedAccount, err := CasefoldName(account)
  1298. if err != nil {
  1299. return
  1300. }
  1301. unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
  1302. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1303. am.server.store.View(func(tx *buntdb.Tx) error {
  1304. if name, err := tx.Get(accountNameKey); err == nil {
  1305. result = name
  1306. return nil
  1307. }
  1308. if name, err := tx.Get(unregisteredKey); err == nil {
  1309. result = name
  1310. }
  1311. return nil
  1312. })
  1313. return
  1314. }
  1315. func (am *AccountManager) deserializeRawAccount(raw rawClientAccount, cfName string) (result ClientAccount, err error) {
  1316. result.Name = raw.Name
  1317. result.NameCasefolded = cfName
  1318. regTimeInt, _ := strconv.ParseInt(raw.RegisteredAt, 10, 64)
  1319. result.RegisteredAt = time.Unix(0, regTimeInt).UTC()
  1320. e := json.Unmarshal([]byte(raw.Credentials), &result.Credentials)
  1321. if e != nil {
  1322. am.server.logger.Error("internal", "could not unmarshal credentials", e.Error())
  1323. err = errAccountDoesNotExist
  1324. return
  1325. }
  1326. result.AdditionalNicks = unmarshalReservedNicks(raw.AdditionalNicks)
  1327. result.Verified = raw.Verified
  1328. if raw.VHost != "" {
  1329. e := json.Unmarshal([]byte(raw.VHost), &result.VHost)
  1330. if e != nil {
  1331. am.server.logger.Warning("internal", "could not unmarshal vhost for account", result.Name, e.Error())
  1332. // pretend they have no vhost and move on
  1333. }
  1334. }
  1335. if raw.Settings != "" {
  1336. e := json.Unmarshal([]byte(raw.Settings), &result.Settings)
  1337. if e != nil {
  1338. am.server.logger.Warning("internal", "could not unmarshal settings for account", result.Name, e.Error())
  1339. }
  1340. }
  1341. if raw.Suspended != "" {
  1342. sus := new(AccountSuspension)
  1343. e := json.Unmarshal([]byte(raw.Suspended), sus)
  1344. if e != nil {
  1345. am.server.logger.Error("internal", "corrupt suspension data", result.Name, e.Error())
  1346. } else {
  1347. result.Suspended = sus
  1348. }
  1349. }
  1350. return
  1351. }
  1352. func (am *AccountManager) loadRawAccount(tx *buntdb.Tx, casefoldedAccount string) (result rawClientAccount, err error) {
  1353. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  1354. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1355. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  1356. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  1357. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  1358. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  1359. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  1360. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1361. suspendedKey := fmt.Sprintf(keyAccountSuspended, casefoldedAccount)
  1362. _, e := tx.Get(accountKey)
  1363. if e == buntdb.ErrNotFound {
  1364. err = errAccountDoesNotExist
  1365. return
  1366. }
  1367. result.Name, _ = tx.Get(accountNameKey)
  1368. result.RegisteredAt, _ = tx.Get(registeredTimeKey)
  1369. result.Credentials, _ = tx.Get(credentialsKey)
  1370. result.AdditionalNicks, _ = tx.Get(nicksKey)
  1371. result.VHost, _ = tx.Get(vhostKey)
  1372. result.Settings, _ = tx.Get(settingsKey)
  1373. result.Suspended, _ = tx.Get(suspendedKey)
  1374. if _, e = tx.Get(verifiedKey); e == nil {
  1375. result.Verified = true
  1376. }
  1377. return
  1378. }
  1379. type AccountSuspension struct {
  1380. AccountName string `json:"AccountName,omitempty"`
  1381. TimeCreated time.Time
  1382. Duration time.Duration
  1383. OperName string
  1384. Reason string
  1385. }
  1386. func (am *AccountManager) Suspend(accountName string, duration time.Duration, operName, reason string) (err error) {
  1387. account, err := CasefoldName(accountName)
  1388. if err != nil {
  1389. return errAccountDoesNotExist
  1390. }
  1391. suspension := AccountSuspension{
  1392. TimeCreated: time.Now().UTC(),
  1393. Duration: duration,
  1394. OperName: operName,
  1395. Reason: reason,
  1396. }
  1397. suspensionStr, err := json.Marshal(suspension)
  1398. if err != nil {
  1399. am.server.logger.Error("internal", "suspension json unserializable", err.Error())
  1400. return errAccountDoesNotExist
  1401. }
  1402. existsKey := fmt.Sprintf(keyAccountExists, account)
  1403. suspensionKey := fmt.Sprintf(keyAccountSuspended, account)
  1404. var setOptions *buntdb.SetOptions
  1405. if duration != time.Duration(0) {
  1406. setOptions = &buntdb.SetOptions{Expires: true, TTL: duration}
  1407. }
  1408. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1409. _, err := tx.Get(existsKey)
  1410. if err != nil {
  1411. return errAccountDoesNotExist
  1412. }
  1413. _, _, err = tx.Set(suspensionKey, string(suspensionStr), setOptions)
  1414. return err
  1415. })
  1416. if err == errAccountDoesNotExist {
  1417. return err
  1418. } else if err != nil {
  1419. am.server.logger.Error("internal", "couldn't persist suspension", account, err.Error())
  1420. } // keep going
  1421. am.Lock()
  1422. clients := am.accountToClients[account]
  1423. delete(am.accountToClients, account)
  1424. am.Unlock()
  1425. // kill clients, sending them the reason
  1426. suspension.AccountName = accountName
  1427. for _, client := range clients {
  1428. client.Logout()
  1429. client.Quit(suspensionToString(client, suspension), nil)
  1430. client.destroy(nil)
  1431. }
  1432. return nil
  1433. }
  1434. func (am *AccountManager) killClients(clients []*Client) {
  1435. for _, client := range clients {
  1436. client.Logout()
  1437. client.Quit(client.t("You are no longer authorized to be on this server"), nil)
  1438. client.destroy(nil)
  1439. }
  1440. }
  1441. func (am *AccountManager) Unsuspend(accountName string) (err error) {
  1442. cfaccount, err := CasefoldName(accountName)
  1443. if err != nil {
  1444. return errAccountDoesNotExist
  1445. }
  1446. existsKey := fmt.Sprintf(keyAccountExists, cfaccount)
  1447. suspensionKey := fmt.Sprintf(keyAccountSuspended, cfaccount)
  1448. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1449. _, err := tx.Get(existsKey)
  1450. if err != nil {
  1451. return errAccountDoesNotExist
  1452. }
  1453. _, err = tx.Delete(suspensionKey)
  1454. if err != nil {
  1455. return errNoop
  1456. }
  1457. return nil
  1458. })
  1459. return err
  1460. }
  1461. func (am *AccountManager) ListSuspended() (result []AccountSuspension) {
  1462. var names []string
  1463. var raw []string
  1464. prefix := fmt.Sprintf(keyAccountSuspended, "")
  1465. am.server.store.View(func(tx *buntdb.Tx) error {
  1466. err := tx.AscendGreaterOrEqual("", prefix, func(key, value string) bool {
  1467. if !strings.HasPrefix(key, prefix) {
  1468. return false
  1469. }
  1470. raw = append(raw, value)
  1471. cfname := strings.TrimPrefix(key, prefix)
  1472. name, _ := tx.Get(fmt.Sprintf(keyAccountName, cfname))
  1473. names = append(names, name)
  1474. return true
  1475. })
  1476. return err
  1477. })
  1478. result = make([]AccountSuspension, 0, len(raw))
  1479. for i := 0; i < len(raw); i++ {
  1480. var sus AccountSuspension
  1481. err := json.Unmarshal([]byte(raw[i]), &sus)
  1482. if err != nil {
  1483. am.server.logger.Error("internal", "corrupt data for suspension", names[i], err.Error())
  1484. continue
  1485. }
  1486. sus.AccountName = names[i]
  1487. result = append(result, sus)
  1488. }
  1489. return
  1490. }
  1491. // renames an account (within very restrictive limits); see #1380
  1492. func (am *AccountManager) Rename(oldName, newName string) (err error) {
  1493. accountData, err := am.LoadAccount(oldName)
  1494. if err != nil {
  1495. return
  1496. }
  1497. newCfName, err := CasefoldName(newName)
  1498. if err != nil {
  1499. return errNicknameInvalid
  1500. }
  1501. if newCfName != accountData.NameCasefolded {
  1502. return errInvalidAccountRename
  1503. }
  1504. key := fmt.Sprintf(keyAccountName, accountData.NameCasefolded)
  1505. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1506. tx.Set(key, newName, nil)
  1507. return nil
  1508. })
  1509. if err != nil {
  1510. return err
  1511. }
  1512. am.RLock()
  1513. defer am.RUnlock()
  1514. for _, client := range am.accountToClients[accountData.NameCasefolded] {
  1515. client.setAccountName(newName)
  1516. }
  1517. return nil
  1518. }
  1519. func (am *AccountManager) Unregister(account string, erase bool) error {
  1520. config := am.server.Config()
  1521. casefoldedAccount, err := CasefoldName(account)
  1522. if err != nil {
  1523. return errAccountDoesNotExist
  1524. }
  1525. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  1526. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  1527. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  1528. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  1529. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  1530. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  1531. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  1532. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1533. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  1534. channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
  1535. joinedChannelsKey := fmt.Sprintf(keyAccountChannelToModes, casefoldedAccount)
  1536. lastSeenKey := fmt.Sprintf(keyAccountLastSeen, casefoldedAccount)
  1537. unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
  1538. modesKey := fmt.Sprintf(keyAccountModes, casefoldedAccount)
  1539. realnameKey := fmt.Sprintf(keyAccountRealname, casefoldedAccount)
  1540. suspendedKey := fmt.Sprintf(keyAccountSuspended, casefoldedAccount)
  1541. pwResetKey := fmt.Sprintf(keyAccountPwReset, casefoldedAccount)
  1542. emailChangeKey := fmt.Sprintf(keyAccountEmailChange, casefoldedAccount)
  1543. var clients []*Client
  1544. defer func() {
  1545. am.killClients(clients)
  1546. }()
  1547. var registeredChannels []string
  1548. // on our way out, unregister all the account's channels and delete them from the db
  1549. defer func() {
  1550. for _, channelName := range registeredChannels {
  1551. err := am.server.channels.SetUnregistered(channelName, casefoldedAccount)
  1552. if err != nil {
  1553. am.server.logger.Error("internal", "couldn't unregister channel", channelName, err.Error())
  1554. }
  1555. }
  1556. }()
  1557. var credText string
  1558. var rawNicks string
  1559. am.serialCacheUpdateMutex.Lock()
  1560. defer am.serialCacheUpdateMutex.Unlock()
  1561. var accountName string
  1562. var channelsStr string
  1563. keepProtections := false
  1564. am.server.store.Update(func(tx *buntdb.Tx) error {
  1565. // get the unfolded account name; for an active account, this is
  1566. // stored under accountNameKey, for an unregistered account under unregisteredKey
  1567. accountName, _ = tx.Get(accountNameKey)
  1568. if accountName == "" {
  1569. accountName, _ = tx.Get(unregisteredKey)
  1570. }
  1571. if erase {
  1572. tx.Delete(unregisteredKey)
  1573. } else {
  1574. if _, err := tx.Get(verifiedKey); err == nil {
  1575. tx.Set(unregisteredKey, accountName, nil)
  1576. keepProtections = true
  1577. }
  1578. }
  1579. tx.Delete(accountKey)
  1580. tx.Delete(accountNameKey)
  1581. tx.Delete(verifiedKey)
  1582. tx.Delete(registeredTimeKey)
  1583. tx.Delete(verificationCodeKey)
  1584. tx.Delete(settingsKey)
  1585. rawNicks, _ = tx.Get(nicksKey)
  1586. tx.Delete(nicksKey)
  1587. credText, err = tx.Get(credentialsKey)
  1588. tx.Delete(credentialsKey)
  1589. tx.Delete(vhostKey)
  1590. channelsStr, _ = tx.Get(channelsKey)
  1591. tx.Delete(channelsKey)
  1592. tx.Delete(joinedChannelsKey)
  1593. tx.Delete(lastSeenKey)
  1594. tx.Delete(modesKey)
  1595. tx.Delete(realnameKey)
  1596. tx.Delete(suspendedKey)
  1597. tx.Delete(pwResetKey)
  1598. tx.Delete(emailChangeKey)
  1599. return nil
  1600. })
  1601. if err == nil {
  1602. var creds AccountCredentials
  1603. if err := json.Unmarshal([]byte(credText), &creds); err == nil {
  1604. for _, cert := range creds.Certfps {
  1605. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  1606. am.server.store.Update(func(tx *buntdb.Tx) error {
  1607. if account, err := tx.Get(certFPKey); err == nil && account == casefoldedAccount {
  1608. tx.Delete(certFPKey)
  1609. }
  1610. return nil
  1611. })
  1612. }
  1613. }
  1614. }
  1615. skeleton, _ := Skeleton(accountName)
  1616. additionalNicks := unmarshalReservedNicks(rawNicks)
  1617. registeredChannels = unmarshalRegisteredChannels(channelsStr)
  1618. am.Lock()
  1619. defer am.Unlock()
  1620. clients = am.accountToClients[casefoldedAccount]
  1621. delete(am.accountToClients, casefoldedAccount)
  1622. // protect the account name itself where applicable, but not any grouped nicks
  1623. if !(keepProtections && config.Accounts.NickReservation.Method == NickEnforcementStrict) {
  1624. delete(am.nickToAccount, casefoldedAccount)
  1625. delete(am.skeletonToAccount, skeleton)
  1626. }
  1627. for _, nick := range additionalNicks {
  1628. delete(am.nickToAccount, nick)
  1629. additionalSkel, _ := Skeleton(nick)
  1630. delete(am.skeletonToAccount, additionalSkel)
  1631. }
  1632. if err != nil && !erase {
  1633. return errAccountDoesNotExist
  1634. }
  1635. return nil
  1636. }
  1637. func unmarshalRegisteredChannels(channelsStr string) (result []string) {
  1638. if channelsStr != "" {
  1639. result = strings.Split(channelsStr, ",")
  1640. }
  1641. return
  1642. }
  1643. func (am *AccountManager) ChannelsForAccount(account string) (channels []string) {
  1644. cfaccount, err := CasefoldName(account)
  1645. if err != nil {
  1646. return
  1647. }
  1648. var channelStr string
  1649. key := fmt.Sprintf(keyAccountChannels, cfaccount)
  1650. am.server.store.View(func(tx *buntdb.Tx) error {
  1651. channelStr, _ = tx.Get(key)
  1652. return nil
  1653. })
  1654. return unmarshalRegisteredChannels(channelStr)
  1655. }
  1656. func (am *AccountManager) AuthenticateByCertificate(client *Client, certfp string, peerCerts []*x509.Certificate, authzid string) (err error) {
  1657. if certfp == "" {
  1658. return errAccountInvalidCredentials
  1659. }
  1660. var clientAccount ClientAccount
  1661. defer func() {
  1662. if err != nil {
  1663. return
  1664. } else if !clientAccount.Verified {
  1665. err = errAccountUnverified
  1666. return
  1667. } else if clientAccount.Suspended != nil {
  1668. err = errAccountSuspended
  1669. return
  1670. }
  1671. // TODO(#1109) clean this check up?
  1672. if client.registered {
  1673. if clientAlready := am.server.clients.Get(clientAccount.Name); clientAlready != nil && clientAlready.AlwaysOn() {
  1674. err = errNickAccountMismatch
  1675. return
  1676. }
  1677. }
  1678. am.Login(client, clientAccount)
  1679. return
  1680. }()
  1681. config := am.server.Config()
  1682. if config.Accounts.AuthScript.Enabled {
  1683. var output AuthScriptOutput
  1684. output, err = CheckAuthScript(am.server.semaphores.AuthScript, config.Accounts.AuthScript.ScriptConfig,
  1685. AuthScriptInput{Certfp: certfp, IP: client.IP().String(), peerCerts: peerCerts})
  1686. if err != nil {
  1687. am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
  1688. } else if output.Success && output.AccountName != "" {
  1689. clientAccount, err = am.loadWithAutocreation(output.AccountName, config.Accounts.AuthScript.Autocreate)
  1690. return
  1691. }
  1692. }
  1693. var account string
  1694. certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
  1695. err = am.server.store.View(func(tx *buntdb.Tx) error {
  1696. account, _ = tx.Get(certFPKey)
  1697. if account == "" {
  1698. return errAccountInvalidCredentials
  1699. }
  1700. return nil
  1701. })
  1702. if err != nil {
  1703. return err
  1704. }
  1705. if authzid != "" && authzid != account {
  1706. return errAuthzidAuthcidMismatch
  1707. }
  1708. // ok, we found an account corresponding to their certificate
  1709. clientAccount, err = am.LoadAccount(account)
  1710. return err
  1711. }
  1712. type settingsMunger func(input AccountSettings) (output AccountSettings, err error)
  1713. func (am *AccountManager) ModifyAccountSettings(account string, munger settingsMunger) (newSettings AccountSettings, err error) {
  1714. casefoldedAccount, err := CasefoldName(account)
  1715. if err != nil {
  1716. return newSettings, errAccountDoesNotExist
  1717. }
  1718. // TODO implement this in general via a compare-and-swap API
  1719. accountData, err := am.LoadAccount(casefoldedAccount)
  1720. if err != nil {
  1721. return
  1722. } else if !accountData.Verified {
  1723. return newSettings, errAccountUnverified
  1724. }
  1725. newSettings, err = munger(accountData.Settings)
  1726. if err != nil {
  1727. return
  1728. }
  1729. text, err := json.Marshal(newSettings)
  1730. if err != nil {
  1731. return
  1732. }
  1733. key := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1734. serializedValue := string(text)
  1735. err = am.server.store.Update(func(tx *buntdb.Tx) (err error) {
  1736. _, _, err = tx.Set(key, serializedValue, nil)
  1737. return
  1738. })
  1739. if err != nil {
  1740. err = errAccountUpdateFailed
  1741. return
  1742. }
  1743. // success, push new settings into the client objects
  1744. am.Lock()
  1745. defer am.Unlock()
  1746. for _, client := range am.accountToClients[casefoldedAccount] {
  1747. client.SetAccountSettings(newSettings)
  1748. }
  1749. return
  1750. }
  1751. // represents someone's status in hostserv
  1752. type VHostInfo struct {
  1753. ApprovedVHost string
  1754. Enabled bool
  1755. }
  1756. // callback type implementing the actual business logic of vhost operations
  1757. type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
  1758. func (am *AccountManager) VHostSet(account string, vhost string) (result VHostInfo, err error) {
  1759. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1760. output = input
  1761. output.Enabled = true
  1762. output.ApprovedVHost = vhost
  1763. return
  1764. }
  1765. return am.performVHostChange(account, munger)
  1766. }
  1767. func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (result VHostInfo, err error) {
  1768. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1769. if input.ApprovedVHost == "" {
  1770. err = errNoVhost
  1771. return
  1772. }
  1773. output = input
  1774. output.Enabled = enabled
  1775. return
  1776. }
  1777. return am.performVHostChange(client.Account(), munger)
  1778. }
  1779. func (am *AccountManager) performVHostChange(account string, munger vhostMunger) (result VHostInfo, err error) {
  1780. account, err = CasefoldName(account)
  1781. if err != nil || account == "" {
  1782. err = errAccountDoesNotExist
  1783. return
  1784. }
  1785. if am.server.Defcon() <= 3 {
  1786. err = errFeatureDisabled
  1787. return
  1788. }
  1789. clientAccount, err := am.LoadAccount(account)
  1790. if err != nil {
  1791. err = errAccountDoesNotExist
  1792. return
  1793. } else if !clientAccount.Verified {
  1794. err = errAccountUnverified
  1795. return
  1796. }
  1797. result, err = munger(clientAccount.VHost)
  1798. if err != nil {
  1799. return
  1800. }
  1801. vhtext, err := json.Marshal(result)
  1802. if err != nil {
  1803. err = errAccountUpdateFailed
  1804. return
  1805. }
  1806. vhstr := string(vhtext)
  1807. key := fmt.Sprintf(keyAccountVHost, account)
  1808. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1809. _, _, err := tx.Set(key, vhstr, nil)
  1810. return err
  1811. })
  1812. if err != nil {
  1813. err = errAccountUpdateFailed
  1814. return
  1815. }
  1816. am.applyVhostToClients(account, result)
  1817. return result, nil
  1818. }
  1819. func (am *AccountManager) applyVHostInfo(client *Client, info VHostInfo) {
  1820. // if hostserv is disabled in config, then don't grant vhosts
  1821. // that were previously approved while it was enabled
  1822. if !am.server.Config().Accounts.VHosts.Enabled {
  1823. return
  1824. }
  1825. vhost := ""
  1826. if info.Enabled {
  1827. vhost = info.ApprovedVHost
  1828. }
  1829. oldNickmask := client.NickMaskString()
  1830. updated := client.SetVHost(vhost)
  1831. if updated && client.Registered() {
  1832. // TODO: doing I/O here is kind of a kludge
  1833. client.sendChghost(oldNickmask, client.Hostname())
  1834. }
  1835. }
  1836. func (am *AccountManager) applyVhostToClients(account string, result VHostInfo) {
  1837. am.RLock()
  1838. clients := am.accountToClients[account]
  1839. am.RUnlock()
  1840. for _, client := range clients {
  1841. am.applyVHostInfo(client, result)
  1842. }
  1843. }
  1844. func (am *AccountManager) Login(client *Client, account ClientAccount) {
  1845. client.Login(account)
  1846. am.applyVHostInfo(client, account.VHost)
  1847. casefoldedAccount := client.Account()
  1848. am.Lock()
  1849. defer am.Unlock()
  1850. am.accountToClients[casefoldedAccount] = append(am.accountToClients[casefoldedAccount], client)
  1851. }
  1852. func (am *AccountManager) Logout(client *Client) {
  1853. am.Lock()
  1854. defer am.Unlock()
  1855. casefoldedAccount := client.Account()
  1856. if casefoldedAccount == "" {
  1857. return
  1858. }
  1859. client.Logout()
  1860. clients := am.accountToClients[casefoldedAccount]
  1861. if len(clients) <= 1 {
  1862. delete(am.accountToClients, casefoldedAccount)
  1863. return
  1864. }
  1865. remainingClients := make([]*Client, len(clients)-1)
  1866. remainingPos := 0
  1867. for currentPos := 0; currentPos < len(clients); currentPos++ {
  1868. if clients[currentPos] != client {
  1869. remainingClients[remainingPos] = clients[currentPos]
  1870. remainingPos++
  1871. }
  1872. }
  1873. am.accountToClients[casefoldedAccount] = remainingClients
  1874. }
  1875. var (
  1876. // EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
  1877. // This can be moved to some other data structure/place if we need to load/unload mechs later.
  1878. EnabledSaslMechanisms = map[string]func(*Server, *Client, *Session, []byte, *ResponseBuffer) bool{
  1879. "PLAIN": authPlainHandler,
  1880. "EXTERNAL": authExternalHandler,
  1881. "SCRAM-SHA-256": authScramHandler,
  1882. }
  1883. )
  1884. type CredentialsVersion int
  1885. const (
  1886. CredentialsLegacy CredentialsVersion = 0
  1887. CredentialsSHA3Bcrypt CredentialsVersion = 1
  1888. // negative numbers for migration
  1889. CredentialsAtheme = -1
  1890. CredentialsAnope = -2
  1891. )
  1892. type SCRAMCreds struct {
  1893. Salt []byte
  1894. Iters int
  1895. StoredKey []byte
  1896. ServerKey []byte
  1897. }
  1898. // AccountCredentials stores the various methods for verifying accounts.
  1899. type AccountCredentials struct {
  1900. Version CredentialsVersion
  1901. PassphraseHash []byte
  1902. Certfps []string
  1903. SCRAMCreds
  1904. }
  1905. func (ac *AccountCredentials) Empty() bool {
  1906. return len(ac.PassphraseHash) == 0 && len(ac.Certfps) == 0
  1907. }
  1908. // helper to assemble the serialized JSON for an account's credentials
  1909. func (ac *AccountCredentials) Serialize() (result string, err error) {
  1910. ac.Version = 1
  1911. credText, err := json.Marshal(*ac)
  1912. if err != nil {
  1913. return "", err
  1914. }
  1915. return string(credText), nil
  1916. }
  1917. func (ac *AccountCredentials) SetPassphrase(passphrase string, bcryptCost uint) (err error) {
  1918. if passphrase == "" {
  1919. ac.PassphraseHash = nil
  1920. ac.SCRAMCreds = SCRAMCreds{}
  1921. return nil
  1922. }
  1923. if ValidatePassphrase(passphrase) != nil {
  1924. return errAccountBadPassphrase
  1925. }
  1926. ac.PassphraseHash, err = passwd.GenerateFromPassword([]byte(passphrase), int(bcryptCost))
  1927. if err != nil {
  1928. return errAccountBadPassphrase
  1929. }
  1930. // we can pass an empty account name because it won't actually be incorporated
  1931. // into the credentials; it's just a quirk of the xdg-go/scram API that the way
  1932. // to produce server credentials is to call NewClient* and then GetStoredCredentials
  1933. scramClient, err := scram.SHA256.NewClientUnprepped("", passphrase, "")
  1934. if err != nil {
  1935. return errAccountBadPassphrase
  1936. }
  1937. salt := make([]byte, 16)
  1938. rand.Read(salt)
  1939. // xdg-go/scram says: "Clients have a default minimum PBKDF2 iteration count of 4096."
  1940. minIters := 4096
  1941. scramCreds := scramClient.GetStoredCredentials(scram.KeyFactors{Salt: string(salt), Iters: minIters})
  1942. ac.SCRAMCreds = SCRAMCreds{
  1943. Salt: salt,
  1944. Iters: minIters,
  1945. StoredKey: scramCreds.StoredKey,
  1946. ServerKey: scramCreds.ServerKey,
  1947. }
  1948. return nil
  1949. }
  1950. func (am *AccountManager) NewScramConversation() *scram.ServerConversation {
  1951. server, _ := scram.SHA256.NewServer(am.lookupSCRAMCreds)
  1952. return server.NewConversation()
  1953. }
  1954. func (am *AccountManager) lookupSCRAMCreds(accountName string) (creds scram.StoredCredentials, err error) {
  1955. // strip client ID if present:
  1956. if strudelIndex := strings.IndexByte(accountName, '@'); strudelIndex != -1 {
  1957. accountName = accountName[:strudelIndex]
  1958. }
  1959. acct, err := am.LoadAccount(accountName)
  1960. if err != nil {
  1961. return
  1962. }
  1963. if acct.Credentials.SCRAMCreds.Iters == 0 {
  1964. err = errNoSCRAMCredentials
  1965. return
  1966. }
  1967. creds.Salt = string(acct.Credentials.SCRAMCreds.Salt)
  1968. creds.Iters = acct.Credentials.SCRAMCreds.Iters
  1969. creds.StoredKey = acct.Credentials.SCRAMCreds.StoredKey
  1970. creds.ServerKey = acct.Credentials.SCRAMCreds.ServerKey
  1971. return
  1972. }
  1973. func (ac *AccountCredentials) AddCertfp(certfp string) (err error) {
  1974. // XXX we require that certfp is already normalized (rather than normalize here
  1975. // and pass back the normalized version as an additional return parameter);
  1976. // this is just a final sanity check:
  1977. if len(certfp) != 64 {
  1978. return utils.ErrInvalidCertfp
  1979. }
  1980. for _, current := range ac.Certfps {
  1981. if certfp == current {
  1982. return errNoop
  1983. }
  1984. }
  1985. if maxCertfpsPerAccount <= len(ac.Certfps) {
  1986. return errLimitExceeded
  1987. }
  1988. ac.Certfps = append(ac.Certfps, certfp)
  1989. return nil
  1990. }
  1991. func (ac *AccountCredentials) RemoveCertfp(certfp string) (err error) {
  1992. found := false
  1993. newList := make([]string, 0, len(ac.Certfps))
  1994. for _, current := range ac.Certfps {
  1995. if current == certfp {
  1996. found = true
  1997. } else {
  1998. newList = append(newList, current)
  1999. }
  2000. }
  2001. if !found {
  2002. // this is important because it prevents you from deleting someone else's
  2003. // fingerprint record
  2004. return errNoop
  2005. }
  2006. ac.Certfps = newList
  2007. return nil
  2008. }
  2009. type MulticlientAllowedSetting int
  2010. const (
  2011. MulticlientAllowedServerDefault MulticlientAllowedSetting = iota
  2012. MulticlientDisallowedByUser
  2013. MulticlientAllowedByUser
  2014. )
  2015. // controls whether/when clients without event-playback support see fake
  2016. // PRIVMSGs for JOINs
  2017. type ReplayJoinsSetting uint
  2018. const (
  2019. ReplayJoinsCommandsOnly = iota // replay in HISTORY or CHATHISTORY output
  2020. ReplayJoinsAlways // replay in HISTORY, CHATHISTORY, or autoreplay
  2021. )
  2022. func replayJoinsSettingFromString(str string) (result ReplayJoinsSetting, err error) {
  2023. switch strings.ToLower(str) {
  2024. case "commands-only":
  2025. result = ReplayJoinsCommandsOnly
  2026. case "always":
  2027. result = ReplayJoinsAlways
  2028. default:
  2029. err = errInvalidParams
  2030. }
  2031. return
  2032. }
  2033. // XXX: AllowBouncer cannot be renamed AllowMulticlient because it is stored in
  2034. // persistent JSON blobs in the database
  2035. type AccountSettings struct {
  2036. AutoreplayLines *int
  2037. NickEnforcement NickEnforcementMethod
  2038. AllowBouncer MulticlientAllowedSetting
  2039. ReplayJoins ReplayJoinsSetting
  2040. AlwaysOn PersistentStatus
  2041. AutoreplayMissed bool
  2042. DMHistory HistoryStatus
  2043. AutoAway PersistentStatus
  2044. Email string
  2045. }
  2046. // ClientAccount represents a user account.
  2047. type ClientAccount struct {
  2048. // Name of the account.
  2049. Name string
  2050. NameCasefolded string
  2051. RegisteredAt time.Time
  2052. Credentials AccountCredentials
  2053. Verified bool
  2054. Suspended *AccountSuspension
  2055. AdditionalNicks []string
  2056. VHost VHostInfo
  2057. Settings AccountSettings
  2058. }
  2059. // convenience for passing around raw serialized account data
  2060. type rawClientAccount struct {
  2061. Name string
  2062. RegisteredAt string
  2063. Credentials string
  2064. Verified bool
  2065. AdditionalNicks string
  2066. VHost string
  2067. Settings string
  2068. Suspended string
  2069. }