Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

server.go 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  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. "bufio"
  8. "crypto/tls"
  9. "fmt"
  10. "net"
  11. "net/http"
  12. _ "net/http/pprof"
  13. "os"
  14. "os/signal"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "syscall"
  19. "time"
  20. "unsafe"
  21. "github.com/goshuirc/irc-go/ircfmt"
  22. "github.com/oragono/oragono/irc/caps"
  23. "github.com/oragono/oragono/irc/connection_limits"
  24. "github.com/oragono/oragono/irc/logger"
  25. "github.com/oragono/oragono/irc/modes"
  26. "github.com/oragono/oragono/irc/sno"
  27. "github.com/oragono/oragono/irc/utils"
  28. "github.com/tidwall/buntdb"
  29. )
  30. var (
  31. // common error line to sub values into
  32. errorMsg = "ERROR :%s\r\n"
  33. // supportedUserModesString acts as a cache for when we introduce users
  34. supportedUserModesString = modes.SupportedUserModes.String()
  35. // supportedChannelModesString acts as a cache for when we introduce users
  36. supportedChannelModesString = modes.SupportedChannelModes.String()
  37. // SupportedCapabilities are the caps we advertise.
  38. // MaxLine, SASL and STS may be unset during server startup / rehash.
  39. SupportedCapabilities = caps.NewCompleteSet()
  40. // CapValues are the actual values we advertise to v3.2 clients.
  41. // actual values are set during server startup.
  42. CapValues = caps.NewValues()
  43. )
  44. // ListenerWrapper wraps a listener so it can be safely reconfigured or stopped
  45. type ListenerWrapper struct {
  46. listener net.Listener
  47. tlsConfig *tls.Config
  48. isTor bool
  49. shouldStop bool
  50. // protects atomic update of tlsConfig and shouldStop:
  51. configMutex sync.Mutex // tier 1
  52. }
  53. // Server is the main Oragono server.
  54. type Server struct {
  55. accounts AccountManager
  56. channels ChannelManager
  57. channelRegistry ChannelRegistry
  58. clients ClientManager
  59. config unsafe.Pointer
  60. configFilename string
  61. connectionLimiter *connection_limits.Limiter
  62. connectionThrottler *connection_limits.Throttler
  63. ctime time.Time
  64. dlines *DLineManager
  65. helpIndexManager HelpIndexManager
  66. klines *KLineManager
  67. listeners map[string]*ListenerWrapper
  68. logger *logger.Manager
  69. monitorManager *MonitorManager
  70. name string
  71. nameCasefolded string
  72. rehashMutex sync.Mutex // tier 4
  73. rehashSignal chan os.Signal
  74. pprofServer *http.Server
  75. resumeManager ResumeManager
  76. signals chan os.Signal
  77. snomasks *SnoManager
  78. store *buntdb.DB
  79. torLimiter connection_limits.TorLimiter
  80. whoWas WhoWasList
  81. stats Stats
  82. semaphores ServerSemaphores
  83. }
  84. var (
  85. // ServerExitSignals are the signals the server will exit on.
  86. ServerExitSignals = []os.Signal{
  87. syscall.SIGINT,
  88. syscall.SIGTERM,
  89. syscall.SIGQUIT,
  90. }
  91. )
  92. type clientConn struct {
  93. Conn net.Conn
  94. IsTLS bool
  95. IsTor bool
  96. }
  97. // NewServer returns a new Oragono server.
  98. func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
  99. // initialize data structures
  100. server := &Server{
  101. connectionLimiter: connection_limits.NewLimiter(),
  102. connectionThrottler: connection_limits.NewThrottler(),
  103. listeners: make(map[string]*ListenerWrapper),
  104. logger: logger,
  105. monitorManager: NewMonitorManager(),
  106. rehashSignal: make(chan os.Signal, 1),
  107. signals: make(chan os.Signal, len(ServerExitSignals)),
  108. snomasks: NewSnoManager(),
  109. }
  110. server.clients.Initialize()
  111. server.semaphores.Initialize()
  112. server.resumeManager.Initialize(server)
  113. server.whoWas.Initialize(config.Limits.WhowasEntries)
  114. if err := server.applyConfig(config, true); err != nil {
  115. return nil, err
  116. }
  117. // Attempt to clean up when receiving these signals.
  118. signal.Notify(server.signals, ServerExitSignals...)
  119. signal.Notify(server.rehashSignal, syscall.SIGHUP)
  120. return server, nil
  121. }
  122. // setISupport sets up our RPL_ISUPPORT reply.
  123. func (config *Config) generateISupport() (err error) {
  124. maxTargetsString := strconv.Itoa(maxTargets)
  125. // add RPL_ISUPPORT tokens
  126. isupport := &config.Server.isupport
  127. isupport.Initialize()
  128. isupport.Add("AWAYLEN", strconv.Itoa(config.Limits.AwayLen))
  129. isupport.Add("CASEMAPPING", "ascii")
  130. isupport.Add("CHANMODES", strings.Join([]string{modes.Modes{modes.BanMask, modes.ExceptMask, modes.InviteMask}.String(), "", modes.Modes{modes.UserLimit, modes.Key}.String(), modes.Modes{modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.ChanRoleplaying, modes.Secret}.String()}, ","))
  131. if config.History.Enabled && config.History.ChathistoryMax > 0 {
  132. isupport.Add("draft/CHATHISTORY", strconv.Itoa(config.History.ChathistoryMax))
  133. }
  134. isupport.Add("CHANNELLEN", strconv.Itoa(config.Limits.ChannelLen))
  135. isupport.Add("CHANTYPES", "#")
  136. isupport.Add("ELIST", "U")
  137. isupport.Add("EXCEPTS", "")
  138. isupport.Add("INVEX", "")
  139. isupport.Add("KICKLEN", strconv.Itoa(config.Limits.KickLen))
  140. isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(config.Limits.ChanListModes)))
  141. isupport.Add("MAXTARGETS", maxTargetsString)
  142. isupport.Add("MODES", "")
  143. isupport.Add("MONITOR", strconv.Itoa(config.Limits.MonitorEntries))
  144. isupport.Add("NETWORK", config.Network.Name)
  145. isupport.Add("NICKLEN", strconv.Itoa(config.Limits.NickLen))
  146. isupport.Add("PREFIX", "(qaohv)~&@%+")
  147. isupport.Add("RPCHAN", "E")
  148. isupport.Add("RPUSER", "E")
  149. isupport.Add("STATUSMSG", "~&@%+")
  150. isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:%s,TAGMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString, maxTargetsString))
  151. isupport.Add("TOPICLEN", strconv.Itoa(config.Limits.TopicLen))
  152. isupport.Add("UTF8MAPPING", casemappingName)
  153. err = isupport.RegenerateCachedReply()
  154. return
  155. }
  156. // Shutdown shuts down the server.
  157. func (server *Server) Shutdown() {
  158. //TODO(dan): Make sure we disallow new nicks
  159. for _, client := range server.clients.AllClients() {
  160. client.Notice("Server is shutting down")
  161. }
  162. if err := server.store.Close(); err != nil {
  163. server.logger.Error("shutdown", fmt.Sprintln("Could not close datastore:", err))
  164. }
  165. }
  166. // Run starts the server.
  167. func (server *Server) Run() {
  168. // defer closing db/store
  169. defer server.store.Close()
  170. for {
  171. select {
  172. case <-server.signals:
  173. server.Shutdown()
  174. return
  175. case <-server.rehashSignal:
  176. go func() {
  177. server.logger.Info("server", "Rehashing due to SIGHUP")
  178. err := server.rehash()
  179. if err != nil {
  180. server.logger.Error("server", fmt.Sprintln("Failed to rehash:", err.Error()))
  181. }
  182. }()
  183. }
  184. }
  185. }
  186. func (server *Server) acceptClient(conn clientConn) {
  187. var isBanned bool
  188. var banMsg string
  189. var ipaddr net.IP
  190. if conn.IsTor {
  191. ipaddr = utils.IPv4LoopbackAddress
  192. isBanned, banMsg = server.checkTorLimits()
  193. } else {
  194. ipaddr = utils.AddrToIP(conn.Conn.RemoteAddr())
  195. isBanned, banMsg = server.checkBans(ipaddr)
  196. }
  197. if isBanned {
  198. // this might not show up properly on some clients, but our objective here is just to close the connection out before it has a load impact on us
  199. conn.Conn.Write([]byte(fmt.Sprintf(errorMsg, banMsg)))
  200. conn.Conn.Close()
  201. return
  202. }
  203. server.logger.Info("localconnect-ip", fmt.Sprintf("Client connecting from %v", ipaddr))
  204. go RunNewClient(server, conn)
  205. }
  206. func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) {
  207. // check DLINEs
  208. isBanned, info := server.dlines.CheckIP(ipaddr)
  209. if isBanned {
  210. server.logger.Info("localconnect-ip", fmt.Sprintf("Client from %v rejected by d-line", ipaddr))
  211. return true, info.BanMessage("You are banned from this server (%s)")
  212. }
  213. // check connection limits
  214. err := server.connectionLimiter.AddClient(ipaddr, false)
  215. if err != nil {
  216. // too many connections from one client, tell the client and close the connection
  217. server.logger.Info("localconnect-ip", fmt.Sprintf("Client from %v rejected for connection limit", ipaddr))
  218. return true, "Too many clients from your network"
  219. }
  220. // check connection throttle
  221. err = server.connectionThrottler.AddClient(ipaddr)
  222. if err != nil {
  223. // too many connections too quickly from client, tell them and close the connection
  224. duration := server.connectionThrottler.BanDuration()
  225. if duration == 0 {
  226. return false, ""
  227. }
  228. server.dlines.AddIP(ipaddr, duration, server.connectionThrottler.BanMessage(), "Exceeded automated connection throttle", "auto.connection.throttler")
  229. // they're DLINE'd for 15 minutes or whatever, so we can reset the connection throttle now,
  230. // and once their temporary DLINE is finished they can fill up the throttler again
  231. server.connectionThrottler.ResetFor(ipaddr)
  232. // this might not show up properly on some clients, but our objective here is just to close it out before it has a load impact on us
  233. server.logger.Info(
  234. "localconnect-ip",
  235. fmt.Sprintf("Client from %v exceeded connection throttle, d-lining for %v", ipaddr, duration))
  236. return true, server.connectionThrottler.BanMessage()
  237. }
  238. return false, ""
  239. }
  240. func (server *Server) checkTorLimits() (banned bool, message string) {
  241. switch server.torLimiter.AddClient() {
  242. case connection_limits.ErrLimitExceeded:
  243. return true, "Too many clients from the Tor network"
  244. case connection_limits.ErrThrottleExceeded:
  245. return true, "Exceeded connection throttle for the Tor network"
  246. default:
  247. return false, ""
  248. }
  249. }
  250. //
  251. // IRC protocol listeners
  252. //
  253. // createListener starts a given listener.
  254. func (server *Server) createListener(addr string, tlsConfig *tls.Config, isTor bool, bindMode os.FileMode) (*ListenerWrapper, error) {
  255. // make listener
  256. var listener net.Listener
  257. var err error
  258. addr = strings.TrimPrefix(addr, "unix:")
  259. if strings.HasPrefix(addr, "/") {
  260. // https://stackoverflow.com/a/34881585
  261. os.Remove(addr)
  262. listener, err = net.Listen("unix", addr)
  263. if err == nil && bindMode != 0 {
  264. os.Chmod(addr, bindMode)
  265. }
  266. } else {
  267. listener, err = net.Listen("tcp", addr)
  268. }
  269. if err != nil {
  270. return nil, err
  271. }
  272. // throw our details to the server so we can be modified/killed later
  273. wrapper := ListenerWrapper{
  274. listener: listener,
  275. tlsConfig: tlsConfig,
  276. isTor: isTor,
  277. shouldStop: false,
  278. }
  279. var shouldStop bool
  280. // setup accept goroutine
  281. go func() {
  282. for {
  283. conn, err := listener.Accept()
  284. // synchronously access config data:
  285. wrapper.configMutex.Lock()
  286. shouldStop = wrapper.shouldStop
  287. tlsConfig = wrapper.tlsConfig
  288. isTor = wrapper.isTor
  289. wrapper.configMutex.Unlock()
  290. if err == nil {
  291. if tlsConfig != nil {
  292. conn = tls.Server(conn, tlsConfig)
  293. }
  294. newConn := clientConn{
  295. Conn: conn,
  296. IsTLS: tlsConfig != nil,
  297. IsTor: isTor,
  298. }
  299. // hand off the connection
  300. go server.acceptClient(newConn)
  301. }
  302. if shouldStop {
  303. listener.Close()
  304. return
  305. }
  306. }
  307. }()
  308. return &wrapper, nil
  309. }
  310. //
  311. // server functionality
  312. //
  313. func (server *Server) tryRegister(c *Client, session *Session) {
  314. resumed := false
  315. // try to complete registration, either via RESUME token or normally
  316. if c.resumeDetails != nil {
  317. if !c.tryResume() {
  318. return
  319. }
  320. resumed = true
  321. } else {
  322. if c.preregNick == "" || !c.HasUsername() || session.capState == caps.NegotiatingState {
  323. return
  324. }
  325. // client MUST send PASS if necessary, or authenticate with SASL if necessary,
  326. // before completing the other registration commands
  327. config := server.Config()
  328. if !c.isAuthorized(config) {
  329. c.Quit(c.t("Bad password"), nil)
  330. c.destroy(false, nil)
  331. return
  332. }
  333. rb := NewResponseBuffer(session)
  334. nickAssigned := performNickChange(server, c, c, session, c.preregNick, rb)
  335. rb.Send(true)
  336. if !nickAssigned {
  337. c.preregNick = ""
  338. return
  339. }
  340. // check KLINEs
  341. isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...)
  342. if isBanned {
  343. c.Quit(info.BanMessage(c.t("You are banned from this server (%s)")), nil)
  344. c.destroy(false, nil)
  345. return
  346. }
  347. }
  348. if session.client != c {
  349. // reattached, bail out.
  350. // we'll play the reg burst later, on the new goroutine associated with
  351. // (thisSession, otherClient). This is to avoid having to transfer state
  352. // like nickname, hostname, etc. to show the correct values in the reg burst.
  353. return
  354. }
  355. // registration has succeeded:
  356. c.SetRegistered()
  357. // count new user in statistics
  358. server.stats.ChangeTotal(1)
  359. server.playRegistrationBurst(session)
  360. if resumed {
  361. c.tryResumeChannels()
  362. } else {
  363. server.monitorManager.AlertAbout(c, true)
  364. }
  365. }
  366. func (server *Server) playRegistrationBurst(session *Session) {
  367. c := session.client
  368. // continue registration
  369. d := c.Details()
  370. server.logger.Info("localconnect", fmt.Sprintf("Client connected [%s] [u:%s] [r:%s]", d.nick, d.username, d.realname))
  371. server.snomasks.Send(sno.LocalConnects, fmt.Sprintf("Client connected [%s] [u:%s] [h:%s] [ip:%s] [r:%s]", d.nick, d.username, c.RawHostname(), c.IPString(), d.realname))
  372. // send welcome text
  373. //NOTE(dan): we specifically use the NICK here instead of the nickmask
  374. // see http://modern.ircdocs.horse/#rplwelcome-001 for details on why we avoid using the nickmask
  375. session.Send(nil, server.name, RPL_WELCOME, d.nick, fmt.Sprintf(c.t("Welcome to the Internet Relay Network %s"), d.nick))
  376. session.Send(nil, server.name, RPL_YOURHOST, d.nick, fmt.Sprintf(c.t("Your host is %[1]s, running version %[2]s"), server.name, Ver))
  377. session.Send(nil, server.name, RPL_CREATED, d.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123)))
  378. //TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
  379. session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
  380. rb := NewResponseBuffer(session)
  381. c.RplISupport(rb)
  382. server.MOTD(c, rb)
  383. rb.Send(true)
  384. modestring := c.ModeString()
  385. if modestring != "+" {
  386. session.Send(nil, d.nickMask, RPL_UMODEIS, d.nick, modestring)
  387. }
  388. if server.logger.IsLoggingRawIO() {
  389. session.Send(nil, c.server.name, "NOTICE", d.nick, c.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
  390. }
  391. }
  392. // t returns the translated version of the given string, based on the languages configured by the client.
  393. func (client *Client) t(originalString string) string {
  394. // TODO(slingamn) investigate a fast path for this, using an atomic load to see if translation is disabled
  395. languages := client.Languages()
  396. return client.server.Languages().Translate(languages, originalString)
  397. }
  398. // MOTD serves the Message of the Day.
  399. func (server *Server) MOTD(client *Client, rb *ResponseBuffer) {
  400. motdLines := server.Config().Server.motdLines
  401. if len(motdLines) < 1 {
  402. rb.Add(nil, server.name, ERR_NOMOTD, client.nick, client.t("MOTD File is missing"))
  403. return
  404. }
  405. rb.Add(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf(client.t("- %s Message of the day - "), server.name))
  406. for _, line := range motdLines {
  407. rb.Add(nil, server.name, RPL_MOTD, client.nick, line)
  408. }
  409. rb.Add(nil, server.name, RPL_ENDOFMOTD, client.nick, client.t("End of MOTD command"))
  410. }
  411. // WhoisChannelsNames returns the common channel names between two users.
  412. func (client *Client) WhoisChannelsNames(target *Client, multiPrefix bool) []string {
  413. var chstrs []string
  414. for _, channel := range target.Channels() {
  415. // channel is secret and the target can't see it
  416. if !client.HasMode(modes.Operator) {
  417. if (target.HasMode(modes.Invisible) || channel.flags.HasMode(modes.Secret)) && !channel.hasClient(client) {
  418. continue
  419. }
  420. }
  421. chstrs = append(chstrs, channel.ClientPrefixes(target, multiPrefix)+channel.name)
  422. }
  423. return chstrs
  424. }
  425. func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
  426. cnick := client.Nick()
  427. targetInfo := target.Details()
  428. rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nick, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname)
  429. tnick := targetInfo.nick
  430. whoischannels := client.WhoisChannelsNames(target, rb.session.capabilities.Has(caps.MultiPrefix))
  431. if whoischannels != nil {
  432. rb.Add(nil, client.server.name, RPL_WHOISCHANNELS, cnick, tnick, strings.Join(whoischannels, " "))
  433. }
  434. tOper := target.Oper()
  435. if tOper != nil {
  436. rb.Add(nil, client.server.name, RPL_WHOISOPERATOR, cnick, tnick, tOper.WhoisLine)
  437. }
  438. if client.HasMode(modes.Operator) || client == target {
  439. rb.Add(nil, client.server.name, RPL_WHOISACTUALLY, cnick, tnick, fmt.Sprintf("%s@%s", targetInfo.username, target.RawHostname()), target.IPString(), client.t("Actual user@host, Actual IP"))
  440. }
  441. if target.HasMode(modes.TLS) {
  442. rb.Add(nil, client.server.name, RPL_WHOISSECURE, cnick, tnick, client.t("is using a secure connection"))
  443. }
  444. if targetInfo.accountName != "*" {
  445. rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, cnick, tnick, targetInfo.accountName, client.t("is logged in as"))
  446. }
  447. if target.HasMode(modes.Bot) {
  448. rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name)))
  449. }
  450. tLanguages := target.Languages()
  451. if 0 < len(tLanguages) {
  452. params := []string{cnick, tnick}
  453. params = append(params, client.server.Languages().Codes(tLanguages)...)
  454. params = append(params, client.t("can speak these languages"))
  455. rb.Add(nil, client.server.name, RPL_WHOISLANGUAGE, params...)
  456. }
  457. if target.certfp != "" && (client.HasMode(modes.Operator) || client == target) {
  458. rb.Add(nil, client.server.name, RPL_WHOISCERTFP, cnick, tnick, fmt.Sprintf(client.t("has client certificate fingerprint %s"), target.certfp))
  459. }
  460. rb.Add(nil, client.server.name, RPL_WHOISIDLE, cnick, tnick, strconv.FormatUint(target.IdleSeconds(), 10), strconv.FormatInt(target.SignonTime(), 10), client.t("seconds idle, signon time"))
  461. }
  462. // rplWhoReply returns the WHO reply between one user and another channel/user.
  463. // <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
  464. // :<hopcount> <real name>
  465. func (target *Client) rplWhoReply(channel *Channel, client *Client, rb *ResponseBuffer) {
  466. channelName := "*"
  467. flags := ""
  468. if client.Away() {
  469. flags = "G"
  470. } else {
  471. flags = "H"
  472. }
  473. if client.HasMode(modes.Operator) {
  474. flags += "*"
  475. }
  476. if channel != nil {
  477. // TODO is this right?
  478. flags += channel.ClientPrefixes(client, rb.session.capabilities.Has(caps.MultiPrefix))
  479. channelName = channel.name
  480. }
  481. // hardcode a hopcount of 0 for now
  482. rb.Add(nil, target.server.name, RPL_WHOREPLY, target.nick, channelName, client.Username(), client.Hostname(), client.server.name, client.Nick(), flags, "0 "+client.Realname())
  483. }
  484. // rehash reloads the config and applies the changes from the config file.
  485. func (server *Server) rehash() error {
  486. server.logger.Debug("server", "Starting rehash")
  487. // only let one REHASH go on at a time
  488. server.rehashMutex.Lock()
  489. defer server.rehashMutex.Unlock()
  490. server.logger.Debug("server", "Got rehash lock")
  491. config, err := LoadConfig(server.configFilename)
  492. if err != nil {
  493. return fmt.Errorf("Error loading config file config: %s", err.Error())
  494. }
  495. err = server.applyConfig(config, false)
  496. if err != nil {
  497. return fmt.Errorf("Error applying config changes: %s", err.Error())
  498. }
  499. return nil
  500. }
  501. func (server *Server) applyConfig(config *Config, initial bool) (err error) {
  502. if initial {
  503. server.ctime = time.Now()
  504. server.configFilename = config.Filename
  505. server.name = config.Server.Name
  506. server.nameCasefolded = config.Server.nameCasefolded
  507. } else {
  508. // enforce configs that can't be changed after launch:
  509. currentLimits := server.Limits()
  510. if currentLimits.LineLen.Rest != config.Limits.LineLen.Rest {
  511. return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
  512. } else if server.name != config.Server.Name {
  513. return fmt.Errorf("Server name cannot be changed after launching the server, rehash aborted")
  514. } else if server.Config().Datastore.Path != config.Datastore.Path {
  515. return fmt.Errorf("Datastore path cannot be changed after launching the server, rehash aborted")
  516. }
  517. }
  518. // sanity checks complete, start modifying server state
  519. server.logger.Info("server", "Using config file", server.configFilename)
  520. oldConfig := server.Config()
  521. // first, reload config sections for functionality implemented in subpackages:
  522. err = server.connectionLimiter.ApplyConfig(config.Server.ConnectionLimiter)
  523. if err != nil {
  524. return err
  525. }
  526. err = server.connectionThrottler.ApplyConfig(config.Server.ConnectionThrottler)
  527. if err != nil {
  528. return err
  529. }
  530. tlConf := &config.Server.TorListeners
  531. server.torLimiter.Configure(tlConf.MaxConnections, tlConf.ThrottleDuration, tlConf.MaxConnectionsPerDuration)
  532. // reload logging config
  533. wasLoggingRawIO := !initial && server.logger.IsLoggingRawIO()
  534. err = server.logger.ApplyConfig(config.Logging)
  535. if err != nil {
  536. return err
  537. }
  538. nowLoggingRawIO := server.logger.IsLoggingRawIO()
  539. // notify existing clients if raw i/o logging was enabled by a rehash
  540. sendRawOutputNotice := !wasLoggingRawIO && nowLoggingRawIO
  541. // setup new and removed caps
  542. addedCaps := caps.NewSet()
  543. removedCaps := caps.NewSet()
  544. updatedCaps := caps.NewSet()
  545. // Translations
  546. server.logger.Debug("server", "Regenerating HELP indexes for new languages")
  547. server.helpIndexManager.GenerateIndices(config.languageManager)
  548. currentLanguageValue, _ := CapValues.Get(caps.Languages)
  549. newLanguageValue := config.languageManager.CapValue()
  550. if currentLanguageValue != newLanguageValue {
  551. updatedCaps.Add(caps.Languages)
  552. CapValues.Set(caps.Languages, newLanguageValue)
  553. }
  554. // SASL
  555. authPreviouslyEnabled := oldConfig != nil && oldConfig.Accounts.AuthenticationEnabled
  556. if config.Accounts.AuthenticationEnabled && (oldConfig == nil || !authPreviouslyEnabled) {
  557. // enabling SASL
  558. SupportedCapabilities.Enable(caps.SASL)
  559. CapValues.Set(caps.SASL, "PLAIN,EXTERNAL")
  560. addedCaps.Add(caps.SASL)
  561. } else if !config.Accounts.AuthenticationEnabled && (oldConfig == nil || authPreviouslyEnabled) {
  562. // disabling SASL
  563. SupportedCapabilities.Disable(caps.SASL)
  564. removedCaps.Add(caps.SASL)
  565. }
  566. nickReservationPreviouslyDisabled := oldConfig != nil && !oldConfig.Accounts.NickReservation.Enabled
  567. nickReservationNowEnabled := config.Accounts.NickReservation.Enabled
  568. if nickReservationPreviouslyDisabled && nickReservationNowEnabled {
  569. server.accounts.buildNickToAccountIndex()
  570. }
  571. hsPreviouslyDisabled := oldConfig != nil && !oldConfig.Accounts.VHosts.Enabled
  572. hsNowEnabled := config.Accounts.VHosts.Enabled
  573. if hsPreviouslyDisabled && hsNowEnabled {
  574. server.accounts.initVHostRequestQueue()
  575. }
  576. chanRegPreviouslyDisabled := oldConfig != nil && !oldConfig.Channels.Registration.Enabled
  577. chanRegNowEnabled := config.Channels.Registration.Enabled
  578. if chanRegPreviouslyDisabled && chanRegNowEnabled {
  579. server.channels.loadRegisteredChannels()
  580. }
  581. // MaxLine
  582. if config.Limits.LineLen.Rest != 512 {
  583. SupportedCapabilities.Enable(caps.MaxLine)
  584. value := fmt.Sprintf("%d", config.Limits.LineLen.Rest)
  585. CapValues.Set(caps.MaxLine, value)
  586. } else {
  587. SupportedCapabilities.Disable(caps.MaxLine)
  588. }
  589. // STS
  590. stsPreviouslyEnabled := oldConfig != nil && oldConfig.Server.STS.Enabled
  591. stsValue := config.Server.STS.Value()
  592. stsDisabledByRehash := false
  593. stsCurrentCapValue, _ := CapValues.Get(caps.STS)
  594. server.logger.Debug("server", "STS Vals", stsCurrentCapValue, stsValue, fmt.Sprintf("server[%v] config[%v]", stsPreviouslyEnabled, config.Server.STS.Enabled))
  595. if config.Server.STS.Enabled {
  596. // enabling STS
  597. SupportedCapabilities.Enable(caps.STS)
  598. if !stsPreviouslyEnabled {
  599. addedCaps.Add(caps.STS)
  600. CapValues.Set(caps.STS, stsValue)
  601. } else if stsValue != stsCurrentCapValue {
  602. // STS policy updated
  603. CapValues.Set(caps.STS, stsValue)
  604. updatedCaps.Add(caps.STS)
  605. }
  606. } else {
  607. // disabling STS
  608. SupportedCapabilities.Disable(caps.STS)
  609. if stsPreviouslyEnabled {
  610. removedCaps.Add(caps.STS)
  611. stsDisabledByRehash = true
  612. }
  613. }
  614. // resize history buffers as needed
  615. if oldConfig != nil {
  616. if oldConfig.History.ChannelLength != config.History.ChannelLength {
  617. for _, channel := range server.channels.Channels() {
  618. channel.history.Resize(config.History.ChannelLength)
  619. }
  620. }
  621. if oldConfig.History.ClientLength != config.History.ClientLength {
  622. for _, client := range server.clients.AllClients() {
  623. client.history.Resize(config.History.ClientLength)
  624. }
  625. }
  626. }
  627. // burst new and removed caps
  628. var capBurstSessions []*Session
  629. added := make(map[caps.Version]string)
  630. var removed string
  631. // updated caps get DEL'd and then NEW'd
  632. // so, we can just add updated ones to both removed and added lists here and they'll be correctly handled
  633. server.logger.Debug("server", "Updated Caps", updatedCaps.String(caps.Cap301, CapValues))
  634. addedCaps.Union(updatedCaps)
  635. removedCaps.Union(updatedCaps)
  636. if !addedCaps.Empty() || !removedCaps.Empty() {
  637. capBurstSessions = server.clients.AllWithCapsNotify()
  638. added[caps.Cap301] = addedCaps.String(caps.Cap301, CapValues)
  639. added[caps.Cap302] = addedCaps.String(caps.Cap302, CapValues)
  640. // removed never has values, so we leave it as Cap301
  641. removed = removedCaps.String(caps.Cap301, CapValues)
  642. }
  643. for _, sSession := range capBurstSessions {
  644. if stsDisabledByRehash {
  645. // remove STS policy
  646. //TODO(dan): this is an ugly hack. we can write this better.
  647. stsPolicy := "sts=duration=0"
  648. if !addedCaps.Empty() {
  649. added[caps.Cap302] = added[caps.Cap302] + " " + stsPolicy
  650. } else {
  651. addedCaps.Enable(caps.STS)
  652. added[caps.Cap302] = stsPolicy
  653. }
  654. }
  655. // DEL caps and then send NEW ones so that updated caps get removed/added correctly
  656. if !removedCaps.Empty() {
  657. sSession.Send(nil, server.name, "CAP", sSession.client.Nick(), "DEL", removed)
  658. }
  659. if !addedCaps.Empty() {
  660. sSession.Send(nil, server.name, "CAP", sSession.client.Nick(), "NEW", added[sSession.capVersion])
  661. }
  662. }
  663. // save a pointer to the new config
  664. server.SetConfig(config)
  665. server.logger.Info("server", "Using datastore", config.Datastore.Path)
  666. if initial {
  667. if err := server.loadDatastore(config); err != nil {
  668. return err
  669. }
  670. }
  671. server.setupPprofListener(config)
  672. // set RPL_ISUPPORT
  673. var newISupportReplies [][]string
  674. if oldConfig != nil {
  675. newISupportReplies = oldConfig.Server.isupport.GetDifference(&config.Server.isupport)
  676. }
  677. // we are now open for business
  678. err = server.setupListeners(config)
  679. if !initial {
  680. // push new info to all of our clients
  681. for _, sClient := range server.clients.AllClients() {
  682. for _, tokenline := range newISupportReplies {
  683. sClient.Send(nil, server.name, RPL_ISUPPORT, append([]string{sClient.nick}, tokenline...)...)
  684. }
  685. if sendRawOutputNotice {
  686. sClient.Notice(sClient.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
  687. }
  688. if !oldConfig.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.Enabled {
  689. sClient.nickTimer.Initialize(sClient)
  690. sClient.nickTimer.Touch(nil)
  691. } else if oldConfig.Accounts.NickReservation.Enabled && !config.Accounts.NickReservation.Enabled {
  692. sClient.nickTimer.Stop()
  693. }
  694. }
  695. }
  696. return err
  697. }
  698. func (server *Server) setupPprofListener(config *Config) {
  699. pprofListener := ""
  700. if config.Debug.PprofListener != nil {
  701. pprofListener = *config.Debug.PprofListener
  702. }
  703. if server.pprofServer != nil {
  704. if pprofListener == "" || (pprofListener != server.pprofServer.Addr) {
  705. server.logger.Info("server", "Stopping pprof listener", server.pprofServer.Addr)
  706. server.pprofServer.Close()
  707. server.pprofServer = nil
  708. }
  709. }
  710. if pprofListener != "" && server.pprofServer == nil {
  711. ps := http.Server{
  712. Addr: pprofListener,
  713. }
  714. go func() {
  715. if err := ps.ListenAndServe(); err != nil {
  716. server.logger.Error("server", "pprof listener failed", err.Error())
  717. }
  718. }()
  719. server.pprofServer = &ps
  720. server.logger.Info("server", "Started pprof listener", server.pprofServer.Addr)
  721. }
  722. }
  723. func (config *Config) loadMOTD() (err error) {
  724. if config.Server.MOTD != "" {
  725. file, err := os.Open(config.Server.MOTD)
  726. if err == nil {
  727. defer file.Close()
  728. reader := bufio.NewReader(file)
  729. for {
  730. line, err := reader.ReadString('\n')
  731. if err != nil {
  732. break
  733. }
  734. line = strings.TrimRight(line, "\r\n")
  735. if config.Server.MOTDFormatting {
  736. line = ircfmt.Unescape(line)
  737. }
  738. // "- " is the required prefix for MOTD, we just add it here to make
  739. // bursting it out to clients easier
  740. line = fmt.Sprintf("- %s", line)
  741. config.Server.motdLines = append(config.Server.motdLines, line)
  742. }
  743. }
  744. }
  745. return
  746. }
  747. func (server *Server) loadDatastore(config *Config) error {
  748. // open the datastore and load server state for which it (rather than config)
  749. // is the source of truth
  750. _, err := os.Stat(config.Datastore.Path)
  751. if os.IsNotExist(err) {
  752. server.logger.Warning("server", "database does not exist, creating it", config.Datastore.Path)
  753. err = initializeDB(config.Datastore.Path)
  754. if err != nil {
  755. return err
  756. }
  757. }
  758. db, err := OpenDatabase(config)
  759. if err == nil {
  760. server.store = db
  761. } else {
  762. return fmt.Errorf("Failed to open datastore: %s", err.Error())
  763. }
  764. // load *lines (from the datastores)
  765. server.logger.Debug("server", "Loading D/Klines")
  766. server.loadDLines()
  767. server.loadKLines()
  768. server.channelRegistry.Initialize(server)
  769. server.channels.Initialize(server)
  770. server.accounts.Initialize(server)
  771. return nil
  772. }
  773. func (server *Server) setupListeners(config *Config) (err error) {
  774. logListener := func(addr string, tlsconfig *tls.Config, isTor bool) {
  775. server.logger.Info("listeners",
  776. fmt.Sprintf("now listening on %s, tls=%t, tor=%t.", addr, (tlsconfig != nil), isTor),
  777. )
  778. }
  779. tlsListeners, err := config.TLSListeners()
  780. if err != nil {
  781. server.logger.Error("server", "failed to reload TLS certificates, aborting rehash", err.Error())
  782. return
  783. }
  784. isTorListener := func(listener string) bool {
  785. for _, torListener := range config.Server.TorListeners.Listeners {
  786. if listener == torListener {
  787. return true
  788. }
  789. }
  790. return false
  791. }
  792. // update or destroy all existing listeners
  793. for addr := range server.listeners {
  794. currentListener := server.listeners[addr]
  795. var stillConfigured bool
  796. for _, newaddr := range config.Server.Listen {
  797. if newaddr == addr {
  798. stillConfigured = true
  799. break
  800. }
  801. }
  802. // pass new config information to the listener, to be picked up after
  803. // its next Accept(). this is like sending over a buffered channel of
  804. // size 1, but where sending a second item overwrites the buffered item
  805. // instead of blocking.
  806. tlsConfig := tlsListeners[addr]
  807. isTor := isTorListener(addr)
  808. currentListener.configMutex.Lock()
  809. currentListener.shouldStop = !stillConfigured
  810. currentListener.tlsConfig = tlsConfig
  811. currentListener.isTor = isTor
  812. currentListener.configMutex.Unlock()
  813. if stillConfigured {
  814. logListener(addr, tlsConfig, isTor)
  815. } else {
  816. // tell the listener it should stop by interrupting its Accept() call:
  817. currentListener.listener.Close()
  818. delete(server.listeners, addr)
  819. server.logger.Info("listeners", fmt.Sprintf("stopped listening on %s.", addr))
  820. }
  821. }
  822. // create new listeners that were not previously configured
  823. for _, newaddr := range config.Server.Listen {
  824. _, exists := server.listeners[newaddr]
  825. if !exists {
  826. // make new listener
  827. isTor := isTorListener(newaddr)
  828. tlsConfig := tlsListeners[newaddr]
  829. listener, listenerErr := server.createListener(newaddr, tlsConfig, isTor, config.Server.UnixBindMode)
  830. if listenerErr != nil {
  831. server.logger.Error("server", "couldn't listen on", newaddr, listenerErr.Error())
  832. err = listenerErr
  833. continue
  834. }
  835. server.listeners[newaddr] = listener
  836. logListener(newaddr, tlsConfig, isTor)
  837. }
  838. }
  839. if len(tlsListeners) == 0 {
  840. server.logger.Warning("server", "You are not exposing an SSL/TLS listening port. You should expose at least one port (typically 6697) to accept TLS connections")
  841. }
  842. var usesStandardTLSPort bool
  843. for addr := range tlsListeners {
  844. if strings.HasSuffix(addr, ":6697") {
  845. usesStandardTLSPort = true
  846. break
  847. }
  848. }
  849. if 0 < len(tlsListeners) && !usesStandardTLSPort {
  850. server.logger.Warning("server", "Port 6697 is the standard TLS port for IRC. You should (also) expose port 6697 as a TLS port to ensure clients can connect securely")
  851. }
  852. return
  853. }
  854. // elistMatcher takes and matches ELIST conditions
  855. type elistMatcher struct {
  856. MinClientsActive bool
  857. MinClients int
  858. MaxClientsActive bool
  859. MaxClients int
  860. }
  861. // Matches checks whether the given channel matches our matches.
  862. func (matcher *elistMatcher) Matches(channel *Channel) bool {
  863. if matcher.MinClientsActive {
  864. if len(channel.Members()) < matcher.MinClients {
  865. return false
  866. }
  867. }
  868. if matcher.MaxClientsActive {
  869. if len(channel.Members()) < len(channel.members) {
  870. return false
  871. }
  872. }
  873. return true
  874. }
  875. // RplList returns the RPL_LIST numeric for the given channel.
  876. func (target *Client) RplList(channel *Channel, rb *ResponseBuffer) {
  877. // get the correct number of channel members
  878. var memberCount int
  879. if target.HasMode(modes.Operator) || channel.hasClient(target) {
  880. memberCount = len(channel.Members())
  881. } else {
  882. for _, member := range channel.Members() {
  883. if !member.HasMode(modes.Invisible) {
  884. memberCount++
  885. }
  886. }
  887. }
  888. rb.Add(nil, target.server.name, RPL_LIST, target.nick, channel.name, strconv.Itoa(memberCount), channel.topic)
  889. }
  890. var (
  891. infoString1 = strings.Split(` ▄▄▄ ▄▄▄· ▄▄ • ▐ ▄
  892. ▪ ▀▄ █·▐█ ▀█ ▐█ ▀ ▪▪ •█▌▐█▪
  893. ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ▄█ ▀█▄ ▄█▀▄▪▐█▐▐▌ ▄█▀▄
  894. ▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▄▪▐█▐█▌ ▐▌██▐█▌▐█▌.▐▌
  895. ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪
  896. https://oragono.io/
  897. https://github.com/oragono/oragono
  898. https://crowdin.com/project/oragono
  899. `, "\n")
  900. infoString2 = strings.Split(` Daniel Oakley, DanielOaks, <daniel@danieloaks.net>
  901. Shivaram Lingamneni, slingamn, <slingamn@cs.stanford.edu>
  902. `, "\n")
  903. infoString3 = strings.Split(` 3onyc
  904. Edmund Huber
  905. Euan Kemp (euank)
  906. Jeremy Latt
  907. Martin Lindhe (martinlindhe)
  908. Roberto Besser (besser)
  909. Robin Burchell (rburchell)
  910. Sean Enck (enckse)
  911. soul9
  912. Vegax
  913. `, "\n")
  914. )