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

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