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.

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