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

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