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

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789
  1. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "encoding/json"
  6. "fmt"
  7. "net/smtp"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "sync/atomic"
  12. "time"
  13. "unicode"
  14. "github.com/oragono/oragono/irc/caps"
  15. "github.com/oragono/oragono/irc/ldap"
  16. "github.com/oragono/oragono/irc/passwd"
  17. "github.com/oragono/oragono/irc/utils"
  18. "github.com/tidwall/buntdb"
  19. )
  20. const (
  21. keyAccountExists = "account.exists %s"
  22. keyAccountVerified = "account.verified %s"
  23. keyAccountCallback = "account.callback %s"
  24. keyAccountVerificationCode = "account.verificationcode %s"
  25. keyAccountName = "account.name %s" // stores the 'preferred name' of the account, not casemapped
  26. keyAccountRegTime = "account.registered.time %s"
  27. keyAccountCredentials = "account.credentials %s"
  28. keyAccountAdditionalNicks = "account.additionalnicks %s"
  29. keyAccountSettings = "account.settings %s"
  30. keyAccountVHost = "account.vhost %s"
  31. keyCertToAccount = "account.creds.certfp %s"
  32. keyAccountChannels = "account.channels %s" // channels registered to the account
  33. keyAccountJoinedChannels = "account.joinedto %s" // channels a persistent client has joined
  34. keyAccountLastSeen = "account.lastseen %s"
  35. keyVHostQueueAcctToId = "vhostQueue %s"
  36. vhostRequestIdx = "vhostQueue"
  37. maxCertfpsPerAccount = 5
  38. )
  39. // everything about accounts is persistent; therefore, the database is the authoritative
  40. // source of truth for all account information. anything on the heap is just a cache
  41. type AccountManager struct {
  42. // XXX these are up here so they can be aligned to a 64-bit boundary, please forgive me
  43. // autoincrementing ID for vhost requests:
  44. vhostRequestID uint64
  45. vhostRequestPendingCount uint64
  46. sync.RWMutex // tier 2
  47. serialCacheUpdateMutex sync.Mutex // tier 3
  48. vHostUpdateMutex sync.Mutex // tier 3
  49. server *Server
  50. // track clients logged in to accounts
  51. accountToClients map[string][]*Client
  52. nickToAccount map[string]string
  53. skeletonToAccount map[string]string
  54. accountToMethod map[string]NickEnforcementMethod
  55. }
  56. func (am *AccountManager) Initialize(server *Server) {
  57. am.accountToClients = make(map[string][]*Client)
  58. am.nickToAccount = make(map[string]string)
  59. am.skeletonToAccount = make(map[string]string)
  60. am.accountToMethod = make(map[string]NickEnforcementMethod)
  61. am.server = server
  62. config := server.Config()
  63. am.buildNickToAccountIndex(config)
  64. am.initVHostRequestQueue(config)
  65. am.createAlwaysOnClients(config)
  66. }
  67. func (am *AccountManager) createAlwaysOnClients(config *Config) {
  68. if config.Accounts.Multiclient.AlwaysOn == PersistentDisabled {
  69. return
  70. }
  71. verifiedPrefix := fmt.Sprintf(keyAccountVerified, "")
  72. am.serialCacheUpdateMutex.Lock()
  73. defer am.serialCacheUpdateMutex.Unlock()
  74. var accounts []string
  75. am.server.store.View(func(tx *buntdb.Tx) error {
  76. err := tx.AscendGreaterOrEqual("", verifiedPrefix, func(key, value string) bool {
  77. if !strings.HasPrefix(key, verifiedPrefix) {
  78. return false
  79. }
  80. account := strings.TrimPrefix(key, verifiedPrefix)
  81. accounts = append(accounts, account)
  82. return true
  83. })
  84. return err
  85. })
  86. for _, accountName := range accounts {
  87. account, err := am.LoadAccount(accountName)
  88. if err == nil && account.Verified &&
  89. persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, account.Settings.AlwaysOn) {
  90. am.server.AddAlwaysOnClient(account, am.loadChannels(accountName), am.loadLastSeen(accountName))
  91. }
  92. }
  93. }
  94. func (am *AccountManager) buildNickToAccountIndex(config *Config) {
  95. if !config.Accounts.NickReservation.Enabled {
  96. return
  97. }
  98. nickToAccount := make(map[string]string)
  99. skeletonToAccount := make(map[string]string)
  100. accountToMethod := make(map[string]NickEnforcementMethod)
  101. existsPrefix := fmt.Sprintf(keyAccountExists, "")
  102. am.serialCacheUpdateMutex.Lock()
  103. defer am.serialCacheUpdateMutex.Unlock()
  104. err := am.server.store.View(func(tx *buntdb.Tx) error {
  105. err := tx.AscendGreaterOrEqual("", existsPrefix, func(key, value string) bool {
  106. if !strings.HasPrefix(key, existsPrefix) {
  107. return false
  108. }
  109. account := strings.TrimPrefix(key, existsPrefix)
  110. if _, err := tx.Get(fmt.Sprintf(keyAccountVerified, account)); err == nil {
  111. nickToAccount[account] = account
  112. accountName, err := tx.Get(fmt.Sprintf(keyAccountName, account))
  113. if err != nil {
  114. am.server.logger.Error("internal", "missing account name for", account)
  115. } else {
  116. skeleton, _ := Skeleton(accountName)
  117. skeletonToAccount[skeleton] = account
  118. }
  119. }
  120. if rawNicks, err := tx.Get(fmt.Sprintf(keyAccountAdditionalNicks, account)); err == nil {
  121. additionalNicks := unmarshalReservedNicks(rawNicks)
  122. for _, nick := range additionalNicks {
  123. cfnick, _ := CasefoldName(nick)
  124. nickToAccount[cfnick] = account
  125. skeleton, _ := Skeleton(nick)
  126. skeletonToAccount[skeleton] = account
  127. }
  128. }
  129. if rawPrefs, err := tx.Get(fmt.Sprintf(keyAccountSettings, account)); err == nil {
  130. var prefs AccountSettings
  131. err := json.Unmarshal([]byte(rawPrefs), &prefs)
  132. if err == nil && prefs.NickEnforcement != NickEnforcementOptional {
  133. accountToMethod[account] = prefs.NickEnforcement
  134. } else if err != nil {
  135. am.server.logger.Error("internal", "corrupt account creds", account)
  136. }
  137. }
  138. return true
  139. })
  140. return err
  141. })
  142. if err != nil {
  143. am.server.logger.Error("internal", "couldn't read reserved nicks", err.Error())
  144. } else {
  145. am.Lock()
  146. am.nickToAccount = nickToAccount
  147. am.skeletonToAccount = skeletonToAccount
  148. am.accountToMethod = accountToMethod
  149. am.Unlock()
  150. }
  151. }
  152. func (am *AccountManager) initVHostRequestQueue(config *Config) {
  153. if !config.Accounts.VHosts.Enabled {
  154. return
  155. }
  156. am.vHostUpdateMutex.Lock()
  157. defer am.vHostUpdateMutex.Unlock()
  158. // the db maps the account name to the autoincrementing integer ID of its request
  159. // create an numerically ordered index on ID, so we can list the oldest requests
  160. // finally, collect the integer id of the newest request and the total request count
  161. var total uint64
  162. var lastIDStr string
  163. err := am.server.store.Update(func(tx *buntdb.Tx) error {
  164. err := tx.CreateIndex(vhostRequestIdx, fmt.Sprintf(keyVHostQueueAcctToId, "*"), buntdb.IndexInt)
  165. if err != nil {
  166. return err
  167. }
  168. return tx.Descend(vhostRequestIdx, func(key, value string) bool {
  169. if lastIDStr == "" {
  170. lastIDStr = value
  171. }
  172. total++
  173. return true
  174. })
  175. })
  176. if err != nil {
  177. am.server.logger.Error("internal", "could not create vhost queue index", err.Error())
  178. }
  179. lastID, _ := strconv.ParseUint(lastIDStr, 10, 64)
  180. am.server.logger.Debug("services", fmt.Sprintf("vhost queue length is %d, autoincrementing id is %d", total, lastID))
  181. atomic.StoreUint64(&am.vhostRequestID, lastID)
  182. atomic.StoreUint64(&am.vhostRequestPendingCount, total)
  183. }
  184. func (am *AccountManager) NickToAccount(nick string) string {
  185. cfnick, err := CasefoldName(nick)
  186. if err != nil {
  187. return ""
  188. }
  189. am.RLock()
  190. defer am.RUnlock()
  191. return am.nickToAccount[cfnick]
  192. }
  193. // given an account, combine stored enforcement method with the config settings
  194. // to compute the actual enforcement method
  195. func configuredEnforcementMethod(config *Config, storedMethod NickEnforcementMethod) (result NickEnforcementMethod) {
  196. if !config.Accounts.NickReservation.Enabled {
  197. return NickEnforcementNone
  198. }
  199. result = storedMethod
  200. // if they don't have a custom setting, or customization is disabled, use the default
  201. if result == NickEnforcementOptional || !config.Accounts.NickReservation.AllowCustomEnforcement {
  202. result = config.Accounts.NickReservation.Method
  203. }
  204. if result == NickEnforcementOptional {
  205. // enforcement was explicitly enabled neither in the config or by the user
  206. result = NickEnforcementNone
  207. }
  208. return
  209. }
  210. // Given a nick, looks up the account that owns it and the method (none/timeout/strict)
  211. // used to enforce ownership.
  212. func (am *AccountManager) EnforcementStatus(cfnick, skeleton string) (account string, method NickEnforcementMethod) {
  213. config := am.server.Config()
  214. if !config.Accounts.NickReservation.Enabled {
  215. return "", NickEnforcementNone
  216. }
  217. am.RLock()
  218. defer am.RUnlock()
  219. finalEnforcementMethod := func(account_ string) (result NickEnforcementMethod) {
  220. storedMethod := am.accountToMethod[account_]
  221. return configuredEnforcementMethod(config, storedMethod)
  222. }
  223. nickAccount := am.nickToAccount[cfnick]
  224. skelAccount := am.skeletonToAccount[skeleton]
  225. if nickAccount == "" && skelAccount == "" {
  226. return "", NickEnforcementNone
  227. } else if nickAccount != "" && (skelAccount == nickAccount || skelAccount == "") {
  228. return nickAccount, finalEnforcementMethod(nickAccount)
  229. } else if skelAccount != "" && nickAccount == "" {
  230. return skelAccount, finalEnforcementMethod(skelAccount)
  231. } else {
  232. // nickAccount != skelAccount and both are nonempty:
  233. // two people have competing claims on (this casefolding of) this nick!
  234. nickMethod := finalEnforcementMethod(nickAccount)
  235. skelMethod := finalEnforcementMethod(skelAccount)
  236. switch {
  237. case skelMethod == NickEnforcementNone:
  238. return nickAccount, nickMethod
  239. case nickMethod == NickEnforcementNone:
  240. return skelAccount, skelMethod
  241. default:
  242. // nobody can use this nick
  243. return "!", NickEnforcementStrict
  244. }
  245. }
  246. }
  247. // Sets a custom enforcement method for an account and stores it in the database.
  248. func (am *AccountManager) SetEnforcementStatus(account string, method NickEnforcementMethod) (finalSettings AccountSettings, err error) {
  249. config := am.server.Config()
  250. if !(config.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.AllowCustomEnforcement) {
  251. err = errFeatureDisabled
  252. return
  253. }
  254. setter := func(in AccountSettings) (out AccountSettings, err error) {
  255. out = in
  256. out.NickEnforcement = method
  257. return out, nil
  258. }
  259. _, err = am.ModifyAccountSettings(account, setter)
  260. if err != nil {
  261. return
  262. }
  263. // this update of the data plane is racey, but it's probably fine
  264. am.Lock()
  265. defer am.Unlock()
  266. if method == NickEnforcementOptional {
  267. delete(am.accountToMethod, account)
  268. } else {
  269. am.accountToMethod[account] = method
  270. }
  271. return
  272. }
  273. func (am *AccountManager) AccountToClients(account string) (result []*Client) {
  274. cfaccount, err := CasefoldName(account)
  275. if err != nil {
  276. return
  277. }
  278. am.RLock()
  279. defer am.RUnlock()
  280. return am.accountToClients[cfaccount]
  281. }
  282. func (am *AccountManager) Register(client *Client, account string, callbackNamespace string, callbackValue string, passphrase string, certfp string) error {
  283. casefoldedAccount, err := CasefoldName(account)
  284. skeleton, skerr := Skeleton(account)
  285. if err != nil || skerr != nil || account == "" || account == "*" {
  286. return errAccountCreation
  287. }
  288. if restrictedCasefoldedNicks[casefoldedAccount] || restrictedSkeletons[skeleton] {
  289. return errAccountAlreadyRegistered
  290. }
  291. config := am.server.Config()
  292. // final "is registration allowed" check, probably redundant:
  293. if !(config.Accounts.Registration.Enabled || callbackNamespace == "admin") {
  294. return errFeatureDisabled
  295. }
  296. // if nick reservation is enabled, you can only register your current nickname
  297. // as an account; this prevents "land-grab" situations where someone else
  298. // registers your nick out from under you and then NS GHOSTs you
  299. // n.b. client is nil during a SAREGISTER
  300. // n.b. if ForceGuestFormat, then there's no concern, because you can't
  301. // register a guest nickname anyway, and the actual registration system
  302. // will prevent any double-register
  303. if client != nil && config.Accounts.NickReservation.Enabled &&
  304. !config.Accounts.NickReservation.ForceGuestFormat &&
  305. client.NickCasefolded() != casefoldedAccount {
  306. return errAccountMustHoldNick
  307. }
  308. // can't register a guest nickname
  309. if config.Accounts.NickReservation.guestRegexpFolded.MatchString(casefoldedAccount) {
  310. return errAccountAlreadyRegistered
  311. }
  312. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  313. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  314. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  315. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  316. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  317. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  318. certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
  319. var creds AccountCredentials
  320. creds.Version = 1
  321. err = creds.SetPassphrase(passphrase, am.server.Config().Accounts.Registration.BcryptCost)
  322. if err != nil {
  323. return err
  324. }
  325. creds.AddCertfp(certfp)
  326. credStr, err := creds.Serialize()
  327. if err != nil {
  328. return err
  329. }
  330. registeredTimeStr := strconv.FormatInt(time.Now().UnixNano(), 10)
  331. callbackSpec := fmt.Sprintf("%s:%s", callbackNamespace, callbackValue)
  332. var setOptions *buntdb.SetOptions
  333. ttl := time.Duration(config.Accounts.Registration.VerifyTimeout)
  334. if ttl != 0 {
  335. setOptions = &buntdb.SetOptions{Expires: true, TTL: ttl}
  336. }
  337. err = func() error {
  338. am.serialCacheUpdateMutex.Lock()
  339. defer am.serialCacheUpdateMutex.Unlock()
  340. // can't register an account with the same name as a registered nick
  341. if am.NickToAccount(casefoldedAccount) != "" {
  342. return errAccountAlreadyRegistered
  343. }
  344. return am.server.store.Update(func(tx *buntdb.Tx) error {
  345. _, err := am.loadRawAccount(tx, casefoldedAccount)
  346. if err != errAccountDoesNotExist {
  347. return errAccountAlreadyRegistered
  348. }
  349. if certfp != "" {
  350. // make sure certfp doesn't already exist because that'd be silly
  351. _, err := tx.Get(certFPKey)
  352. if err != buntdb.ErrNotFound {
  353. return errCertfpAlreadyExists
  354. }
  355. }
  356. tx.Set(accountKey, "1", setOptions)
  357. tx.Set(accountNameKey, account, setOptions)
  358. tx.Set(registeredTimeKey, registeredTimeStr, setOptions)
  359. tx.Set(credentialsKey, credStr, setOptions)
  360. tx.Set(callbackKey, callbackSpec, setOptions)
  361. if certfp != "" {
  362. tx.Set(certFPKey, casefoldedAccount, setOptions)
  363. }
  364. return nil
  365. })
  366. }()
  367. if err != nil {
  368. return err
  369. }
  370. code, err := am.dispatchCallback(client, casefoldedAccount, callbackNamespace, callbackValue)
  371. if err != nil {
  372. am.Unregister(casefoldedAccount)
  373. return errCallbackFailed
  374. } else {
  375. return am.server.store.Update(func(tx *buntdb.Tx) error {
  376. _, _, err = tx.Set(verificationCodeKey, code, setOptions)
  377. return err
  378. })
  379. }
  380. }
  381. // validatePassphrase checks whether a passphrase is allowed by our rules
  382. func validatePassphrase(passphrase string) error {
  383. // sanity check the length
  384. if len(passphrase) == 0 || len(passphrase) > 300 {
  385. return errAccountBadPassphrase
  386. }
  387. // we use * as a placeholder in some places, if it's gotten this far then fail
  388. if passphrase == "*" {
  389. return errAccountBadPassphrase
  390. }
  391. // for now, just enforce that spaces are not allowed
  392. for _, r := range passphrase {
  393. if unicode.IsSpace(r) {
  394. return errAccountBadPassphrase
  395. }
  396. }
  397. return nil
  398. }
  399. // changes the password for an account
  400. func (am *AccountManager) setPassword(account string, password string, hasPrivs bool) (err error) {
  401. cfAccount, err := CasefoldName(account)
  402. if err != nil {
  403. return errAccountDoesNotExist
  404. }
  405. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  406. var credStr string
  407. am.server.store.View(func(tx *buntdb.Tx) error {
  408. // no need to check verification status here or below;
  409. // you either need to be auth'ed to the account or be an oper to do this
  410. credStr, err = tx.Get(credKey)
  411. return nil
  412. })
  413. if err != nil {
  414. return errAccountDoesNotExist
  415. }
  416. var creds AccountCredentials
  417. err = json.Unmarshal([]byte(credStr), &creds)
  418. if err != nil {
  419. return err
  420. }
  421. if !hasPrivs && creds.Empty() {
  422. return errCredsExternallyManaged
  423. }
  424. err = creds.SetPassphrase(password, am.server.Config().Accounts.Registration.BcryptCost)
  425. if err != nil {
  426. return err
  427. }
  428. if creds.Empty() && !hasPrivs {
  429. return errEmptyCredentials
  430. }
  431. newCredStr, err := creds.Serialize()
  432. if err != nil {
  433. return err
  434. }
  435. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  436. curCredStr, err := tx.Get(credKey)
  437. if credStr != curCredStr {
  438. return errCASFailed
  439. }
  440. _, _, err = tx.Set(credKey, newCredStr, nil)
  441. return err
  442. })
  443. return err
  444. }
  445. func (am *AccountManager) saveChannels(account string, channels []string) {
  446. channelsStr := strings.Join(channels, ",")
  447. key := fmt.Sprintf(keyAccountJoinedChannels, account)
  448. am.server.store.Update(func(tx *buntdb.Tx) error {
  449. tx.Set(key, channelsStr, nil)
  450. return nil
  451. })
  452. }
  453. func (am *AccountManager) loadChannels(account string) (channels []string) {
  454. key := fmt.Sprintf(keyAccountJoinedChannels, account)
  455. var channelsStr string
  456. am.server.store.View(func(tx *buntdb.Tx) error {
  457. channelsStr, _ = tx.Get(key)
  458. return nil
  459. })
  460. if channelsStr != "" {
  461. return strings.Split(channelsStr, ",")
  462. }
  463. return
  464. }
  465. func (am *AccountManager) saveLastSeen(account string, lastSeen time.Time) {
  466. key := fmt.Sprintf(keyAccountLastSeen, account)
  467. var val string
  468. if !lastSeen.IsZero() {
  469. val = strconv.FormatInt(lastSeen.UnixNano(), 10)
  470. }
  471. am.server.store.Update(func(tx *buntdb.Tx) error {
  472. if val != "" {
  473. tx.Set(key, val, nil)
  474. } else {
  475. tx.Delete(key)
  476. }
  477. return nil
  478. })
  479. }
  480. func (am *AccountManager) loadLastSeen(account string) (lastSeen time.Time) {
  481. key := fmt.Sprintf(keyAccountLastSeen, account)
  482. var lsText string
  483. am.server.store.Update(func(tx *buntdb.Tx) error {
  484. lsText, _ = tx.Get(key)
  485. // XXX clear this on startup, because it's not clear when it's
  486. // going to be overwritten, and restarting the server twice in a row
  487. // could result in a large amount of duplicated history replay
  488. tx.Delete(key)
  489. return nil
  490. })
  491. lsNum, err := strconv.ParseInt(lsText, 10, 64)
  492. if err == nil {
  493. return time.Unix(0, lsNum).UTC()
  494. }
  495. return
  496. }
  497. func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasPrivs bool) (err error) {
  498. certfp, err = utils.NormalizeCertfp(certfp)
  499. if err != nil {
  500. return err
  501. }
  502. cfAccount, err := CasefoldName(account)
  503. if err != nil {
  504. return errAccountDoesNotExist
  505. }
  506. credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
  507. var credStr string
  508. am.server.store.View(func(tx *buntdb.Tx) error {
  509. credStr, err = tx.Get(credKey)
  510. return nil
  511. })
  512. if err != nil {
  513. return errAccountDoesNotExist
  514. }
  515. var creds AccountCredentials
  516. err = json.Unmarshal([]byte(credStr), &creds)
  517. if err != nil {
  518. return err
  519. }
  520. if !hasPrivs && creds.Empty() {
  521. return errCredsExternallyManaged
  522. }
  523. if add {
  524. err = creds.AddCertfp(certfp)
  525. } else {
  526. err = creds.RemoveCertfp(certfp)
  527. }
  528. if err != nil {
  529. return err
  530. }
  531. if creds.Empty() && !hasPrivs {
  532. return errEmptyCredentials
  533. }
  534. newCredStr, err := creds.Serialize()
  535. if err != nil {
  536. return err
  537. }
  538. certfpKey := fmt.Sprintf(keyCertToAccount, certfp)
  539. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  540. curCredStr, err := tx.Get(credKey)
  541. if credStr != curCredStr {
  542. return errCASFailed
  543. }
  544. if add {
  545. _, err = tx.Get(certfpKey)
  546. if err != buntdb.ErrNotFound {
  547. return errCertfpAlreadyExists
  548. }
  549. tx.Set(certfpKey, cfAccount, nil)
  550. } else {
  551. tx.Delete(certfpKey)
  552. }
  553. _, _, err = tx.Set(credKey, newCredStr, nil)
  554. return err
  555. })
  556. return err
  557. }
  558. func (am *AccountManager) dispatchCallback(client *Client, casefoldedAccount string, callbackNamespace string, callbackValue string) (string, error) {
  559. if callbackNamespace == "*" || callbackNamespace == "none" || callbackNamespace == "admin" {
  560. return "", nil
  561. } else if callbackNamespace == "mailto" {
  562. return am.dispatchMailtoCallback(client, casefoldedAccount, callbackValue)
  563. } else {
  564. return "", fmt.Errorf("Callback not implemented: %s", callbackNamespace)
  565. }
  566. }
  567. func (am *AccountManager) dispatchMailtoCallback(client *Client, casefoldedAccount string, callbackValue string) (code string, err error) {
  568. config := am.server.Config().Accounts.Registration.Callbacks.Mailto
  569. code = utils.GenerateSecretToken()
  570. subject := config.VerifyMessageSubject
  571. if subject == "" {
  572. subject = fmt.Sprintf(client.t("Verify your account on %s"), am.server.name)
  573. }
  574. messageStrings := []string{
  575. fmt.Sprintf("From: %s\r\n", config.Sender),
  576. fmt.Sprintf("To: %s\r\n", callbackValue),
  577. fmt.Sprintf("Subject: %s\r\n", subject),
  578. "\r\n", // end headers, begin message body
  579. fmt.Sprintf(client.t("Account: %s"), casefoldedAccount) + "\r\n",
  580. fmt.Sprintf(client.t("Verification code: %s"), code) + "\r\n",
  581. "\r\n",
  582. client.t("To verify your account, issue the following command:") + "\r\n",
  583. fmt.Sprintf("/MSG NickServ VERIFY %s %s", casefoldedAccount, code) + "\r\n",
  584. }
  585. var message []byte
  586. for i := 0; i < len(messageStrings); i++ {
  587. message = append(message, []byte(messageStrings[i])...)
  588. }
  589. addr := fmt.Sprintf("%s:%d", config.Server, config.Port)
  590. var auth smtp.Auth
  591. if config.Username != "" && config.Password != "" {
  592. auth = smtp.PlainAuth("", config.Username, config.Password, config.Server)
  593. }
  594. // TODO: this will never send the password in plaintext over a nonlocal link,
  595. // but it might send the email in plaintext, regardless of the value of
  596. // config.TLS.InsecureSkipVerify
  597. err = smtp.SendMail(addr, auth, config.Sender, []string{callbackValue}, message)
  598. if err != nil {
  599. am.server.logger.Error("internal", "Failed to dispatch e-mail", err.Error())
  600. }
  601. return
  602. }
  603. func (am *AccountManager) Verify(client *Client, account string, code string) error {
  604. casefoldedAccount, err := CasefoldName(account)
  605. if err != nil || account == "" || account == "*" {
  606. return errAccountVerificationFailed
  607. }
  608. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  609. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  610. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  611. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  612. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  613. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  614. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  615. var raw rawClientAccount
  616. func() {
  617. am.serialCacheUpdateMutex.Lock()
  618. defer am.serialCacheUpdateMutex.Unlock()
  619. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  620. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  621. if err == errAccountDoesNotExist {
  622. return errAccountDoesNotExist
  623. } else if err != nil {
  624. return errAccountVerificationFailed
  625. } else if raw.Verified {
  626. return errAccountAlreadyVerified
  627. }
  628. // actually verify the code
  629. // a stored code of "" means a none callback / no code required
  630. success := false
  631. storedCode, err := tx.Get(verificationCodeKey)
  632. if err == nil {
  633. // this is probably unnecessary
  634. if storedCode == "" || utils.SecretTokensMatch(storedCode, code) {
  635. success = true
  636. }
  637. }
  638. if !success {
  639. return errAccountVerificationInvalidCode
  640. }
  641. // verify the account
  642. tx.Set(verifiedKey, "1", nil)
  643. // don't need the code anymore
  644. tx.Delete(verificationCodeKey)
  645. // re-set all other keys, removing the TTL
  646. tx.Set(accountKey, "1", nil)
  647. tx.Set(accountNameKey, raw.Name, nil)
  648. tx.Set(registeredTimeKey, raw.RegisteredAt, nil)
  649. tx.Set(callbackKey, raw.Callback, nil)
  650. tx.Set(credentialsKey, raw.Credentials, nil)
  651. var creds AccountCredentials
  652. // XXX we shouldn't do (de)serialization inside the txn,
  653. // but this is like 2 usec on my system
  654. json.Unmarshal([]byte(raw.Credentials), &creds)
  655. for _, cert := range creds.Certfps {
  656. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  657. tx.Set(certFPKey, casefoldedAccount, nil)
  658. }
  659. return nil
  660. })
  661. if err == nil {
  662. skeleton, _ := Skeleton(raw.Name)
  663. am.Lock()
  664. am.nickToAccount[casefoldedAccount] = casefoldedAccount
  665. am.skeletonToAccount[skeleton] = casefoldedAccount
  666. am.Unlock()
  667. }
  668. }()
  669. if err != nil {
  670. return err
  671. }
  672. nick := "[server admin]"
  673. if client != nil {
  674. nick = client.Nick()
  675. }
  676. am.server.logger.Info("accounts", "client", nick, "registered account", casefoldedAccount)
  677. raw.Verified = true
  678. clientAccount, err := am.deserializeRawAccount(raw, casefoldedAccount)
  679. if err != nil {
  680. return err
  681. }
  682. if client != nil {
  683. am.Login(client, clientAccount)
  684. }
  685. return nil
  686. }
  687. // register and verify an account, for internal use
  688. func (am *AccountManager) SARegister(account, passphrase string) (err error) {
  689. err = am.Register(nil, account, "admin", "", passphrase, "")
  690. if err == nil {
  691. err = am.Verify(nil, account, "")
  692. }
  693. return
  694. }
  695. func marshalReservedNicks(nicks []string) string {
  696. return strings.Join(nicks, ",")
  697. }
  698. func unmarshalReservedNicks(nicks string) (result []string) {
  699. if nicks == "" {
  700. return
  701. }
  702. return strings.Split(nicks, ",")
  703. }
  704. func (am *AccountManager) SetNickReserved(client *Client, nick string, saUnreserve bool, reserve bool) error {
  705. cfnick, err := CasefoldName(nick)
  706. skeleton, skerr := Skeleton(nick)
  707. // garbage nick, or garbage options, or disabled
  708. nrconfig := am.server.Config().Accounts.NickReservation
  709. if err != nil || skerr != nil || cfnick == "" || (reserve && saUnreserve) || !nrconfig.Enabled {
  710. return errAccountNickReservationFailed
  711. }
  712. // the cache is in sync with the DB while we hold serialCacheUpdateMutex
  713. am.serialCacheUpdateMutex.Lock()
  714. defer am.serialCacheUpdateMutex.Unlock()
  715. // find the affected account, which is usually the client's:
  716. account := client.Account()
  717. if saUnreserve {
  718. // unless this is a sadrop:
  719. account = am.NickToAccount(cfnick)
  720. if account == "" {
  721. // nothing to do
  722. return nil
  723. }
  724. }
  725. if account == "" {
  726. return errAccountNotLoggedIn
  727. }
  728. am.Lock()
  729. accountForNick := am.nickToAccount[cfnick]
  730. var accountForSkeleton string
  731. if reserve {
  732. accountForSkeleton = am.skeletonToAccount[skeleton]
  733. }
  734. am.Unlock()
  735. if reserve && (accountForNick != "" || accountForSkeleton != "") {
  736. return errNicknameReserved
  737. } else if !reserve && !saUnreserve && accountForNick != account {
  738. return errNicknameReserved
  739. } else if !reserve && cfnick == account {
  740. return errAccountCantDropPrimaryNick
  741. }
  742. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, account)
  743. unverifiedAccountKey := fmt.Sprintf(keyAccountExists, cfnick)
  744. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  745. if reserve {
  746. // unverified accounts don't show up in NickToAccount yet (which is intentional),
  747. // however you shouldn't be able to reserve a nick out from under them
  748. _, err := tx.Get(unverifiedAccountKey)
  749. if err == nil {
  750. return errNicknameReserved
  751. }
  752. }
  753. rawNicks, err := tx.Get(nicksKey)
  754. if err != nil && err != buntdb.ErrNotFound {
  755. return err
  756. }
  757. nicks := unmarshalReservedNicks(rawNicks)
  758. if reserve {
  759. if len(nicks) >= nrconfig.AdditionalNickLimit {
  760. return errAccountTooManyNicks
  761. }
  762. nicks = append(nicks, nick)
  763. } else {
  764. // compute (original reserved nicks) minus cfnick
  765. var newNicks []string
  766. for _, reservedNick := range nicks {
  767. cfreservednick, _ := CasefoldName(reservedNick)
  768. if cfreservednick != cfnick {
  769. newNicks = append(newNicks, reservedNick)
  770. } else {
  771. // found the original, unfolded version of the nick we're dropping;
  772. // recompute the true skeleton from it
  773. skeleton, _ = Skeleton(reservedNick)
  774. }
  775. }
  776. nicks = newNicks
  777. }
  778. marshaledNicks := marshalReservedNicks(nicks)
  779. _, _, err = tx.Set(nicksKey, string(marshaledNicks), nil)
  780. return err
  781. })
  782. if err == errAccountTooManyNicks || err == errNicknameReserved {
  783. return err
  784. } else if err != nil {
  785. return errAccountNickReservationFailed
  786. }
  787. // success
  788. am.Lock()
  789. defer am.Unlock()
  790. if reserve {
  791. am.nickToAccount[cfnick] = account
  792. am.skeletonToAccount[skeleton] = account
  793. } else {
  794. delete(am.nickToAccount, cfnick)
  795. delete(am.skeletonToAccount, skeleton)
  796. }
  797. return nil
  798. }
  799. func (am *AccountManager) checkPassphrase(accountName, passphrase string) (account ClientAccount, err error) {
  800. account, err = am.LoadAccount(accountName)
  801. if err != nil {
  802. return
  803. }
  804. if !account.Verified {
  805. err = errAccountUnverified
  806. return
  807. }
  808. switch account.Credentials.Version {
  809. case 0:
  810. err = handleLegacyPasswordV0(am.server, accountName, account.Credentials, passphrase)
  811. case 1:
  812. if passwd.CompareHashAndPassword(account.Credentials.PassphraseHash, []byte(passphrase)) != nil {
  813. err = errAccountInvalidCredentials
  814. }
  815. default:
  816. err = errAccountInvalidCredentials
  817. }
  818. return
  819. }
  820. func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) (err error) {
  821. // XXX check this now, so we don't allow a redundant login for an always-on client
  822. // even for a brief period. the other potential source of nick-account conflicts
  823. // is from force-nick-equals-account, but those will be caught later by
  824. // fixupNickEqualsAccount and if there is a conflict, they will be logged out.
  825. if client.registered {
  826. if clientAlready := am.server.clients.Get(accountName); clientAlready != nil && clientAlready.AlwaysOn() {
  827. return errNickAccountMismatch
  828. }
  829. }
  830. var account ClientAccount
  831. defer func() {
  832. if err == nil {
  833. am.Login(client, account)
  834. }
  835. }()
  836. ldapConf := am.server.Config().Accounts.LDAP
  837. if ldapConf.Enabled {
  838. err = ldap.CheckLDAPPassphrase(ldapConf, accountName, passphrase, am.server.logger)
  839. if err == nil {
  840. account, err = am.LoadAccount(accountName)
  841. // autocreate if necessary:
  842. if err == errAccountDoesNotExist && ldapConf.Autocreate {
  843. err = am.SARegister(accountName, "")
  844. if err != nil {
  845. return
  846. }
  847. account, err = am.LoadAccount(accountName)
  848. }
  849. return
  850. }
  851. }
  852. account, err = am.checkPassphrase(accountName, passphrase)
  853. return err
  854. }
  855. func (am *AccountManager) LoadAccount(accountName string) (result ClientAccount, err error) {
  856. casefoldedAccount, err := CasefoldName(accountName)
  857. if err != nil {
  858. err = errAccountDoesNotExist
  859. return
  860. }
  861. var raw rawClientAccount
  862. am.server.store.View(func(tx *buntdb.Tx) error {
  863. raw, err = am.loadRawAccount(tx, casefoldedAccount)
  864. return nil
  865. })
  866. if err != nil {
  867. return
  868. }
  869. result, err = am.deserializeRawAccount(raw, casefoldedAccount)
  870. return
  871. }
  872. func (am *AccountManager) deserializeRawAccount(raw rawClientAccount, cfName string) (result ClientAccount, err error) {
  873. result.Name = raw.Name
  874. result.NameCasefolded = cfName
  875. regTimeInt, _ := strconv.ParseInt(raw.RegisteredAt, 10, 64)
  876. result.RegisteredAt = time.Unix(0, regTimeInt).UTC()
  877. e := json.Unmarshal([]byte(raw.Credentials), &result.Credentials)
  878. if e != nil {
  879. am.server.logger.Error("internal", "could not unmarshal credentials", e.Error())
  880. err = errAccountDoesNotExist
  881. return
  882. }
  883. result.AdditionalNicks = unmarshalReservedNicks(raw.AdditionalNicks)
  884. result.Verified = raw.Verified
  885. if raw.VHost != "" {
  886. e := json.Unmarshal([]byte(raw.VHost), &result.VHost)
  887. if e != nil {
  888. am.server.logger.Warning("internal", "could not unmarshal vhost for account", result.Name, e.Error())
  889. // pretend they have no vhost and move on
  890. }
  891. }
  892. if raw.Settings != "" {
  893. e := json.Unmarshal([]byte(raw.Settings), &result.Settings)
  894. if e != nil {
  895. am.server.logger.Warning("internal", "could not unmarshal settings for account", result.Name, e.Error())
  896. }
  897. }
  898. return
  899. }
  900. func (am *AccountManager) loadRawAccount(tx *buntdb.Tx, casefoldedAccount string) (result rawClientAccount, err error) {
  901. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  902. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  903. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  904. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  905. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  906. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  907. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  908. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  909. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  910. _, e := tx.Get(accountKey)
  911. if e == buntdb.ErrNotFound {
  912. err = errAccountDoesNotExist
  913. return
  914. }
  915. result.Name, _ = tx.Get(accountNameKey)
  916. result.RegisteredAt, _ = tx.Get(registeredTimeKey)
  917. result.Credentials, _ = tx.Get(credentialsKey)
  918. result.Callback, _ = tx.Get(callbackKey)
  919. result.AdditionalNicks, _ = tx.Get(nicksKey)
  920. result.VHost, _ = tx.Get(vhostKey)
  921. result.Settings, _ = tx.Get(settingsKey)
  922. if _, e = tx.Get(verifiedKey); e == nil {
  923. result.Verified = true
  924. }
  925. return
  926. }
  927. func (am *AccountManager) Unregister(account string) error {
  928. config := am.server.Config()
  929. casefoldedAccount, err := CasefoldName(account)
  930. if err != nil {
  931. return errAccountDoesNotExist
  932. }
  933. accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
  934. accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
  935. registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
  936. credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccount)
  937. callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
  938. verificationCodeKey := fmt.Sprintf(keyAccountVerificationCode, casefoldedAccount)
  939. verifiedKey := fmt.Sprintf(keyAccountVerified, casefoldedAccount)
  940. nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
  941. settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  942. vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
  943. vhostQueueKey := fmt.Sprintf(keyVHostQueueAcctToId, casefoldedAccount)
  944. channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
  945. joinedChannelsKey := fmt.Sprintf(keyAccountJoinedChannels, casefoldedAccount)
  946. lastSeenKey := fmt.Sprintf(keyAccountLastSeen, casefoldedAccount)
  947. var clients []*Client
  948. var registeredChannels []string
  949. // on our way out, unregister all the account's channels and delete them from the db
  950. defer func() {
  951. for _, channelName := range registeredChannels {
  952. am.server.channels.SetUnregistered(channelName, casefoldedAccount)
  953. }
  954. }()
  955. var credText string
  956. var rawNicks string
  957. am.serialCacheUpdateMutex.Lock()
  958. defer am.serialCacheUpdateMutex.Unlock()
  959. var accountName string
  960. var channelsStr string
  961. am.server.store.Update(func(tx *buntdb.Tx) error {
  962. tx.Delete(accountKey)
  963. accountName, _ = tx.Get(accountNameKey)
  964. tx.Delete(accountNameKey)
  965. tx.Delete(verifiedKey)
  966. tx.Delete(registeredTimeKey)
  967. tx.Delete(callbackKey)
  968. tx.Delete(verificationCodeKey)
  969. tx.Delete(settingsKey)
  970. rawNicks, _ = tx.Get(nicksKey)
  971. tx.Delete(nicksKey)
  972. credText, err = tx.Get(credentialsKey)
  973. tx.Delete(credentialsKey)
  974. tx.Delete(vhostKey)
  975. channelsStr, _ = tx.Get(channelsKey)
  976. tx.Delete(channelsKey)
  977. tx.Delete(joinedChannelsKey)
  978. tx.Delete(lastSeenKey)
  979. _, err := tx.Delete(vhostQueueKey)
  980. am.decrementVHostQueueCount(casefoldedAccount, err)
  981. return nil
  982. })
  983. if err == nil {
  984. var creds AccountCredentials
  985. if err = json.Unmarshal([]byte(credText), &creds); err == nil {
  986. for _, cert := range creds.Certfps {
  987. certFPKey := fmt.Sprintf(keyCertToAccount, cert)
  988. am.server.store.Update(func(tx *buntdb.Tx) error {
  989. if account, err := tx.Get(certFPKey); err == nil && account == casefoldedAccount {
  990. tx.Delete(certFPKey)
  991. }
  992. return nil
  993. })
  994. }
  995. }
  996. }
  997. skeleton, _ := Skeleton(accountName)
  998. additionalNicks := unmarshalReservedNicks(rawNicks)
  999. registeredChannels = unmarshalRegisteredChannels(channelsStr)
  1000. am.Lock()
  1001. defer am.Unlock()
  1002. clients = am.accountToClients[casefoldedAccount]
  1003. delete(am.accountToClients, casefoldedAccount)
  1004. delete(am.nickToAccount, casefoldedAccount)
  1005. delete(am.skeletonToAccount, skeleton)
  1006. for _, nick := range additionalNicks {
  1007. delete(am.nickToAccount, nick)
  1008. additionalSkel, _ := Skeleton(nick)
  1009. delete(am.skeletonToAccount, additionalSkel)
  1010. }
  1011. for _, client := range clients {
  1012. if config.Accounts.RequireSasl.Enabled {
  1013. client.Logout()
  1014. client.Quit(client.t("You are no longer authorized to be on this server"), nil)
  1015. // destroy acquires a semaphore so we can't call it while holding a lock
  1016. go client.destroy(nil)
  1017. } else {
  1018. am.logoutOfAccount(client)
  1019. }
  1020. }
  1021. if err != nil {
  1022. return errAccountDoesNotExist
  1023. }
  1024. return nil
  1025. }
  1026. func unmarshalRegisteredChannels(channelsStr string) (result []string) {
  1027. if channelsStr != "" {
  1028. result = strings.Split(channelsStr, ",")
  1029. }
  1030. return
  1031. }
  1032. func (am *AccountManager) ChannelsForAccount(account string) (channels []string) {
  1033. cfaccount, err := CasefoldName(account)
  1034. if err != nil {
  1035. return
  1036. }
  1037. var channelStr string
  1038. key := fmt.Sprintf(keyAccountChannels, cfaccount)
  1039. am.server.store.View(func(tx *buntdb.Tx) error {
  1040. channelStr, _ = tx.Get(key)
  1041. return nil
  1042. })
  1043. return unmarshalRegisteredChannels(channelStr)
  1044. }
  1045. func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid string) error {
  1046. if certfp == "" {
  1047. return errAccountInvalidCredentials
  1048. }
  1049. var account string
  1050. certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
  1051. err := am.server.store.View(func(tx *buntdb.Tx) error {
  1052. account, _ = tx.Get(certFPKey)
  1053. if account == "" {
  1054. return errAccountInvalidCredentials
  1055. }
  1056. return nil
  1057. })
  1058. if err != nil {
  1059. return err
  1060. }
  1061. if authzid != "" && authzid != account {
  1062. return errAuthzidAuthcidMismatch
  1063. }
  1064. // ok, we found an account corresponding to their certificate
  1065. clientAccount, err := am.LoadAccount(account)
  1066. if err != nil {
  1067. return err
  1068. } else if !clientAccount.Verified {
  1069. return errAccountUnverified
  1070. }
  1071. if client.registered {
  1072. if clientAlready := am.server.clients.Get(clientAccount.Name); clientAlready != nil && clientAlready.AlwaysOn() {
  1073. return errNickAccountMismatch
  1074. }
  1075. }
  1076. am.Login(client, clientAccount)
  1077. return nil
  1078. }
  1079. type settingsMunger func(input AccountSettings) (output AccountSettings, err error)
  1080. func (am *AccountManager) ModifyAccountSettings(account string, munger settingsMunger) (newSettings AccountSettings, err error) {
  1081. casefoldedAccount, err := CasefoldName(account)
  1082. if err != nil {
  1083. return newSettings, errAccountDoesNotExist
  1084. }
  1085. // TODO implement this in general via a compare-and-swap API
  1086. accountData, err := am.LoadAccount(casefoldedAccount)
  1087. if err != nil {
  1088. return
  1089. } else if !accountData.Verified {
  1090. return newSettings, errAccountUnverified
  1091. }
  1092. newSettings, err = munger(accountData.Settings)
  1093. if err != nil {
  1094. return
  1095. }
  1096. text, err := json.Marshal(newSettings)
  1097. if err != nil {
  1098. return
  1099. }
  1100. key := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
  1101. serializedValue := string(text)
  1102. err = am.server.store.Update(func(tx *buntdb.Tx) (err error) {
  1103. _, _, err = tx.Set(key, serializedValue, nil)
  1104. return
  1105. })
  1106. if err != nil {
  1107. err = errAccountUpdateFailed
  1108. return
  1109. }
  1110. // success, push new settings into the client objects
  1111. am.Lock()
  1112. defer am.Unlock()
  1113. for _, client := range am.accountToClients[casefoldedAccount] {
  1114. client.SetAccountSettings(newSettings)
  1115. }
  1116. return
  1117. }
  1118. // represents someone's status in hostserv
  1119. type VHostInfo struct {
  1120. ApprovedVHost string
  1121. Enabled bool
  1122. Forbidden bool
  1123. RequestedVHost string
  1124. RejectedVHost string
  1125. RejectionReason string
  1126. LastRequestTime time.Time
  1127. }
  1128. // pair type, <VHostInfo, accountName>
  1129. type PendingVHostRequest struct {
  1130. VHostInfo
  1131. Account string
  1132. }
  1133. type vhostThrottleExceeded struct {
  1134. timeRemaining time.Duration
  1135. }
  1136. func (vhe *vhostThrottleExceeded) Error() string {
  1137. return fmt.Sprintf("Wait at least %v and try again", vhe.timeRemaining)
  1138. }
  1139. func (vh *VHostInfo) checkThrottle(cooldown time.Duration) (err error) {
  1140. if cooldown == 0 {
  1141. return nil
  1142. }
  1143. now := time.Now().UTC()
  1144. elapsed := now.Sub(vh.LastRequestTime)
  1145. if elapsed > cooldown {
  1146. // success
  1147. vh.LastRequestTime = now
  1148. return nil
  1149. } else {
  1150. return &vhostThrottleExceeded{timeRemaining: cooldown - elapsed}
  1151. }
  1152. }
  1153. // callback type implementing the actual business logic of vhost operations
  1154. type vhostMunger func(input VHostInfo) (output VHostInfo, err error)
  1155. func (am *AccountManager) VHostSet(account string, vhost string) (result VHostInfo, err error) {
  1156. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1157. output = input
  1158. output.Enabled = true
  1159. output.ApprovedVHost = vhost
  1160. return
  1161. }
  1162. return am.performVHostChange(account, munger)
  1163. }
  1164. func (am *AccountManager) VHostRequest(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
  1165. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1166. output = input
  1167. if input.Forbidden {
  1168. err = errVhostsForbidden
  1169. return
  1170. }
  1171. // you can update your existing request, but if you were approved or rejected,
  1172. // you can't spam a new request
  1173. if output.RequestedVHost == "" {
  1174. err = output.checkThrottle(cooldown)
  1175. }
  1176. if err != nil {
  1177. return
  1178. }
  1179. output.RequestedVHost = vhost
  1180. output.RejectedVHost = ""
  1181. output.RejectionReason = ""
  1182. output.LastRequestTime = time.Now().UTC()
  1183. return
  1184. }
  1185. return am.performVHostChange(account, munger)
  1186. }
  1187. func (am *AccountManager) VHostTake(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
  1188. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1189. output = input
  1190. if input.Forbidden {
  1191. err = errVhostsForbidden
  1192. return
  1193. }
  1194. // if you have a request pending, you can cancel it using take;
  1195. // otherwise, you're subject to the same throttling as if you were making a request
  1196. if output.RequestedVHost == "" {
  1197. err = output.checkThrottle(cooldown)
  1198. }
  1199. if err != nil {
  1200. return
  1201. }
  1202. output.ApprovedVHost = vhost
  1203. output.RequestedVHost = ""
  1204. output.RejectedVHost = ""
  1205. output.RejectionReason = ""
  1206. output.LastRequestTime = time.Now().UTC()
  1207. return
  1208. }
  1209. return am.performVHostChange(account, munger)
  1210. }
  1211. func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
  1212. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1213. output = input
  1214. output.Enabled = true
  1215. output.ApprovedVHost = input.RequestedVHost
  1216. output.RequestedVHost = ""
  1217. output.RejectionReason = ""
  1218. return
  1219. }
  1220. return am.performVHostChange(account, munger)
  1221. }
  1222. func (am *AccountManager) VHostReject(account string, reason string) (result VHostInfo, err error) {
  1223. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1224. output = input
  1225. output.RejectedVHost = output.RequestedVHost
  1226. output.RequestedVHost = ""
  1227. output.RejectionReason = reason
  1228. return
  1229. }
  1230. return am.performVHostChange(account, munger)
  1231. }
  1232. func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (result VHostInfo, err error) {
  1233. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1234. if input.ApprovedVHost == "" {
  1235. err = errNoVhost
  1236. return
  1237. }
  1238. output = input
  1239. output.Enabled = enabled
  1240. return
  1241. }
  1242. return am.performVHostChange(client.Account(), munger)
  1243. }
  1244. func (am *AccountManager) VHostForbid(account string, forbid bool) (result VHostInfo, err error) {
  1245. munger := func(input VHostInfo) (output VHostInfo, err error) {
  1246. output = input
  1247. output.Forbidden = forbid
  1248. return
  1249. }
  1250. return am.performVHostChange(account, munger)
  1251. }
  1252. func (am *AccountManager) performVHostChange(account string, munger vhostMunger) (result VHostInfo, err error) {
  1253. account, err = CasefoldName(account)
  1254. if err != nil || account == "" {
  1255. err = errAccountDoesNotExist
  1256. return
  1257. }
  1258. am.vHostUpdateMutex.Lock()
  1259. defer am.vHostUpdateMutex.Unlock()
  1260. clientAccount, err := am.LoadAccount(account)
  1261. if err != nil {
  1262. err = errAccountDoesNotExist
  1263. return
  1264. } else if !clientAccount.Verified {
  1265. err = errAccountUnverified
  1266. return
  1267. }
  1268. result, err = munger(clientAccount.VHost)
  1269. if err != nil {
  1270. return
  1271. }
  1272. vhtext, err := json.Marshal(result)
  1273. if err != nil {
  1274. err = errAccountUpdateFailed
  1275. return
  1276. }
  1277. vhstr := string(vhtext)
  1278. key := fmt.Sprintf(keyAccountVHost, account)
  1279. queueKey := fmt.Sprintf(keyVHostQueueAcctToId, account)
  1280. err = am.server.store.Update(func(tx *buntdb.Tx) error {
  1281. if _, _, err := tx.Set(key, vhstr, nil); err != nil {
  1282. return err
  1283. }
  1284. // update request queue
  1285. if clientAccount.VHost.RequestedVHost == "" && result.RequestedVHost != "" {
  1286. id := atomic.AddUint64(&am.vhostRequestID, 1)
  1287. if _, _, err = tx.Set(queueKey, strconv.FormatUint(id, 10), nil); err != nil {
  1288. return err
  1289. }
  1290. atomic.AddUint64(&am.vhostRequestPendingCount, 1)
  1291. } else if clientAccount.VHost.RequestedVHost != "" && result.RequestedVHost == "" {
  1292. _, err = tx.Delete(queueKey)
  1293. am.decrementVHostQueueCount(account, err)
  1294. }
  1295. return nil
  1296. })
  1297. if err != nil {
  1298. err = errAccountUpdateFailed
  1299. return
  1300. }
  1301. am.applyVhostToClients(account, result)
  1302. return result, nil
  1303. }
  1304. // XXX annoying helper method for keeping the queue count in sync with the DB
  1305. // `err` is the buntdb error returned from deleting the queue key
  1306. func (am *AccountManager) decrementVHostQueueCount(account string, err error) {
  1307. if err == nil {
  1308. // successfully deleted a queue entry, do a 2's complement decrement:
  1309. atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
  1310. } else if err != buntdb.ErrNotFound {
  1311. am.server.logger.Error("internal", "buntdb dequeue error", account, err.Error())
  1312. }
  1313. }
  1314. func (am *AccountManager) VHostListRequests(limit int) (requests []PendingVHostRequest, total int) {
  1315. am.vHostUpdateMutex.Lock()
  1316. defer am.vHostUpdateMutex.Unlock()
  1317. total = int(atomic.LoadUint64(&am.vhostRequestPendingCount))
  1318. prefix := fmt.Sprintf(keyVHostQueueAcctToId, "")
  1319. accounts := make([]string, 0, limit)
  1320. err := am.server.store.View(func(tx *buntdb.Tx) error {
  1321. return tx.Ascend(vhostRequestIdx, func(key, value string) bool {
  1322. accounts = append(accounts, strings.TrimPrefix(key, prefix))
  1323. return len(accounts) < limit
  1324. })
  1325. })
  1326. if err != nil {
  1327. am.server.logger.Error("internal", "couldn't traverse vhost queue", err.Error())
  1328. return
  1329. }
  1330. for _, account := range accounts {
  1331. accountInfo, err := am.LoadAccount(account)
  1332. if err == nil {
  1333. requests = append(requests, PendingVHostRequest{
  1334. Account: account,
  1335. VHostInfo: accountInfo.VHost,
  1336. })
  1337. } else {
  1338. am.server.logger.Error("internal", "corrupt account", account, err.Error())
  1339. }
  1340. }
  1341. return
  1342. }
  1343. func (am *AccountManager) applyVHostInfo(client *Client, info VHostInfo) {
  1344. // if hostserv is disabled in config, then don't grant vhosts
  1345. // that were previously approved while it was enabled
  1346. if !am.server.Config().Accounts.VHosts.Enabled {
  1347. return
  1348. }
  1349. vhost := ""
  1350. if info.Enabled && !info.Forbidden {
  1351. vhost = info.ApprovedVHost
  1352. }
  1353. oldNickmask := client.NickMaskString()
  1354. updated := client.SetVHost(vhost)
  1355. if updated {
  1356. // TODO: doing I/O here is kind of a kludge
  1357. go client.sendChghost(oldNickmask, client.Hostname())
  1358. }
  1359. }
  1360. func (am *AccountManager) applyVhostToClients(account string, result VHostInfo) {
  1361. am.RLock()
  1362. clients := am.accountToClients[account]
  1363. am.RUnlock()
  1364. for _, client := range clients {
  1365. am.applyVHostInfo(client, result)
  1366. }
  1367. }
  1368. func (am *AccountManager) Login(client *Client, account ClientAccount) {
  1369. client.Login(account)
  1370. client.nickTimer.Touch(nil)
  1371. am.applyVHostInfo(client, account.VHost)
  1372. casefoldedAccount := client.Account()
  1373. am.Lock()
  1374. defer am.Unlock()
  1375. am.accountToClients[casefoldedAccount] = append(am.accountToClients[casefoldedAccount], client)
  1376. }
  1377. func (am *AccountManager) Logout(client *Client) {
  1378. am.Lock()
  1379. defer am.Unlock()
  1380. casefoldedAccount := client.Account()
  1381. if casefoldedAccount == "" {
  1382. return
  1383. }
  1384. am.logoutOfAccount(client)
  1385. clients := am.accountToClients[casefoldedAccount]
  1386. if len(clients) <= 1 {
  1387. delete(am.accountToClients, casefoldedAccount)
  1388. return
  1389. }
  1390. remainingClients := make([]*Client, len(clients)-1)
  1391. remainingPos := 0
  1392. for currentPos := 0; currentPos < len(clients); currentPos++ {
  1393. if clients[currentPos] != client {
  1394. remainingClients[remainingPos] = clients[currentPos]
  1395. remainingPos++
  1396. }
  1397. }
  1398. am.accountToClients[casefoldedAccount] = remainingClients
  1399. }
  1400. var (
  1401. // EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
  1402. // This can be moved to some other data structure/place if we need to load/unload mechs later.
  1403. EnabledSaslMechanisms = map[string]func(*Server, *Client, string, []byte, *ResponseBuffer) bool{
  1404. "PLAIN": authPlainHandler,
  1405. "EXTERNAL": authExternalHandler,
  1406. }
  1407. )
  1408. // AccountCredentials stores the various methods for verifying accounts.
  1409. type AccountCredentials struct {
  1410. Version uint
  1411. PassphraseSalt []byte // legacy field, not used by v1 and later
  1412. PassphraseHash []byte
  1413. Certfps []string
  1414. }
  1415. func (ac *AccountCredentials) Empty() bool {
  1416. return len(ac.PassphraseHash) == 0 && len(ac.Certfps) == 0
  1417. }
  1418. // helper to assemble the serialized JSON for an account's credentials
  1419. func (ac *AccountCredentials) Serialize() (result string, err error) {
  1420. ac.Version = 1
  1421. credText, err := json.Marshal(*ac)
  1422. if err != nil {
  1423. return "", err
  1424. }
  1425. return string(credText), nil
  1426. }
  1427. func (ac *AccountCredentials) SetPassphrase(passphrase string, bcryptCost uint) (err error) {
  1428. if passphrase == "" {
  1429. ac.PassphraseHash = nil
  1430. return nil
  1431. }
  1432. if validatePassphrase(passphrase) != nil {
  1433. return errAccountBadPassphrase
  1434. }
  1435. ac.PassphraseHash, err = passwd.GenerateFromPassword([]byte(passphrase), int(bcryptCost))
  1436. if err != nil {
  1437. return errAccountBadPassphrase
  1438. }
  1439. return nil
  1440. }
  1441. func (ac *AccountCredentials) AddCertfp(certfp string) (err error) {
  1442. // XXX we require that certfp is already normalized (rather than normalize here
  1443. // and pass back the normalized version as an additional return parameter);
  1444. // this is just a final sanity check:
  1445. if len(certfp) != 64 {
  1446. return utils.ErrInvalidCertfp
  1447. }
  1448. for _, current := range ac.Certfps {
  1449. if certfp == current {
  1450. return errNoop
  1451. }
  1452. }
  1453. if maxCertfpsPerAccount <= len(ac.Certfps) {
  1454. return errLimitExceeded
  1455. }
  1456. ac.Certfps = append(ac.Certfps, certfp)
  1457. return nil
  1458. }
  1459. func (ac *AccountCredentials) RemoveCertfp(certfp string) (err error) {
  1460. found := false
  1461. newList := make([]string, 0, len(ac.Certfps))
  1462. for _, current := range ac.Certfps {
  1463. if current == certfp {
  1464. found = true
  1465. } else {
  1466. newList = append(newList, current)
  1467. }
  1468. }
  1469. if !found {
  1470. // this is important because it prevents you from deleting someone else's
  1471. // fingerprint record
  1472. return errNoop
  1473. }
  1474. ac.Certfps = newList
  1475. return nil
  1476. }
  1477. type MulticlientAllowedSetting int
  1478. const (
  1479. MulticlientAllowedServerDefault MulticlientAllowedSetting = iota
  1480. MulticlientDisallowedByUser
  1481. MulticlientAllowedByUser
  1482. )
  1483. // controls whether/when clients without event-playback support see fake
  1484. // PRIVMSGs for JOINs
  1485. type ReplayJoinsSetting uint
  1486. const (
  1487. ReplayJoinsCommandsOnly = iota // replay in HISTORY or CHATHISTORY output
  1488. ReplayJoinsAlways // replay in HISTORY, CHATHISTORY, or autoreplay
  1489. ReplayJoinsNever // never replay
  1490. )
  1491. func replayJoinsSettingFromString(str string) (result ReplayJoinsSetting, err error) {
  1492. switch strings.ToLower(str) {
  1493. case "commands-only":
  1494. result = ReplayJoinsCommandsOnly
  1495. case "always":
  1496. result = ReplayJoinsAlways
  1497. case "never":
  1498. result = ReplayJoinsNever
  1499. default:
  1500. err = errInvalidParams
  1501. }
  1502. return
  1503. }
  1504. // XXX: AllowBouncer cannot be renamed AllowMulticlient because it is stored in
  1505. // persistent JSON blobs in the database
  1506. type AccountSettings struct {
  1507. AutoreplayLines *int
  1508. NickEnforcement NickEnforcementMethod
  1509. AllowBouncer MulticlientAllowedSetting
  1510. ReplayJoins ReplayJoinsSetting
  1511. AlwaysOn PersistentStatus
  1512. AutoreplayMissed bool
  1513. DMHistory HistoryStatus
  1514. }
  1515. // ClientAccount represents a user account.
  1516. type ClientAccount struct {
  1517. // Name of the account.
  1518. Name string
  1519. NameCasefolded string
  1520. RegisteredAt time.Time
  1521. Credentials AccountCredentials
  1522. Verified bool
  1523. AdditionalNicks []string
  1524. VHost VHostInfo
  1525. Settings AccountSettings
  1526. }
  1527. // convenience for passing around raw serialized account data
  1528. type rawClientAccount struct {
  1529. Name string
  1530. RegisteredAt string
  1531. Credentials string
  1532. Callback string
  1533. Verified bool
  1534. AdditionalNicks string
  1535. VHost string
  1536. Settings string
  1537. }
  1538. // logoutOfAccount logs the client out of their current account.
  1539. func (am *AccountManager) logoutOfAccount(client *Client) {
  1540. if client.Account() == "" {
  1541. // already logged out
  1542. return
  1543. }
  1544. client.Logout()
  1545. go client.nickTimer.Touch(nil)
  1546. // dispatch account-notify
  1547. // TODO: doing the I/O here is kind of a kludge, let's move this somewhere else
  1548. go func() {
  1549. for friend := range client.Friends(caps.AccountNotify) {
  1550. friend.Send(nil, client.NickMaskString(), "ACCOUNT", "*")
  1551. }
  1552. }()
  1553. }