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

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