Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

server.go 35KB

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