You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

accounts.go 70KB

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