Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

accounts.go 51KB

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