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

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