Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

accounts.go 49KB

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