您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

accounts.go 58KB

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