Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

accounts.go 59KB

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