Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

accounts.go 68KB

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