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.

config.go 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2014-2015 Edmund Huber
  3. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  4. // released under the MIT license
  5. package irc
  6. import (
  7. "crypto/tls"
  8. "fmt"
  9. "io/ioutil"
  10. "log"
  11. "net"
  12. "os"
  13. "regexp"
  14. "sort"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "code.cloudfoundry.org/bytefmt"
  19. "github.com/oragono/oragono/irc/caps"
  20. "github.com/oragono/oragono/irc/cloaks"
  21. "github.com/oragono/oragono/irc/connection_limits"
  22. "github.com/oragono/oragono/irc/custime"
  23. "github.com/oragono/oragono/irc/isupport"
  24. "github.com/oragono/oragono/irc/languages"
  25. "github.com/oragono/oragono/irc/logger"
  26. "github.com/oragono/oragono/irc/modes"
  27. "github.com/oragono/oragono/irc/passwd"
  28. "github.com/oragono/oragono/irc/utils"
  29. "gopkg.in/yaml.v2"
  30. )
  31. // here's how this works: exported (capitalized) members of the config structs
  32. // are defined in the YAML file and deserialized directly from there. They may
  33. // be postprocessed and overwritten by LoadConfig. Unexported (lowercase) members
  34. // are derived from the exported members in LoadConfig.
  35. // TLSListenConfig defines configuration options for listening on TLS.
  36. type TLSListenConfig struct {
  37. Cert string
  38. Key string
  39. }
  40. // This is the YAML-deserializable type of the value of the `Server.Listeners` map
  41. type listenerConfigBlock struct {
  42. TLS TLSListenConfig
  43. Tor bool
  44. STSOnly bool `yaml:"sts-only"`
  45. }
  46. // listenerConfig is the config governing a particular listener (bound address),
  47. // in particular whether it has TLS or Tor (or both) enabled.
  48. type listenerConfig struct {
  49. TLSConfig *tls.Config
  50. IsTor bool
  51. IsSTSOnly bool
  52. }
  53. type AccountConfig struct {
  54. Registration AccountRegistrationConfig
  55. AuthenticationEnabled bool `yaml:"authentication-enabled"`
  56. RequireSasl struct {
  57. Enabled bool
  58. Exempted []string
  59. exemptedNets []net.IPNet
  60. } `yaml:"require-sasl"`
  61. LoginThrottling struct {
  62. Enabled bool
  63. Duration time.Duration
  64. MaxAttempts int `yaml:"max-attempts"`
  65. } `yaml:"login-throttling"`
  66. SkipServerPassword bool `yaml:"skip-server-password"`
  67. NickReservation NickReservationConfig `yaml:"nick-reservation"`
  68. Bouncer struct {
  69. Enabled bool
  70. AllowedByDefault bool `yaml:"allowed-by-default"`
  71. }
  72. VHosts VHostConfig
  73. }
  74. // AccountRegistrationConfig controls account registration.
  75. type AccountRegistrationConfig struct {
  76. Enabled bool
  77. EnabledCallbacks []string `yaml:"enabled-callbacks"`
  78. EnabledCredentialTypes []string `yaml:"-"`
  79. VerifyTimeout time.Duration `yaml:"verify-timeout"`
  80. Callbacks struct {
  81. Mailto struct {
  82. Server string
  83. Port int
  84. TLS struct {
  85. Enabled bool
  86. InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
  87. ServerName string `yaml:"servername"`
  88. }
  89. Username string
  90. Password string
  91. Sender string
  92. VerifyMessageSubject string `yaml:"verify-message-subject"`
  93. VerifyMessage string `yaml:"verify-message"`
  94. }
  95. }
  96. BcryptCost uint `yaml:"bcrypt-cost"`
  97. }
  98. type VHostConfig struct {
  99. Enabled bool
  100. MaxLength int `yaml:"max-length"`
  101. ValidRegexpRaw string `yaml:"valid-regexp"`
  102. ValidRegexp *regexp.Regexp
  103. UserRequests struct {
  104. Enabled bool
  105. Channel string
  106. Cooldown time.Duration
  107. } `yaml:"user-requests"`
  108. }
  109. type NickEnforcementMethod int
  110. const (
  111. // NickEnforcementOptional is the zero value; it serializes to
  112. // "optional" in the yaml config, and "default" as an arg to `NS ENFORCE`.
  113. // in both cases, it means "defer to the other source of truth", i.e.,
  114. // in the config, defer to the user's custom setting, and as a custom setting,
  115. // defer to the default in the config. if both are NickEnforcementOptional then
  116. // there is no enforcement.
  117. // XXX: these are serialized as numbers in the database, so beware of collisions
  118. // when refactoring (any numbers currently in use must keep their meanings, or
  119. // else be fixed up by a schema change)
  120. NickEnforcementOptional NickEnforcementMethod = iota
  121. NickEnforcementNone
  122. NickEnforcementWithTimeout
  123. NickEnforcementStrict
  124. )
  125. func nickReservationToString(method NickEnforcementMethod) string {
  126. switch method {
  127. case NickEnforcementOptional:
  128. return "default"
  129. case NickEnforcementNone:
  130. return "none"
  131. case NickEnforcementWithTimeout:
  132. return "timeout"
  133. case NickEnforcementStrict:
  134. return "strict"
  135. default:
  136. return ""
  137. }
  138. }
  139. func nickReservationFromString(method string) (NickEnforcementMethod, error) {
  140. switch strings.ToLower(method) {
  141. case "default":
  142. return NickEnforcementOptional, nil
  143. case "optional":
  144. return NickEnforcementOptional, nil
  145. case "none":
  146. return NickEnforcementNone, nil
  147. case "timeout":
  148. return NickEnforcementWithTimeout, nil
  149. case "strict":
  150. return NickEnforcementStrict, nil
  151. default:
  152. return NickEnforcementOptional, fmt.Errorf("invalid nick-reservation.method value: %s", method)
  153. }
  154. }
  155. func (nr *NickEnforcementMethod) UnmarshalYAML(unmarshal func(interface{}) error) error {
  156. var orig string
  157. var err error
  158. if err = unmarshal(&orig); err != nil {
  159. return err
  160. }
  161. method, err := nickReservationFromString(orig)
  162. if err == nil {
  163. *nr = method
  164. }
  165. return err
  166. }
  167. type NickReservationConfig struct {
  168. Enabled bool
  169. AdditionalNickLimit int `yaml:"additional-nick-limit"`
  170. Method NickEnforcementMethod
  171. AllowCustomEnforcement bool `yaml:"allow-custom-enforcement"`
  172. RenameTimeout time.Duration `yaml:"rename-timeout"`
  173. RenamePrefix string `yaml:"rename-prefix"`
  174. }
  175. // ChannelRegistrationConfig controls channel registration.
  176. type ChannelRegistrationConfig struct {
  177. Enabled bool
  178. MaxChannelsPerAccount int `yaml:"max-channels-per-account"`
  179. }
  180. // OperClassConfig defines a specific operator class.
  181. type OperClassConfig struct {
  182. Title string
  183. WhoisLine string
  184. Extends string
  185. Capabilities []string
  186. }
  187. // OperConfig defines a specific operator's configuration.
  188. type OperConfig struct {
  189. Class string
  190. Vhost string
  191. WhoisLine string `yaml:"whois-line"`
  192. Password string
  193. Modes string
  194. }
  195. // LineLenConfig controls line lengths.
  196. type LineLenLimits struct {
  197. Rest int
  198. }
  199. // Various server-enforced limits on data size.
  200. type Limits struct {
  201. AwayLen int `yaml:"awaylen"`
  202. ChanListModes int `yaml:"chan-list-modes"`
  203. ChannelLen int `yaml:"channellen"`
  204. IdentLen int `yaml:"identlen"`
  205. KickLen int `yaml:"kicklen"`
  206. LineLen LineLenLimits `yaml:"linelen"`
  207. MonitorEntries int `yaml:"monitor-entries"`
  208. NickLen int `yaml:"nicklen"`
  209. TopicLen int `yaml:"topiclen"`
  210. WhowasEntries int `yaml:"whowas-entries"`
  211. RegistrationMessages int `yaml:"registration-messages"`
  212. }
  213. // STSConfig controls the STS configuration/
  214. type STSConfig struct {
  215. Enabled bool
  216. Duration time.Duration `yaml:"duration-real"`
  217. DurationString string `yaml:"duration"`
  218. Port int
  219. Preload bool
  220. STSOnlyBanner string `yaml:"sts-only-banner"`
  221. bannerLines []string
  222. }
  223. // Value returns the STS value to advertise in CAP
  224. func (sts *STSConfig) Value() string {
  225. val := fmt.Sprintf("duration=%d", int(sts.Duration.Seconds()))
  226. if sts.Enabled && sts.Port > 0 {
  227. val += fmt.Sprintf(",port=%d", sts.Port)
  228. }
  229. if sts.Enabled && sts.Preload {
  230. val += ",preload"
  231. }
  232. return val
  233. }
  234. type FakelagConfig struct {
  235. Enabled bool
  236. Window time.Duration
  237. BurstLimit uint `yaml:"burst-limit"`
  238. MessagesPerWindow uint `yaml:"messages-per-window"`
  239. Cooldown time.Duration
  240. }
  241. type TorListenersConfig struct {
  242. Listeners []string // legacy only
  243. RequireSasl bool `yaml:"require-sasl"`
  244. Vhost string
  245. MaxConnections int `yaml:"max-connections"`
  246. ThrottleDuration time.Duration `yaml:"throttle-duration"`
  247. MaxConnectionsPerDuration int `yaml:"max-connections-per-duration"`
  248. }
  249. // Config defines the overall configuration.
  250. type Config struct {
  251. Network struct {
  252. Name string
  253. }
  254. Server struct {
  255. Password string
  256. passwordBytes []byte
  257. Name string
  258. nameCasefolded string
  259. // Listeners is the new style for configuring listeners:
  260. Listeners map[string]listenerConfigBlock
  261. UnixBindMode os.FileMode `yaml:"unix-bind-mode"`
  262. TorListeners TorListenersConfig `yaml:"tor-listeners"`
  263. // Listen and TLSListeners are the legacy style:
  264. Listen []string
  265. TLSListeners map[string]TLSListenConfig `yaml:"tls-listeners"`
  266. // either way, the result is this:
  267. trueListeners map[string]listenerConfig
  268. STS STSConfig
  269. CheckIdent bool `yaml:"check-ident"`
  270. MOTD string
  271. motdLines []string
  272. MOTDFormatting bool `yaml:"motd-formatting"`
  273. ProxyAllowedFrom []string `yaml:"proxy-allowed-from"`
  274. proxyAllowedFromNets []net.IPNet
  275. WebIRC []webircConfig `yaml:"webirc"`
  276. MaxSendQString string `yaml:"max-sendq"`
  277. MaxSendQBytes int
  278. AllowPlaintextResume bool `yaml:"allow-plaintext-resume"`
  279. Compatibility struct {
  280. ForceTrailing *bool `yaml:"force-trailing"`
  281. forceTrailing bool
  282. SendUnprefixedSasl bool `yaml:"send-unprefixed-sasl"`
  283. }
  284. isupport isupport.List
  285. ConnectionLimiter connection_limits.LimiterConfig `yaml:"connection-limits"`
  286. ConnectionThrottler connection_limits.ThrottlerConfig `yaml:"connection-throttling"`
  287. Cloaks cloaks.CloakConfig `yaml:"ip-cloaking"`
  288. supportedCaps *caps.Set
  289. capValues caps.Values
  290. }
  291. Languages struct {
  292. Enabled bool
  293. Path string
  294. Default string
  295. }
  296. languageManager *languages.Manager
  297. Datastore struct {
  298. Path string
  299. AutoUpgrade bool
  300. }
  301. Accounts AccountConfig
  302. Channels struct {
  303. DefaultModes *string `yaml:"default-modes"`
  304. defaultModes modes.Modes
  305. MaxChannelsPerClient int `yaml:"max-channels-per-client"`
  306. OpOnlyCreation bool `yaml:"operator-only-creation"`
  307. Registration ChannelRegistrationConfig
  308. }
  309. OperClasses map[string]*OperClassConfig `yaml:"oper-classes"`
  310. Opers map[string]*OperConfig
  311. // parsed operator definitions, unexported so they can't be defined
  312. // directly in YAML:
  313. operators map[string]*Oper
  314. Logging []logger.LoggingConfig
  315. Debug struct {
  316. RecoverFromErrors *bool `yaml:"recover-from-errors"`
  317. recoverFromErrors bool
  318. PprofListener *string `yaml:"pprof-listener"`
  319. }
  320. Limits Limits
  321. Fakelag FakelagConfig
  322. History struct {
  323. Enabled bool
  324. ChannelLength int `yaml:"channel-length"`
  325. ClientLength int `yaml:"client-length"`
  326. AutoresizeWindow time.Duration `yaml:"autoresize-window"`
  327. AutoreplayOnJoin int `yaml:"autoreplay-on-join"`
  328. ChathistoryMax int `yaml:"chathistory-maxmessages"`
  329. }
  330. Filename string
  331. }
  332. // OperClass defines an assembled operator class.
  333. type OperClass struct {
  334. Title string
  335. WhoisLine string `yaml:"whois-line"`
  336. Capabilities map[string]bool // map to make lookups much easier
  337. }
  338. // OperatorClasses returns a map of assembled operator classes from the given config.
  339. func (conf *Config) OperatorClasses() (map[string]*OperClass, error) {
  340. ocs := make(map[string]*OperClass)
  341. // loop from no extends to most extended, breaking if we can't add any more
  342. lenOfLastOcs := -1
  343. for {
  344. if lenOfLastOcs == len(ocs) {
  345. return nil, ErrOperClassDependencies
  346. }
  347. lenOfLastOcs = len(ocs)
  348. var anyMissing bool
  349. for name, info := range conf.OperClasses {
  350. _, exists := ocs[name]
  351. _, extendsExists := ocs[info.Extends]
  352. if exists {
  353. // class already exists
  354. continue
  355. } else if len(info.Extends) > 0 && !extendsExists {
  356. // class we extend on doesn't exist
  357. _, exists := conf.OperClasses[info.Extends]
  358. if !exists {
  359. return nil, fmt.Errorf("Operclass [%s] extends [%s], which doesn't exist", name, info.Extends)
  360. }
  361. anyMissing = true
  362. continue
  363. }
  364. // create new operclass
  365. var oc OperClass
  366. oc.Capabilities = make(map[string]bool)
  367. // get inhereted info from other operclasses
  368. if len(info.Extends) > 0 {
  369. einfo := ocs[info.Extends]
  370. for capab := range einfo.Capabilities {
  371. oc.Capabilities[capab] = true
  372. }
  373. }
  374. // add our own info
  375. oc.Title = info.Title
  376. for _, capab := range info.Capabilities {
  377. oc.Capabilities[capab] = true
  378. }
  379. if len(info.WhoisLine) > 0 {
  380. oc.WhoisLine = info.WhoisLine
  381. } else {
  382. oc.WhoisLine = "is a"
  383. if strings.Contains(strings.ToLower(string(oc.Title[0])), "aeiou") {
  384. oc.WhoisLine += "n"
  385. }
  386. oc.WhoisLine += " "
  387. oc.WhoisLine += oc.Title
  388. }
  389. ocs[name] = &oc
  390. }
  391. if !anyMissing {
  392. // we've got every operclass!
  393. break
  394. }
  395. }
  396. return ocs, nil
  397. }
  398. // Oper represents a single assembled operator's config.
  399. type Oper struct {
  400. Name string
  401. Class *OperClass
  402. WhoisLine string
  403. Vhost string
  404. Pass []byte
  405. Modes []modes.ModeChange
  406. }
  407. // Operators returns a map of operator configs from the given OperClass and config.
  408. func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error) {
  409. operators := make(map[string]*Oper)
  410. for name, opConf := range conf.Opers {
  411. var oper Oper
  412. // oper name
  413. name, err := CasefoldName(name)
  414. if err != nil {
  415. return nil, fmt.Errorf("Could not casefold oper name: %s", err.Error())
  416. }
  417. oper.Name = name
  418. oper.Pass, err = decodeLegacyPasswordHash(opConf.Password)
  419. if err != nil {
  420. return nil, err
  421. }
  422. oper.Vhost = opConf.Vhost
  423. class, exists := oc[opConf.Class]
  424. if !exists {
  425. return nil, fmt.Errorf("Could not load operator [%s] - they use operclass [%s] which does not exist", name, opConf.Class)
  426. }
  427. oper.Class = class
  428. if len(opConf.WhoisLine) > 0 {
  429. oper.WhoisLine = opConf.WhoisLine
  430. } else {
  431. oper.WhoisLine = class.WhoisLine
  432. }
  433. modeStr := strings.TrimSpace(opConf.Modes)
  434. modeChanges, unknownChanges := modes.ParseUserModeChanges(strings.Split(modeStr, " ")...)
  435. if len(unknownChanges) > 0 {
  436. return nil, fmt.Errorf("Could not load operator [%s] due to unknown modes %v", name, unknownChanges)
  437. }
  438. oper.Modes = modeChanges
  439. // successful, attach to list of opers
  440. operators[name] = &oper
  441. }
  442. return operators, nil
  443. }
  444. func loadTlsConfig(config TLSListenConfig) (tlsConfig *tls.Config, err error) {
  445. cert, err := tls.LoadX509KeyPair(config.Cert, config.Key)
  446. if err != nil {
  447. return nil, ErrInvalidCertKeyPair
  448. }
  449. result := tls.Config{
  450. Certificates: []tls.Certificate{cert},
  451. ClientAuth: tls.RequestClientCert,
  452. }
  453. return &result, nil
  454. }
  455. // prepareListeners populates Config.Server.trueListeners
  456. func (conf *Config) prepareListeners() (err error) {
  457. listeners := make(map[string]listenerConfig)
  458. if 0 < len(conf.Server.Listeners) {
  459. for addr, block := range conf.Server.Listeners {
  460. var lconf listenerConfig
  461. lconf.IsTor = block.Tor
  462. lconf.IsSTSOnly = block.STSOnly
  463. if lconf.IsSTSOnly && !conf.Server.STS.Enabled {
  464. return fmt.Errorf("%s is configured as a STS-only listener, but STS is disabled", addr)
  465. }
  466. if block.TLS.Cert != "" {
  467. tlsConfig, err := loadTlsConfig(block.TLS)
  468. if err != nil {
  469. return err
  470. }
  471. lconf.TLSConfig = tlsConfig
  472. }
  473. listeners[addr] = lconf
  474. }
  475. } else if 0 < len(conf.Server.Listen) {
  476. log.Printf("WARNING: configuring listeners via the legacy `server.listen` config option")
  477. log.Printf("This will be removed in a later release: you should update to use `server.listeners`")
  478. torListeners := make(map[string]bool, len(conf.Server.TorListeners.Listeners))
  479. for _, addr := range conf.Server.TorListeners.Listeners {
  480. torListeners[addr] = true
  481. }
  482. for _, addr := range conf.Server.Listen {
  483. var lconf listenerConfig
  484. lconf.IsTor = torListeners[addr]
  485. tlsListenConf, ok := conf.Server.TLSListeners[addr]
  486. if ok {
  487. tlsConfig, err := loadTlsConfig(tlsListenConf)
  488. if err != nil {
  489. return err
  490. }
  491. lconf.TLSConfig = tlsConfig
  492. }
  493. listeners[addr] = lconf
  494. }
  495. } else {
  496. return fmt.Errorf("No listeners were configured")
  497. }
  498. conf.Server.trueListeners = listeners
  499. return nil
  500. }
  501. // LoadRawConfig loads the config without doing any consistency checks or postprocessing
  502. func LoadRawConfig(filename string) (config *Config, err error) {
  503. data, err := ioutil.ReadFile(filename)
  504. if err != nil {
  505. return nil, err
  506. }
  507. err = yaml.Unmarshal(data, &config)
  508. if err != nil {
  509. return nil, err
  510. }
  511. return
  512. }
  513. // LoadConfig loads the given YAML configuration file.
  514. func LoadConfig(filename string) (config *Config, err error) {
  515. config, err = LoadRawConfig(filename)
  516. if err != nil {
  517. return nil, err
  518. }
  519. config.Filename = filename
  520. if config.Network.Name == "" {
  521. return nil, ErrNetworkNameMissing
  522. }
  523. if config.Server.Name == "" {
  524. return nil, ErrServerNameMissing
  525. }
  526. if !utils.IsHostname(config.Server.Name) {
  527. return nil, ErrServerNameNotHostname
  528. }
  529. if config.Datastore.Path == "" {
  530. return nil, ErrDatastorePathMissing
  531. }
  532. //dan: automagically fix identlen until a few releases in the future (from now, 0.12.0), being a newly-introduced limit
  533. if config.Limits.IdentLen < 1 {
  534. config.Limits.IdentLen = 20
  535. }
  536. if config.Limits.NickLen < 1 || config.Limits.ChannelLen < 2 || config.Limits.AwayLen < 1 || config.Limits.KickLen < 1 || config.Limits.TopicLen < 1 {
  537. return nil, ErrLimitsAreInsane
  538. }
  539. if config.Limits.RegistrationMessages == 0 {
  540. config.Limits.RegistrationMessages = 1024
  541. }
  542. config.Server.supportedCaps = caps.NewCompleteSet()
  543. config.Server.capValues = make(caps.Values)
  544. err = config.prepareListeners()
  545. if err != nil {
  546. return nil, fmt.Errorf("failed to prepare listeners: %v", err)
  547. }
  548. if config.Server.STS.Enabled {
  549. config.Server.STS.Duration, err = custime.ParseDuration(config.Server.STS.DurationString)
  550. if err != nil {
  551. return nil, fmt.Errorf("Could not parse STS duration: %s", err.Error())
  552. }
  553. if config.Server.STS.Port < 0 || config.Server.STS.Port > 65535 {
  554. return nil, fmt.Errorf("STS port is incorrect, should be 0 if disabled: %d", config.Server.STS.Port)
  555. }
  556. if config.Server.STS.STSOnlyBanner != "" {
  557. config.Server.STS.bannerLines = utils.WordWrap(config.Server.STS.STSOnlyBanner, 400)
  558. } else {
  559. config.Server.STS.bannerLines = []string{fmt.Sprintf("This server is only accessible over TLS. Please reconnect using TLS on port %d.", config.Server.STS.Port)}
  560. }
  561. } else {
  562. config.Server.supportedCaps.Disable(caps.STS)
  563. config.Server.STS.Duration = 0
  564. }
  565. // set this even if STS is disabled
  566. config.Server.capValues[caps.STS] = config.Server.STS.Value()
  567. if config.Server.ConnectionThrottler.Enabled {
  568. config.Server.ConnectionThrottler.Duration, err = time.ParseDuration(config.Server.ConnectionThrottler.DurationString)
  569. if err != nil {
  570. return nil, fmt.Errorf("Could not parse connection-throttle duration: %s", err.Error())
  571. }
  572. config.Server.ConnectionThrottler.BanDuration, err = time.ParseDuration(config.Server.ConnectionThrottler.BanDurationString)
  573. if err != nil {
  574. return nil, fmt.Errorf("Could not parse connection-throttle ban-duration: %s", err.Error())
  575. }
  576. }
  577. // process webirc blocks
  578. var newWebIRC []webircConfig
  579. for _, webirc := range config.Server.WebIRC {
  580. // skip webirc blocks with no hosts (such as the example one)
  581. if len(webirc.Hosts) == 0 {
  582. continue
  583. }
  584. err = webirc.Populate()
  585. if err != nil {
  586. return nil, fmt.Errorf("Could not parse WebIRC config: %s", err.Error())
  587. }
  588. newWebIRC = append(newWebIRC, webirc)
  589. }
  590. config.Server.WebIRC = newWebIRC
  591. // process limits
  592. if config.Limits.LineLen.Rest < 512 {
  593. config.Limits.LineLen.Rest = 512
  594. }
  595. if config.Limits.LineLen.Rest == 512 {
  596. config.Server.supportedCaps.Disable(caps.MaxLine)
  597. } else {
  598. config.Server.capValues[caps.MaxLine] = strconv.Itoa(config.Limits.LineLen.Rest)
  599. }
  600. if !config.Accounts.Bouncer.Enabled {
  601. config.Server.supportedCaps.Disable(caps.Bouncer)
  602. }
  603. var newLogConfigs []logger.LoggingConfig
  604. for _, logConfig := range config.Logging {
  605. // methods
  606. methods := make(map[string]bool)
  607. for _, method := range strings.Split(logConfig.Method, " ") {
  608. if len(method) > 0 {
  609. methods[strings.ToLower(method)] = true
  610. }
  611. }
  612. if methods["file"] && logConfig.Filename == "" {
  613. return nil, ErrLoggerFilenameMissing
  614. }
  615. logConfig.MethodFile = methods["file"]
  616. logConfig.MethodStdout = methods["stdout"]
  617. logConfig.MethodStderr = methods["stderr"]
  618. // levels
  619. level, exists := logger.LogLevelNames[strings.ToLower(logConfig.LevelString)]
  620. if !exists {
  621. return nil, fmt.Errorf("Could not translate log leve [%s]", logConfig.LevelString)
  622. }
  623. logConfig.Level = level
  624. // types
  625. for _, typeStr := range strings.Split(logConfig.TypeString, " ") {
  626. if len(typeStr) == 0 {
  627. continue
  628. }
  629. if typeStr == "-" {
  630. return nil, ErrLoggerExcludeEmpty
  631. }
  632. if typeStr[0] == '-' {
  633. typeStr = typeStr[1:]
  634. logConfig.ExcludedTypes = append(logConfig.ExcludedTypes, typeStr)
  635. } else {
  636. logConfig.Types = append(logConfig.Types, typeStr)
  637. }
  638. }
  639. if len(logConfig.Types) < 1 {
  640. return nil, ErrLoggerHasNoTypes
  641. }
  642. newLogConfigs = append(newLogConfigs, logConfig)
  643. }
  644. config.Logging = newLogConfigs
  645. // hardcode this for now
  646. config.Accounts.Registration.EnabledCredentialTypes = []string{"passphrase", "certfp"}
  647. for i, name := range config.Accounts.Registration.EnabledCallbacks {
  648. if name == "none" {
  649. // we store "none" as "*" internally
  650. config.Accounts.Registration.EnabledCallbacks[i] = "*"
  651. }
  652. }
  653. sort.Strings(config.Accounts.Registration.EnabledCallbacks)
  654. config.Accounts.RequireSasl.exemptedNets, err = utils.ParseNetList(config.Accounts.RequireSasl.Exempted)
  655. if err != nil {
  656. return nil, fmt.Errorf("Could not parse require-sasl exempted nets: %v", err.Error())
  657. }
  658. config.Server.proxyAllowedFromNets, err = utils.ParseNetList(config.Server.ProxyAllowedFrom)
  659. if err != nil {
  660. return nil, fmt.Errorf("Could not parse proxy-allowed-from nets: %v", err.Error())
  661. }
  662. rawRegexp := config.Accounts.VHosts.ValidRegexpRaw
  663. if rawRegexp != "" {
  664. regexp, err := regexp.Compile(rawRegexp)
  665. if err == nil {
  666. config.Accounts.VHosts.ValidRegexp = regexp
  667. } else {
  668. log.Printf("invalid vhost regexp: %s\n", err.Error())
  669. }
  670. }
  671. if config.Accounts.VHosts.ValidRegexp == nil {
  672. config.Accounts.VHosts.ValidRegexp = defaultValidVhostRegex
  673. }
  674. if !config.Accounts.LoginThrottling.Enabled {
  675. config.Accounts.LoginThrottling.MaxAttempts = 0 // limit of 0 means disabled
  676. }
  677. config.Server.capValues[caps.SASL] = "PLAIN,EXTERNAL"
  678. if !config.Accounts.AuthenticationEnabled {
  679. config.Server.supportedCaps.Disable(caps.SASL)
  680. }
  681. maxSendQBytes, err := bytefmt.ToBytes(config.Server.MaxSendQString)
  682. if err != nil {
  683. return nil, fmt.Errorf("Could not parse maximum SendQ size (make sure it only contains whole numbers): %s", err.Error())
  684. }
  685. config.Server.MaxSendQBytes = int(maxSendQBytes)
  686. config.languageManager, err = languages.NewManager(config.Languages.Enabled, config.Languages.Path, config.Languages.Default)
  687. if err != nil {
  688. return nil, fmt.Errorf("Could not load languages: %s", err.Error())
  689. }
  690. config.Server.capValues[caps.Languages] = config.languageManager.CapValue()
  691. // RecoverFromErrors defaults to true
  692. if config.Debug.RecoverFromErrors != nil {
  693. config.Debug.recoverFromErrors = *config.Debug.RecoverFromErrors
  694. } else {
  695. config.Debug.recoverFromErrors = true
  696. }
  697. // casefold/validate server name
  698. config.Server.nameCasefolded, err = Casefold(config.Server.Name)
  699. if err != nil {
  700. return nil, fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error())
  701. }
  702. // process operator definitions, store them to config.operators
  703. operclasses, err := config.OperatorClasses()
  704. if err != nil {
  705. return nil, err
  706. }
  707. opers, err := config.Operators(operclasses)
  708. if err != nil {
  709. return nil, err
  710. }
  711. config.operators = opers
  712. // parse default channel modes
  713. config.Channels.defaultModes = ParseDefaultChannelModes(config.Channels.DefaultModes)
  714. if config.Server.Password != "" {
  715. config.Server.passwordBytes, err = decodeLegacyPasswordHash(config.Server.Password)
  716. if err != nil {
  717. return nil, err
  718. }
  719. }
  720. if config.Accounts.Registration.BcryptCost == 0 {
  721. config.Accounts.Registration.BcryptCost = passwd.DefaultCost
  722. }
  723. if config.Channels.MaxChannelsPerClient == 0 {
  724. config.Channels.MaxChannelsPerClient = 100
  725. }
  726. if config.Channels.Registration.MaxChannelsPerAccount == 0 {
  727. config.Channels.Registration.MaxChannelsPerAccount = 15
  728. }
  729. forceTrailingPtr := config.Server.Compatibility.ForceTrailing
  730. if forceTrailingPtr != nil {
  731. config.Server.Compatibility.forceTrailing = *forceTrailingPtr
  732. } else {
  733. config.Server.Compatibility.forceTrailing = true
  734. }
  735. config.loadMOTD()
  736. err = config.generateISupport()
  737. if err != nil {
  738. return nil, err
  739. }
  740. // in the current implementation, we disable history by creating a history buffer
  741. // with zero capacity. but the `enabled` config option MUST be respected regardless
  742. // of this detail
  743. if !config.History.Enabled {
  744. config.History.ChannelLength = 0
  745. config.History.ClientLength = 0
  746. }
  747. config.Server.Cloaks.Initialize()
  748. if config.Server.Cloaks.Enabled {
  749. if config.Server.Cloaks.Secret == "" || config.Server.Cloaks.Secret == "siaELnk6Kaeo65K3RCrwJjlWaZ-Bt3WuZ2L8MXLbNb4" {
  750. return nil, fmt.Errorf("You must generate a new value of server.ip-cloaking.secret to enable cloaking")
  751. }
  752. }
  753. return config, nil
  754. }