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

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