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

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