You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

accounts.go 58KB

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