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.

server.go 49KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2014-2015 Edmund Huber
  3. // Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
  4. // released under the MIT license
  5. package irc
  6. import (
  7. "bufio"
  8. "crypto/tls"
  9. "encoding/base64"
  10. "errors"
  11. "fmt"
  12. "log"
  13. "net"
  14. "net/http"
  15. "os"
  16. "os/signal"
  17. "strconv"
  18. "strings"
  19. "sync"
  20. "syscall"
  21. "time"
  22. "github.com/DanielOaks/girc-go/ircmsg"
  23. "github.com/tidwall/buntdb"
  24. )
  25. var (
  26. // cached because this may be used lots
  27. tooManyClientsMsg = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your network")
  28. tooManyClientsBytes, _ = tooManyClientsMsg.Line()
  29. bannedFromServerMsg = ircmsg.MakeMessage(nil, "", "ERROR", "You are banned from this server (%s)")
  30. bannedFromServerBytes, _ = bannedFromServerMsg.Line()
  31. errDbOutOfDate = errors.New("Database schema is old.")
  32. )
  33. // Limits holds the maximum limits for various things such as topic lengths
  34. type Limits struct {
  35. AwayLen int
  36. ChannelLen int
  37. KickLen int
  38. MonitorEntries int
  39. NickLen int
  40. TopicLen int
  41. ChanListModes int
  42. }
  43. // ListenerInterface represents an interface for a listener.
  44. type ListenerInterface struct {
  45. Listener net.Listener
  46. Events chan ListenerEvent
  47. }
  48. const (
  49. // DestroyListener instructs the listener to destroy itself.
  50. DestroyListener ListenerEventType = iota
  51. // UpdateListener instructs the listener to update itself (grab new certs, etc).
  52. UpdateListener = iota
  53. )
  54. // ListenerEventType is the type of event this is.
  55. type ListenerEventType int
  56. // ListenerEvent is an event that's passed to the listener.
  57. type ListenerEvent struct {
  58. Type ListenerEventType
  59. NewConfig *tls.Config
  60. }
  61. // Server is the main Oragono server.
  62. type Server struct {
  63. accountRegistration *AccountRegistration
  64. accounts map[string]*ClientAccount
  65. authenticationEnabled bool
  66. channels ChannelNameMap
  67. checkIdent bool
  68. clients *ClientLookupSet
  69. commands chan Command
  70. configFilename string
  71. connectionThrottle *ConnectionThrottle
  72. connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
  73. connectionLimits *ConnectionLimits
  74. connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
  75. ctime time.Time
  76. currentOpers map[*Client]bool
  77. dlines *DLineManager
  78. idle chan *Client
  79. isupport *ISupportList
  80. klines *KLineManager
  81. limits Limits
  82. listenerEventActMutex sync.Mutex
  83. listeners map[string]ListenerInterface
  84. listenerUpdateMutex sync.Mutex
  85. monitoring map[string][]Client
  86. motdLines []string
  87. name string
  88. nameCasefolded string
  89. networkName string
  90. newConns chan clientConn
  91. operators map[string]Oper
  92. operclasses map[string]OperClass
  93. password []byte
  94. passwords *PasswordManager
  95. rehashMutex sync.Mutex
  96. rehashSignal chan os.Signal
  97. restAPI *RestAPIConfig
  98. signals chan os.Signal
  99. store *buntdb.DB
  100. whoWas *WhoWasList
  101. }
  102. var (
  103. // ServerExitSignals are the signals the server will exit on.
  104. ServerExitSignals = []os.Signal{
  105. syscall.SIGINT,
  106. syscall.SIGTERM,
  107. syscall.SIGQUIT,
  108. }
  109. )
  110. type clientConn struct {
  111. Conn net.Conn
  112. IsTLS bool
  113. }
  114. // NewServer returns a new Oragono server.
  115. func NewServer(configFilename string, config *Config) *Server {
  116. casefoldedName, err := Casefold(config.Server.Name)
  117. if err != nil {
  118. log.Println(fmt.Sprintf("Server name isn't valid: [%s]", config.Server.Name), err.Error())
  119. return nil
  120. }
  121. // startup check that we have HELP entries for every command
  122. for name := range Commands {
  123. _, exists := Help[strings.ToLower(name)]
  124. if !exists {
  125. log.Fatal("Help entry does not exist for ", name)
  126. }
  127. }
  128. if config.AuthenticationEnabled {
  129. SupportedCapabilities[SASL] = true
  130. }
  131. operClasses, err := config.OperatorClasses()
  132. if err != nil {
  133. log.Fatal("Error loading oper classes:", err.Error())
  134. }
  135. opers, err := config.Operators(operClasses)
  136. if err != nil {
  137. log.Fatal("Error loading operators:", err.Error())
  138. }
  139. connectionLimits, err := NewConnectionLimits(config.Server.ConnectionLimits)
  140. if err != nil {
  141. log.Fatal("Error loading connection limits:", err.Error())
  142. }
  143. connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
  144. if err != nil {
  145. log.Fatal("Error loading connection throttler:", err.Error())
  146. }
  147. server := &Server{
  148. accounts: make(map[string]*ClientAccount),
  149. authenticationEnabled: config.AuthenticationEnabled,
  150. channels: make(ChannelNameMap),
  151. clients: NewClientLookupSet(),
  152. commands: make(chan Command),
  153. configFilename: configFilename,
  154. connectionLimits: connectionLimits,
  155. connectionThrottle: connectionThrottle,
  156. ctime: time.Now(),
  157. currentOpers: make(map[*Client]bool),
  158. idle: make(chan *Client),
  159. limits: Limits{
  160. AwayLen: int(config.Limits.AwayLen),
  161. ChannelLen: int(config.Limits.ChannelLen),
  162. KickLen: int(config.Limits.KickLen),
  163. MonitorEntries: int(config.Limits.MonitorEntries),
  164. NickLen: int(config.Limits.NickLen),
  165. TopicLen: int(config.Limits.TopicLen),
  166. ChanListModes: int(config.Limits.ChanListModes),
  167. },
  168. listeners: make(map[string]ListenerInterface),
  169. monitoring: make(map[string][]Client),
  170. name: config.Server.Name,
  171. nameCasefolded: casefoldedName,
  172. networkName: config.Network.Name,
  173. newConns: make(chan clientConn),
  174. operclasses: *operClasses,
  175. operators: opers,
  176. signals: make(chan os.Signal, len(ServerExitSignals)),
  177. rehashSignal: make(chan os.Signal, 1),
  178. restAPI: &config.Server.RestAPI,
  179. whoWas: NewWhoWasList(config.Limits.WhowasEntries),
  180. checkIdent: config.Server.CheckIdent,
  181. }
  182. // open data store
  183. db, err := buntdb.Open(config.Datastore.Path)
  184. if err != nil {
  185. log.Fatal(fmt.Sprintf("Failed to open datastore: %s", err.Error()))
  186. }
  187. server.store = db
  188. // check db version
  189. err = server.store.View(func(tx *buntdb.Tx) error {
  190. version, _ := tx.Get(keySchemaVersion)
  191. if version != latestDbSchema {
  192. log.Println(fmt.Sprintf("Database must be updated. Expected schema v%s, got v%s.", latestDbSchema, version))
  193. return errDbOutOfDate
  194. }
  195. return nil
  196. })
  197. if err != nil {
  198. // close the db
  199. db.Close()
  200. return nil
  201. }
  202. // load *lines
  203. server.loadDLines()
  204. server.loadKLines()
  205. // load password manager
  206. err = server.store.View(func(tx *buntdb.Tx) error {
  207. saltString, err := tx.Get(keySalt)
  208. if err != nil {
  209. return fmt.Errorf("Could not retrieve salt string: %s", err.Error())
  210. }
  211. salt, err := base64.StdEncoding.DecodeString(saltString)
  212. if err != nil {
  213. return err
  214. }
  215. pwm := NewPasswordManager(salt)
  216. server.passwords = &pwm
  217. return nil
  218. })
  219. if err != nil {
  220. log.Fatal(fmt.Sprintf("Could not load salt: %s", err.Error()))
  221. }
  222. if config.Server.MOTD != "" {
  223. file, err := os.Open(config.Server.MOTD)
  224. if err == nil {
  225. defer file.Close()
  226. reader := bufio.NewReader(file)
  227. for {
  228. line, err := reader.ReadString('\n')
  229. if err != nil {
  230. break
  231. }
  232. line = strings.TrimRight(line, "\r\n")
  233. // "- " is the required prefix for MOTD, we just add it here to make
  234. // bursting it out to clients easier
  235. line = fmt.Sprintf("- %s", line)
  236. server.motdLines = append(server.motdLines, line)
  237. }
  238. }
  239. }
  240. if config.Server.Password != "" {
  241. server.password = config.Server.PasswordBytes()
  242. }
  243. for _, addr := range config.Server.Listen {
  244. server.createListener(addr, config.TLSListeners())
  245. }
  246. if config.Server.Wslisten != "" {
  247. server.wslisten(config.Server.Wslisten, config.Server.TLSListeners)
  248. }
  249. // registration
  250. accountReg := NewAccountRegistration(config.Registration.Accounts)
  251. server.accountRegistration = &accountReg
  252. // Attempt to clean up when receiving these signals.
  253. signal.Notify(server.signals, ServerExitSignals...)
  254. signal.Notify(server.rehashSignal, syscall.SIGHUP)
  255. server.setISupport()
  256. // start API if enabled
  257. if server.restAPI.Enabled {
  258. Log.info.Printf("%s rest API started on %s .", server.name, server.restAPI.Listen)
  259. server.startRestAPI()
  260. }
  261. return server
  262. }
  263. // setISupport sets up our RPL_ISUPPORT reply.
  264. func (server *Server) setISupport() {
  265. maxTargetsString := strconv.Itoa(maxTargets)
  266. // add RPL_ISUPPORT tokens
  267. server.isupport = NewISupportList()
  268. server.isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
  269. server.isupport.Add("CASEMAPPING", casemappingName)
  270. server.isupport.Add("CHANMODES", strings.Join([]string{ChannelModes{BanMask, ExceptMask, InviteMask}.String(), "", ChannelModes{UserLimit, Key}.String(), ChannelModes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret}.String()}, ","))
  271. server.isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
  272. server.isupport.Add("CHANTYPES", "#")
  273. server.isupport.Add("EXCEPTS", "")
  274. server.isupport.Add("INVEX", "")
  275. server.isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
  276. server.isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(server.limits.ChanListModes)))
  277. server.isupport.Add("MAXTARGETS", maxTargetsString)
  278. server.isupport.Add("MODES", "")
  279. server.isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
  280. server.isupport.Add("NETWORK", server.networkName)
  281. server.isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
  282. server.isupport.Add("PREFIX", "(qaohv)~&@%+")
  283. server.isupport.Add("RPCHAN", "E")
  284. server.isupport.Add("RPUSER", "E")
  285. server.isupport.Add("STATUSMSG", "~&@%+")
  286. server.isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString))
  287. server.isupport.Add("TOPICLEN", strconv.Itoa(server.limits.TopicLen))
  288. // account registration
  289. if server.accountRegistration.Enabled {
  290. // 'none' isn't shown in the REGCALLBACKS vars
  291. var enabledCallbacks []string
  292. for _, name := range server.accountRegistration.EnabledCallbacks {
  293. if name != "*" {
  294. enabledCallbacks = append(enabledCallbacks, name)
  295. }
  296. }
  297. server.isupport.Add("REGCOMMANDS", "CREATE,VERIFY")
  298. server.isupport.Add("REGCALLBACKS", strings.Join(enabledCallbacks, ","))
  299. server.isupport.Add("REGCREDTYPES", "passphrase,certfp")
  300. }
  301. server.isupport.RegenerateCachedReply()
  302. }
  303. func loadChannelList(channel *Channel, list string, maskMode ChannelMode) {
  304. if list == "" {
  305. return
  306. }
  307. channel.lists[maskMode].AddAll(strings.Split(list, " "))
  308. }
  309. func (server *Server) Shutdown() {
  310. //TODO(dan): Make sure we disallow new nicks
  311. server.clients.ByNickMutex.RLock()
  312. for _, client := range server.clients.ByNick {
  313. client.Notice("Server is shutting down")
  314. }
  315. server.clients.ByNickMutex.RUnlock()
  316. if err := server.store.Close(); err != nil {
  317. Log.error.Println("Server.Shutdown store.Close: error:", err)
  318. }
  319. }
  320. // Run starts the server.
  321. func (server *Server) Run() {
  322. // defer closing db/store
  323. defer server.store.Close()
  324. done := false
  325. for !done {
  326. select {
  327. case <-server.signals:
  328. server.Shutdown()
  329. done = true
  330. case <-server.rehashSignal:
  331. // eventually we expect to use HUP to reload config
  332. err := server.rehash()
  333. if err != nil {
  334. Log.error.Println("Failed to rehash:", err.Error())
  335. }
  336. case conn := <-server.newConns:
  337. // check connection limits
  338. ipaddr := net.ParseIP(IPString(conn.Conn.RemoteAddr()))
  339. if ipaddr != nil {
  340. // check DLINEs
  341. isBanned, info := server.dlines.CheckIP(ipaddr)
  342. if isBanned {
  343. banMessage := fmt.Sprintf(bannedFromServerBytes, info.Reason)
  344. if info.Time != nil {
  345. banMessage += fmt.Sprintf(" [%s]", info.Time.Duration.String())
  346. }
  347. conn.Conn.Write([]byte(banMessage))
  348. conn.Conn.Close()
  349. continue
  350. }
  351. // check connection limits
  352. server.connectionLimitsMutex.Lock()
  353. err := server.connectionLimits.AddClient(ipaddr, false)
  354. server.connectionLimitsMutex.Unlock()
  355. if err != nil {
  356. // too many connections from one client, tell the client and close the connection
  357. // 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
  358. conn.Conn.Write([]byte(tooManyClientsBytes))
  359. conn.Conn.Close()
  360. continue
  361. }
  362. // check connection throttle
  363. server.connectionThrottleMutex.Lock()
  364. err = server.connectionThrottle.AddClient(ipaddr)
  365. server.connectionThrottleMutex.Unlock()
  366. if err != nil {
  367. // too many connections too quickly from client, tell them and close the connection
  368. length := &IPRestrictTime{
  369. Duration: server.connectionThrottle.BanDuration,
  370. Expires: time.Now().Add(server.connectionThrottle.BanDuration),
  371. }
  372. server.dlines.AddIP(ipaddr, length, server.connectionThrottle.BanMessage, "Exceeded automated connection throttle")
  373. // reset ban on connectionThrottle
  374. server.connectionThrottle.ResetFor(ipaddr)
  375. // 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
  376. conn.Conn.Write([]byte(server.connectionThrottle.BanMessageBytes))
  377. conn.Conn.Close()
  378. continue
  379. }
  380. go NewClient(server, conn.Conn, conn.IsTLS)
  381. continue
  382. }
  383. case client := <-server.idle:
  384. client.Idle()
  385. }
  386. }
  387. }
  388. //
  389. // IRC protocol listeners
  390. //
  391. // createListener starts the given listeners.
  392. func (server *Server) createListener(addr string, tlsMap map[string]*tls.Config) {
  393. config, listenTLS := tlsMap[addr]
  394. _, alreadyExists := server.listeners[addr]
  395. if alreadyExists {
  396. log.Fatal(server, "listener already exists:", addr)
  397. }
  398. // make listener event channel
  399. listenerEventChannel := make(chan ListenerEvent, 1)
  400. // make listener
  401. listener, err := net.Listen("tcp", addr)
  402. if err != nil {
  403. log.Fatal(server, "listen error: ", err)
  404. }
  405. tlsString := "plaintext"
  406. if listenTLS {
  407. config.ClientAuth = tls.RequestClientCert
  408. listener = tls.NewListener(listener, config)
  409. tlsString = "TLS"
  410. }
  411. // throw our details to the server so we can be modified/killed later
  412. li := ListenerInterface{
  413. Events: listenerEventChannel,
  414. Listener: listener,
  415. }
  416. server.listeners[addr] = li
  417. // start listening
  418. Log.info.Printf("%s listening on %s using %s.", server.name, addr, tlsString)
  419. // setup accept goroutine
  420. go func() {
  421. for {
  422. conn, err := listener.Accept()
  423. if err == nil {
  424. newConn := clientConn{
  425. Conn: conn,
  426. IsTLS: listenTLS,
  427. }
  428. server.newConns <- newConn
  429. }
  430. select {
  431. case event := <-server.listeners[addr].Events:
  432. // this is used to confirm that whoever passed us this event has closed the existing listener correctly (in an attempt to get us to notice the event).
  433. // this is required to keep REHASH from having a very small race possibility of killing the primary listener
  434. server.listenerEventActMutex.Lock()
  435. server.listenerEventActMutex.Unlock()
  436. if event.Type == DestroyListener {
  437. // listener should already be closed, this is just for safety
  438. listener.Close()
  439. return
  440. } else if event.Type == UpdateListener {
  441. // close old listener
  442. listener.Close()
  443. // make new listener
  444. listener, err = net.Listen("tcp", addr)
  445. if err != nil {
  446. log.Fatal(server, "listen error: ", err)
  447. }
  448. tlsString := "plaintext"
  449. if event.NewConfig != nil {
  450. config = event.NewConfig
  451. config.ClientAuth = tls.RequestClientCert
  452. listener = tls.NewListener(listener, config)
  453. tlsString = "TLS"
  454. }
  455. // update server ListenerInterface
  456. li.Listener = listener
  457. server.listenerUpdateMutex.Lock()
  458. server.listeners[addr] = li
  459. server.listenerUpdateMutex.Unlock()
  460. // print notice
  461. Log.info.Printf("%s updated listener %s using %s.", server.name, addr, tlsString)
  462. }
  463. default:
  464. // no events waiting for us, fall-through and continue
  465. }
  466. }
  467. }()
  468. }
  469. //
  470. // websocket listen goroutine
  471. //
  472. func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig) {
  473. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  474. if r.Method != "GET" {
  475. Log.error.Printf("%s method not allowed", server.name)
  476. return
  477. }
  478. // We don't have any subprotocols, so if someone attempts to `new
  479. // WebSocket(server, "subprotocol")` they'll break here, instead of
  480. // getting the default, ambiguous, response from gorilla.
  481. if v, ok := r.Header["Sec-Websocket-Protocol"]; ok {
  482. http.Error(w, fmt.Sprintf("WebSocket subprocotols (e.g. %s) not supported", v), 400)
  483. }
  484. ws, err := upgrader.Upgrade(w, r, nil)
  485. if err != nil {
  486. Log.error.Printf("%s websocket upgrade error: %s", server.name, err)
  487. return
  488. }
  489. newConn := clientConn{
  490. Conn: WSContainer{ws},
  491. IsTLS: false, //TODO(dan): track TLS or not here properly
  492. }
  493. server.newConns <- newConn
  494. })
  495. go func() {
  496. config, listenTLS := tlsMap[addr]
  497. tlsString := "plaintext"
  498. var err error
  499. if listenTLS {
  500. tlsString = "TLS"
  501. }
  502. Log.info.Printf("%s websocket listening on %s using %s.", server.name, addr, tlsString)
  503. if listenTLS {
  504. err = http.ListenAndServeTLS(addr, config.Cert, config.Key, nil)
  505. } else {
  506. err = http.ListenAndServe(addr, nil)
  507. }
  508. if err != nil {
  509. Log.error.Printf("%s listenAndServe (%s) error: %s", server.name, tlsString, err)
  510. }
  511. }()
  512. }
  513. //
  514. // server functionality
  515. //
  516. func (server *Server) tryRegister(c *Client) {
  517. if c.registered || !c.HasNick() || !c.HasUsername() ||
  518. (c.capState == CapNegotiating) {
  519. return
  520. }
  521. // check KLINEs
  522. isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...)
  523. if isBanned {
  524. reason := info.Reason
  525. if info.Time != nil {
  526. reason += fmt.Sprintf(" [%s]", info.Time.Duration.String())
  527. }
  528. c.Send(nil, "", "ERROR", fmt.Sprintf("You are banned from this server (%s)", reason))
  529. c.quitMessageSent = true
  530. c.destroy()
  531. return
  532. }
  533. // continue registration
  534. c.Register()
  535. // send welcome text
  536. //NOTE(dan): we specifically use the NICK here instead of the nickmask
  537. // see http://modern.ircdocs.horse/#rplwelcome-001 for details on why we avoid using the nickmask
  538. c.Send(nil, server.name, RPL_WELCOME, c.nick, fmt.Sprintf("Welcome to the Internet Relay Network %s", c.nick))
  539. c.Send(nil, server.name, RPL_YOURHOST, c.nick, fmt.Sprintf("Your host is %s, running version %s", server.name, Ver))
  540. c.Send(nil, server.name, RPL_CREATED, c.nick, fmt.Sprintf("This server was created %s", server.ctime.Format(time.RFC1123)))
  541. //TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
  542. c.Send(nil, server.name, RPL_MYINFO, c.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
  543. c.RplISupport()
  544. server.MOTD(c)
  545. c.Send(nil, c.nickMaskString, RPL_UMODEIS, c.nick, c.ModeString())
  546. }
  547. func (server *Server) MOTD(client *Client) {
  548. if len(server.motdLines) < 1 {
  549. client.Send(nil, server.name, ERR_NOMOTD, client.nick, "MOTD File is missing")
  550. return
  551. }
  552. client.Send(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf("- %s Message of the day - ", server.name))
  553. for _, line := range server.motdLines {
  554. client.Send(nil, server.name, RPL_MOTD, client.nick, line)
  555. }
  556. client.Send(nil, server.name, RPL_ENDOFMOTD, client.nick, "End of MOTD command")
  557. }
  558. func (server *Server) Id() string {
  559. return server.name
  560. }
  561. func (server *Server) Nick() string {
  562. return server.Id()
  563. }
  564. //
  565. // registration commands
  566. //
  567. // PASS <password>
  568. func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  569. if client.registered {
  570. client.Send(nil, server.name, ERR_ALREADYREGISTRED, client.nick, "You may not reregister")
  571. return false
  572. }
  573. // if no password exists, skip checking
  574. if len(server.password) == 0 {
  575. client.authorized = true
  576. return false
  577. }
  578. // check the provided password
  579. password := []byte(msg.Params[0])
  580. if ComparePassword(server.password, password) != nil {
  581. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  582. client.Send(nil, server.name, "ERROR", "Password incorrect")
  583. return true
  584. }
  585. client.authorized = true
  586. return false
  587. }
  588. // USER <username> * 0 <realname>
  589. func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  590. if client.registered {
  591. client.Send(nil, server.name, ERR_ALREADYREGISTRED, client.nick, "You may not reregister")
  592. return false
  593. }
  594. if !client.authorized {
  595. client.Quit("Bad password")
  596. return true
  597. }
  598. if client.username != "" && client.realname != "" {
  599. return false
  600. }
  601. // confirm that username is valid
  602. //
  603. _, err := CasefoldName(msg.Params[0])
  604. if err != nil {
  605. client.Send(nil, "", "ERROR", "Malformed username")
  606. return true
  607. }
  608. if !client.HasUsername() {
  609. client.username = "~" + msg.Params[0]
  610. // don't bother updating nickmask here, it's not valid anyway
  611. }
  612. if client.realname == "" {
  613. client.realname = msg.Params[3]
  614. }
  615. server.tryRegister(client)
  616. return false
  617. }
  618. // QUIT [<reason>]
  619. func quitHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  620. reason := "Quit"
  621. if len(msg.Params) > 0 {
  622. reason += ": " + msg.Params[0]
  623. }
  624. client.Quit(reason)
  625. return true
  626. }
  627. //
  628. // normal commands
  629. //
  630. // PING <server1> [<server2>]
  631. func pingHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  632. client.Send(nil, server.name, "PONG", msg.Params...)
  633. return false
  634. }
  635. // PONG <server> [ <server2> ]
  636. func pongHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  637. // client gets touched when they send this command, so we don't need to do anything
  638. return false
  639. }
  640. // JOIN <channel>{,<channel>} [<key>{,<key>}]
  641. // JOIN 0
  642. func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  643. // handle JOIN 0
  644. if msg.Params[0] == "0" {
  645. for channel := range client.channels {
  646. channel.Part(client, client.nickCasefolded)
  647. }
  648. return false
  649. }
  650. // handle regular JOINs
  651. channels := strings.Split(msg.Params[0], ",")
  652. var keys []string
  653. if len(msg.Params) > 1 {
  654. keys = strings.Split(msg.Params[1], ",")
  655. }
  656. for i, name := range channels {
  657. casefoldedName, err := CasefoldChannel(name)
  658. if err != nil {
  659. if len(name) > 0 {
  660. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
  661. }
  662. continue
  663. }
  664. channel := server.channels.Get(casefoldedName)
  665. if channel == nil {
  666. if len(casefoldedName) > server.limits.ChannelLen {
  667. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
  668. continue
  669. }
  670. channel = NewChannel(server, name, true)
  671. }
  672. var key string
  673. if len(keys) > i {
  674. key = keys[i]
  675. }
  676. channel.Join(client, key)
  677. }
  678. return false
  679. }
  680. // PART <channel>{,<channel>} [<reason>]
  681. func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  682. channels := strings.Split(msg.Params[0], ",")
  683. var reason string //TODO(dan): if this isn't supplied here, make sure the param doesn't exist in the PART message sent to other users
  684. if len(msg.Params) > 1 {
  685. reason = msg.Params[1]
  686. }
  687. for _, chname := range channels {
  688. casefoldedChannelName, err := CasefoldChannel(chname)
  689. channel := server.channels.Get(casefoldedChannelName)
  690. if err != nil || channel == nil {
  691. if len(chname) > 0 {
  692. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  693. }
  694. continue
  695. }
  696. channel.Part(client, reason)
  697. }
  698. return false
  699. }
  700. // TOPIC <channel> [<topic>]
  701. func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  702. name, err := CasefoldChannel(msg.Params[0])
  703. channel := server.channels.Get(name)
  704. if err != nil || channel == nil {
  705. if len(msg.Params[0]) > 0 {
  706. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, msg.Params[0], "No such channel")
  707. }
  708. return false
  709. }
  710. if len(msg.Params) > 1 {
  711. channel.SetTopic(client, msg.Params[1])
  712. } else {
  713. channel.GetTopic(client)
  714. }
  715. return false
  716. }
  717. // PRIVMSG <target>{,<target>} <message>
  718. func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  719. clientOnlyTags := GetClientOnlyTags(msg.Tags)
  720. targets := strings.Split(msg.Params[0], ",")
  721. message := msg.Params[1]
  722. for i, targetString := range targets {
  723. // max of four targets per privmsg
  724. if i > maxTargets-1 {
  725. break
  726. }
  727. prefixes, targetString := SplitChannelMembershipPrefixes(targetString)
  728. lowestPrefix := GetLowestChannelModePrefix(prefixes)
  729. // eh, no need to notify them
  730. if len(targetString) < 1 {
  731. continue
  732. }
  733. target, err := CasefoldChannel(targetString)
  734. if err == nil {
  735. channel := server.channels.Get(target)
  736. if channel == nil {
  737. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
  738. continue
  739. }
  740. channel.PrivMsg(lowestPrefix, clientOnlyTags, client, message)
  741. } else {
  742. target, err = CasefoldName(targetString)
  743. user := server.clients.Get(target)
  744. if err != nil || user == nil {
  745. if len(target) > 0 {
  746. client.Send(nil, server.name, ERR_NOSUCHNICK, target, "No such nick")
  747. }
  748. continue
  749. }
  750. if !user.capabilities[MessageTags] {
  751. clientOnlyTags = nil
  752. }
  753. user.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
  754. if client.capabilities[EchoMessage] {
  755. client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
  756. }
  757. if user.flags[Away] {
  758. //TODO(dan): possibly implement cooldown of away notifications to users
  759. client.Send(nil, server.name, RPL_AWAY, user.nick, user.awayMessage)
  760. }
  761. }
  762. }
  763. return false
  764. }
  765. func (client *Client) WhoisChannelsNames(target *Client) []string {
  766. isMultiPrefix := target.capabilities[MultiPrefix]
  767. var chstrs []string
  768. index := 0
  769. for channel := range client.channels {
  770. channel.membersMutex.RLock()
  771. defer channel.membersMutex.RUnlock()
  772. // channel is secret and the target can't see it
  773. if !target.flags[Operator] && channel.flags[Secret] && !channel.members.Has(target) {
  774. continue
  775. }
  776. chstrs = append(chstrs, channel.members[client].Prefixes(isMultiPrefix)+channel.name)
  777. index++
  778. }
  779. return chstrs
  780. }
  781. // WHOIS [ <target> ] <mask> *( "," <mask> )
  782. func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  783. var masksString string
  784. //var target string
  785. if len(msg.Params) > 1 {
  786. //target = msg.Params[0]
  787. masksString = msg.Params[1]
  788. } else {
  789. masksString = msg.Params[0]
  790. }
  791. if len(strings.TrimSpace(masksString)) < 1 {
  792. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "No masks given")
  793. return false
  794. }
  795. if client.flags[Operator] {
  796. masks := strings.Split(masksString, ",")
  797. for _, mask := range masks {
  798. casefoldedMask, err := Casefold(mask)
  799. if err != nil {
  800. client.Send(nil, client.server.name, ERR_NOSUCHNICK, mask, "No such nick")
  801. continue
  802. }
  803. matches := server.clients.FindAll(casefoldedMask)
  804. if len(matches) == 0 {
  805. client.Send(nil, client.server.name, ERR_NOSUCHNICK, mask, "No such nick")
  806. continue
  807. }
  808. for mclient := range matches {
  809. client.getWhoisOf(mclient)
  810. }
  811. }
  812. } else {
  813. // only get the first request
  814. casefoldedMask, err := Casefold(strings.Split(masksString, ",")[0])
  815. mclient := server.clients.Get(casefoldedMask)
  816. if err != nil || mclient == nil {
  817. client.Send(nil, client.server.name, ERR_NOSUCHNICK, masksString, "No such nick")
  818. // fall through, ENDOFWHOIS is always sent
  819. } else {
  820. client.getWhoisOf(mclient)
  821. }
  822. }
  823. client.Send(nil, server.name, RPL_ENDOFWHOIS, client.nick, masksString, "End of /WHOIS list")
  824. return false
  825. }
  826. func (client *Client) getWhoisOf(target *Client) {
  827. client.Send(nil, client.server.name, RPL_WHOISUSER, client.nick, target.nick, target.username, target.hostname, "*", target.realname)
  828. whoischannels := client.WhoisChannelsNames(target)
  829. if whoischannels != nil {
  830. // the dodgy +" " hack here is to work around some silly clients that don't parse trailing params correctly. This forces last param to be a trailing always.
  831. client.Send(nil, client.server.name, RPL_WHOISCHANNELS, client.nick, target.nick, strings.Join(whoischannels, " ")+" ")
  832. }
  833. if target.class != nil {
  834. client.Send(nil, client.server.name, RPL_WHOISOPERATOR, client.nick, target.nick, target.whoisLine)
  835. }
  836. if target.certfp != "" && (client.flags[Operator] || client == target) {
  837. client.Send(nil, client.server.name, RPL_WHOISCERTFP, client.nick, target.nick, fmt.Sprintf("has client certificate fingerprint %s", target.certfp))
  838. }
  839. client.Send(nil, client.server.name, RPL_WHOISIDLE, client.nick, target.nick, strconv.FormatUint(target.IdleSeconds(), 10), strconv.FormatInt(target.SignonTime(), 10), "seconds idle, signon time")
  840. }
  841. // <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
  842. // :<hopcount> <real name>
  843. func (target *Client) RplWhoReply(channel *Channel, client *Client) {
  844. channelName := "*"
  845. flags := ""
  846. if client.flags[Away] {
  847. flags = "G"
  848. } else {
  849. flags = "H"
  850. }
  851. if client.flags[Operator] {
  852. flags += "*"
  853. }
  854. if channel != nil {
  855. channel.membersMutex.RLock()
  856. defer channel.membersMutex.RUnlock()
  857. flags += channel.members[client].Prefixes(target.capabilities[MultiPrefix])
  858. channelName = channel.name
  859. }
  860. target.Send(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)
  861. }
  862. func whoChannel(client *Client, channel *Channel, friends ClientSet) {
  863. channel.membersMutex.RLock()
  864. defer channel.membersMutex.RUnlock()
  865. for member := range channel.members {
  866. if !client.flags[Invisible] || friends[client] {
  867. client.RplWhoReply(channel, member)
  868. }
  869. }
  870. }
  871. // WHO [ <mask> [ "o" ] ]
  872. func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  873. friends := client.Friends()
  874. var mask string
  875. if len(msg.Params) > 0 {
  876. casefoldedMask, err := Casefold(msg.Params[0])
  877. if err != nil {
  878. client.Send(nil, server.name, ERR_UNKNOWNERROR, "WHO", "Mask isn't valid")
  879. return false
  880. }
  881. mask = casefoldedMask
  882. }
  883. //TODO(dan): is this used and would I put this param in the Modern doc?
  884. // if not, can we remove it?
  885. //var operatorOnly bool
  886. //if len(msg.Params) > 1 && msg.Params[1] == "o" {
  887. // operatorOnly = true
  888. //}
  889. if mask == "" {
  890. for _, channel := range server.channels {
  891. whoChannel(client, channel, friends)
  892. }
  893. } else if mask[0] == '#' {
  894. // TODO implement wildcard matching
  895. //TODO(dan): ^ only for opers
  896. channel := server.channels.Get(mask)
  897. if channel != nil {
  898. whoChannel(client, channel, friends)
  899. }
  900. } else {
  901. for mclient := range server.clients.FindAll(mask) {
  902. client.RplWhoReply(nil, mclient)
  903. }
  904. }
  905. client.Send(nil, server.name, RPL_ENDOFWHO, client.nick, mask, "End of WHO list")
  906. return false
  907. }
  908. // OPER <name> <password>
  909. func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  910. name, err := CasefoldName(msg.Params[0])
  911. if err != nil {
  912. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  913. return true
  914. }
  915. hash := server.operators[name].Pass
  916. password := []byte(msg.Params[1])
  917. err = ComparePassword(hash, password)
  918. if (hash == nil) || (err != nil) {
  919. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  920. return true
  921. }
  922. client.flags[Operator] = true
  923. client.operName = name
  924. client.class = server.operators[name].Class
  925. server.currentOpers[client] = true
  926. client.whoisLine = server.operators[name].WhoisLine
  927. // push new vhost if one is set
  928. if len(server.operators[name].Vhost) > 0 {
  929. originalHost := client.nickMaskString
  930. client.vhost = server.operators[name].Vhost
  931. for fClient := range client.Friends(ChgHost) {
  932. fClient.SendFromClient(client, nil, originalHost, "CHGHOST", client.username, client.vhost)
  933. }
  934. client.updateNickMask()
  935. }
  936. client.Send(nil, server.name, RPL_YOUREOPER, client.nick, "You are now an IRC operator")
  937. //TODO(dan): Should this be sent automagically as part of setting the flag/mode?
  938. modech := ModeChanges{&ModeChange{
  939. mode: Operator,
  940. op: Add,
  941. }}
  942. client.Send(nil, server.name, "MODE", client.nick, modech.String())
  943. return false
  944. }
  945. // rehash reloads the config and applies the changes from the config file.
  946. func (server *Server) rehash() error {
  947. // only let one REHASH go on at a time
  948. server.rehashMutex.Lock()
  949. config, err := LoadConfig(server.configFilename)
  950. if err != nil {
  951. return fmt.Errorf("Error rehashing config file config: %s", err.Error())
  952. }
  953. // confirm connectionLimits are fine
  954. connectionLimits, err := NewConnectionLimits(config.Server.ConnectionLimits)
  955. if err != nil {
  956. return fmt.Errorf("Error rehashing config file connection-limits: %s", err.Error())
  957. }
  958. // confirm connectionThrottler is fine
  959. connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
  960. if err != nil {
  961. return fmt.Errorf("Error rehashing config file connection-throttle: %s", err.Error())
  962. }
  963. // confirm operator stuff all exists and is fine
  964. operclasses, err := config.OperatorClasses()
  965. if err != nil {
  966. return fmt.Errorf("Error rehashing config file operclasses: %s", err.Error())
  967. }
  968. opers, err := config.Operators(operclasses)
  969. if err != nil {
  970. return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
  971. }
  972. for client := range server.currentOpers {
  973. _, exists := opers[client.operName]
  974. if !exists {
  975. return fmt.Errorf("Oper [%s] no longer exists (used by client [%s])", client.operName, client.nickMaskString)
  976. }
  977. }
  978. // apply new connectionlimits
  979. server.connectionLimitsMutex.Lock()
  980. server.connectionLimits = connectionLimits
  981. server.connectionThrottleMutex.Lock()
  982. server.connectionThrottle = connectionThrottle
  983. server.clients.ByNickMutex.RLock()
  984. for _, client := range server.clients.ByNick {
  985. ipaddr := net.ParseIP(IPString(client.socket.conn.RemoteAddr()))
  986. if ipaddr != nil {
  987. server.connectionLimits.AddClient(ipaddr, true)
  988. }
  989. }
  990. server.clients.ByNickMutex.RUnlock()
  991. server.connectionLimitsMutex.Unlock()
  992. // setup new and removed caps
  993. addedCaps := make(CapabilitySet)
  994. removedCaps := make(CapabilitySet)
  995. // SASL
  996. if config.AuthenticationEnabled && !server.authenticationEnabled {
  997. // enabling SASL
  998. SupportedCapabilities[SASL] = true
  999. addedCaps[SASL] = true
  1000. }
  1001. if !config.AuthenticationEnabled && server.authenticationEnabled {
  1002. // disabling SASL
  1003. SupportedCapabilities[SASL] = false
  1004. removedCaps[SASL] = true
  1005. }
  1006. server.authenticationEnabled = config.AuthenticationEnabled
  1007. // burst new and removed caps
  1008. var capBurstClients ClientSet
  1009. added := make(map[CapVersion]string)
  1010. var removed string
  1011. if len(addedCaps) > 0 || len(removedCaps) > 0 {
  1012. capBurstClients = server.clients.AllWithCaps(CapNotify)
  1013. added[Cap301] = addedCaps.String(Cap301)
  1014. added[Cap302] = addedCaps.String(Cap302)
  1015. // removed never has values
  1016. removed = removedCaps.String(Cap301)
  1017. }
  1018. for sClient := range capBurstClients {
  1019. if len(addedCaps) > 0 {
  1020. sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
  1021. }
  1022. if len(removedCaps) > 0 {
  1023. sClient.Send(nil, server.name, "CAP", sClient.nick, "DEL", removed)
  1024. }
  1025. }
  1026. // set server options
  1027. server.limits = Limits{
  1028. AwayLen: int(config.Limits.AwayLen),
  1029. ChannelLen: int(config.Limits.ChannelLen),
  1030. KickLen: int(config.Limits.KickLen),
  1031. MonitorEntries: int(config.Limits.MonitorEntries),
  1032. NickLen: int(config.Limits.NickLen),
  1033. TopicLen: int(config.Limits.TopicLen),
  1034. ChanListModes: int(config.Limits.ChanListModes),
  1035. }
  1036. server.operclasses = *operclasses
  1037. server.operators = opers
  1038. server.checkIdent = config.Server.CheckIdent
  1039. // registration
  1040. accountReg := NewAccountRegistration(config.Registration.Accounts)
  1041. server.accountRegistration = &accountReg
  1042. // set RPL_ISUPPORT
  1043. oldISupportList := server.isupport
  1044. server.setISupport()
  1045. newISupportReplies := oldISupportList.GetDifference(server.isupport)
  1046. // push new info to all of our clients
  1047. server.clients.ByNickMutex.RLock()
  1048. for _, sClient := range server.clients.ByNick {
  1049. for _, tokenline := range newISupportReplies {
  1050. // ugly trickery ahead
  1051. sClient.Send(nil, server.name, RPL_ISUPPORT, append([]string{sClient.nick}, tokenline...)...)
  1052. }
  1053. }
  1054. server.clients.ByNickMutex.RUnlock()
  1055. // destroy old listeners
  1056. tlsListeners := config.TLSListeners()
  1057. for addr := range server.listeners {
  1058. var exists bool
  1059. for _, newaddr := range config.Server.Listen {
  1060. if newaddr == addr {
  1061. exists = true
  1062. break
  1063. }
  1064. }
  1065. server.listenerEventActMutex.Lock()
  1066. if exists {
  1067. // update old listener
  1068. server.listeners[addr].Events <- ListenerEvent{
  1069. Type: UpdateListener,
  1070. NewConfig: tlsListeners[addr],
  1071. }
  1072. } else {
  1073. // destroy nonexistent listener
  1074. server.listeners[addr].Events <- ListenerEvent{
  1075. Type: DestroyListener,
  1076. }
  1077. }
  1078. // force listener to apply the event right away
  1079. server.listeners[addr].Listener.Close()
  1080. server.listenerEventActMutex.Unlock()
  1081. }
  1082. for _, newaddr := range config.Server.Listen {
  1083. _, exists := server.listeners[newaddr]
  1084. if !exists {
  1085. // make new listener
  1086. server.createListener(newaddr, tlsListeners)
  1087. }
  1088. }
  1089. server.rehashMutex.Unlock()
  1090. return nil
  1091. }
  1092. // REHASH
  1093. func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1094. err := server.rehash()
  1095. if err == nil {
  1096. client.Send(nil, server.name, RPL_REHASHING, client.nick, "ircd.yaml", "Rehashing")
  1097. } else {
  1098. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "REHASH", err.Error())
  1099. }
  1100. return false
  1101. }
  1102. // AWAY [<message>]
  1103. func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1104. var isAway bool
  1105. var text string
  1106. if len(msg.Params) > 0 {
  1107. isAway = true
  1108. text = msg.Params[0]
  1109. if len(text) > server.limits.AwayLen {
  1110. text = text[:server.limits.AwayLen]
  1111. }
  1112. }
  1113. if isAway {
  1114. client.flags[Away] = true
  1115. } else {
  1116. delete(client.flags, Away)
  1117. }
  1118. client.awayMessage = text
  1119. var op ModeOp
  1120. if client.flags[Away] {
  1121. op = Add
  1122. client.Send(nil, server.name, RPL_NOWAWAY, client.nick, "You have been marked as being away")
  1123. } else {
  1124. op = Remove
  1125. client.Send(nil, server.name, RPL_UNAWAY, client.nick, "You are no longer marked as being away")
  1126. }
  1127. //TODO(dan): Should this be sent automagically as part of setting the flag/mode?
  1128. modech := ModeChanges{&ModeChange{
  1129. mode: Away,
  1130. op: op,
  1131. }}
  1132. client.Send(nil, server.name, "MODE", client.nick, client.nick, modech.String())
  1133. // dispatch away-notify
  1134. for friend := range client.Friends(AwayNotify) {
  1135. if client.flags[Away] {
  1136. friend.SendFromClient(client, nil, client.nickMaskString, "AWAY", client.awayMessage)
  1137. } else {
  1138. friend.SendFromClient(client, nil, client.nickMaskString, "AWAY")
  1139. }
  1140. }
  1141. return false
  1142. }
  1143. // ISON <nick>{ <nick>}
  1144. func isonHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1145. var nicks = msg.Params
  1146. var err error
  1147. var casefoldedNick string
  1148. ison := make([]string, 0)
  1149. for _, nick := range nicks {
  1150. casefoldedNick, err = CasefoldName(nick)
  1151. if err != nil {
  1152. continue
  1153. }
  1154. if iclient := server.clients.Get(casefoldedNick); iclient != nil {
  1155. ison = append(ison, iclient.nick)
  1156. }
  1157. }
  1158. client.Send(nil, server.name, RPL_ISON, client.nick, strings.Join(nicks, " "))
  1159. return false
  1160. }
  1161. // MOTD [<target>]
  1162. func motdHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1163. //TODO(dan): hook this up when we have multiple servers I guess???
  1164. //var target string
  1165. //if len(msg.Params) > 0 {
  1166. // target = msg.Params[0]
  1167. //}
  1168. server.MOTD(client)
  1169. return false
  1170. }
  1171. // NOTICE <target>{,<target>} <message>
  1172. func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1173. clientOnlyTags := GetClientOnlyTags(msg.Tags)
  1174. targets := strings.Split(msg.Params[0], ",")
  1175. message := msg.Params[1]
  1176. for i, targetString := range targets {
  1177. // max of four targets per privmsg
  1178. if i > maxTargets-1 {
  1179. break
  1180. }
  1181. prefixes, targetString := SplitChannelMembershipPrefixes(targetString)
  1182. lowestPrefix := GetLowestChannelModePrefix(prefixes)
  1183. target, cerr := CasefoldChannel(targetString)
  1184. if cerr == nil {
  1185. channel := server.channels.Get(target)
  1186. if channel == nil {
  1187. // errors silently ignored with NOTICE as per RFC
  1188. continue
  1189. }
  1190. channel.Notice(lowestPrefix, clientOnlyTags, client, message)
  1191. } else {
  1192. target, err := CasefoldName(targetString)
  1193. if err != nil {
  1194. continue
  1195. }
  1196. user := server.clients.Get(target)
  1197. if user == nil {
  1198. // errors silently ignored with NOTICE as per RFC
  1199. continue
  1200. }
  1201. if !user.capabilities[MessageTags] {
  1202. clientOnlyTags = nil
  1203. }
  1204. user.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
  1205. if client.capabilities[EchoMessage] {
  1206. client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
  1207. }
  1208. }
  1209. }
  1210. return false
  1211. }
  1212. // KICK <channel>{,<channel>} <user>{,<user>} [<comment>]
  1213. func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1214. channels := strings.Split(msg.Params[0], ",")
  1215. users := strings.Split(msg.Params[1], ",")
  1216. if (len(channels) != len(users)) && (len(users) != 1) {
  1217. client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, "KICK", "Not enough parameters")
  1218. return false
  1219. }
  1220. var kicks [][]string
  1221. for index, channel := range channels {
  1222. if len(users) == 1 {
  1223. kicks = append(kicks, []string{channel, users[0]})
  1224. } else {
  1225. kicks = append(kicks, []string{channel, users[index]})
  1226. }
  1227. }
  1228. var comment string
  1229. if len(msg.Params) > 2 {
  1230. comment = msg.Params[2]
  1231. }
  1232. for _, info := range kicks {
  1233. chname := info[0]
  1234. nickname := info[1]
  1235. casefoldedChname, err := CasefoldChannel(chname)
  1236. channel := server.channels.Get(casefoldedChname)
  1237. if err != nil || channel == nil {
  1238. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1239. continue
  1240. }
  1241. casefoldedNickname, err := CasefoldName(nickname)
  1242. target := server.clients.Get(casefoldedNickname)
  1243. if err != nil || target == nil {
  1244. client.Send(nil, server.name, ERR_NOSUCHNICK, nickname, "No such nick")
  1245. continue
  1246. }
  1247. // make sure client has privs to kick the given user
  1248. //TODO(dan): split this into a separate function that checks if users have privs
  1249. // over other users, useful for things like -aoh as well
  1250. channel.membersMutex.Lock()
  1251. var hasPrivs bool
  1252. for _, mode := range ChannelPrivModes {
  1253. if channel.members[client][mode] {
  1254. hasPrivs = true
  1255. // admins cannot kick other admins
  1256. if mode == ChannelAdmin && channel.members[target][ChannelAdmin] {
  1257. hasPrivs = false
  1258. }
  1259. break
  1260. } else if channel.members[target][mode] {
  1261. break
  1262. }
  1263. }
  1264. if hasPrivs {
  1265. if comment == "" {
  1266. comment = nickname
  1267. }
  1268. channel.kickNoMutex(client, target, comment)
  1269. } else {
  1270. client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, chname, "You're not a channel operator")
  1271. }
  1272. channel.membersMutex.Unlock()
  1273. }
  1274. return false
  1275. }
  1276. // LIST [<channel>{,<channel>} [<server>]]
  1277. func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1278. var channels []string
  1279. if len(msg.Params) > 0 {
  1280. channels = strings.Split(msg.Params[0], ",")
  1281. }
  1282. var target string
  1283. if len(msg.Params) > 1 {
  1284. target = msg.Params[1]
  1285. }
  1286. //TODO(dan): target server when we have multiple servers
  1287. //TODO(dan): we should continue just fine if it's this current server though
  1288. if target != "" {
  1289. client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
  1290. return false
  1291. }
  1292. if len(channels) == 0 {
  1293. for _, channel := range server.channels {
  1294. if !client.flags[Operator] && channel.flags[Secret] {
  1295. continue
  1296. }
  1297. client.RplList(channel)
  1298. }
  1299. } else {
  1300. // limit regular users to only listing one channel
  1301. if !client.flags[Operator] {
  1302. channels = channels[:1]
  1303. }
  1304. for _, chname := range channels {
  1305. casefoldedChname, err := CasefoldChannel(chname)
  1306. channel := server.channels.Get(casefoldedChname)
  1307. if err != nil || channel == nil || (!client.flags[Operator] && channel.flags[Secret]) {
  1308. if len(chname) > 0 {
  1309. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1310. }
  1311. continue
  1312. }
  1313. client.RplList(channel)
  1314. }
  1315. }
  1316. client.Send(nil, server.name, RPL_LISTEND, client.nick, "End of LIST")
  1317. return false
  1318. }
  1319. func (target *Client) RplList(channel *Channel) {
  1320. channel.membersMutex.RLock()
  1321. defer channel.membersMutex.RUnlock()
  1322. // get the correct number of channel members
  1323. var memberCount int
  1324. if target.flags[Operator] || channel.members.Has(target) {
  1325. memberCount = len(channel.members)
  1326. } else {
  1327. for member := range channel.members {
  1328. if !member.flags[Invisible] {
  1329. memberCount += 1
  1330. }
  1331. }
  1332. }
  1333. target.Send(nil, target.server.name, RPL_LIST, target.nick, channel.name, string(memberCount), channel.topic)
  1334. }
  1335. // NAMES [<channel>{,<channel>}]
  1336. func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1337. var channels []string
  1338. if len(msg.Params) > 0 {
  1339. channels = strings.Split(msg.Params[0], ",")
  1340. }
  1341. //var target string
  1342. //if len(msg.Params) > 1 {
  1343. // target = msg.Params[1]
  1344. //}
  1345. if len(channels) == 0 {
  1346. for _, channel := range server.channels {
  1347. channel.Names(client)
  1348. }
  1349. return false
  1350. }
  1351. // limit regular users to only listing one channel
  1352. if !client.flags[Operator] {
  1353. channels = channels[:1]
  1354. }
  1355. for _, chname := range channels {
  1356. casefoldedChname, err := CasefoldChannel(chname)
  1357. channel := server.channels.Get(casefoldedChname)
  1358. if err != nil || channel == nil {
  1359. if len(chname) > 0 {
  1360. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1361. }
  1362. continue
  1363. }
  1364. channel.Names(client)
  1365. }
  1366. return false
  1367. }
  1368. // VERSION [<server>]
  1369. func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1370. var target string
  1371. if len(msg.Params) > 0 {
  1372. target = msg.Params[0]
  1373. }
  1374. casefoldedTarget, err := Casefold(target)
  1375. if target != "" && (err != nil || casefoldedTarget != server.nameCasefolded) {
  1376. client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
  1377. return false
  1378. }
  1379. client.Send(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
  1380. client.RplISupport()
  1381. return false
  1382. }
  1383. // INVITE <nickname> <channel>
  1384. func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1385. nickname := msg.Params[0]
  1386. channelName := msg.Params[1]
  1387. casefoldedNickname, err := CasefoldName(nickname)
  1388. target := server.clients.Get(casefoldedNickname)
  1389. if err != nil || target == nil {
  1390. client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, nickname, "No such nick")
  1391. return false
  1392. }
  1393. casefoldedChannelName, err := CasefoldChannel(channelName)
  1394. channel := server.channels.Get(casefoldedChannelName)
  1395. if err != nil || channel == nil {
  1396. client.Send(nil, server.name, RPL_INVITING, client.nick, target.nick, channelName)
  1397. target.Send(nil, client.nickMaskString, "INVITE", target.nick, channel.name)
  1398. return true
  1399. }
  1400. channel.Invite(target, client)
  1401. return false
  1402. }
  1403. // TIME [<server>]
  1404. func timeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1405. var target string
  1406. if len(msg.Params) > 0 {
  1407. target = msg.Params[0]
  1408. }
  1409. casefoldedTarget, err := Casefold(target)
  1410. if (target != "") && err != nil || (casefoldedTarget != server.nameCasefolded) {
  1411. client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
  1412. return false
  1413. }
  1414. client.Send(nil, server.name, RPL_TIME, client.nick, server.name, time.Now().Format(time.RFC1123))
  1415. return false
  1416. }
  1417. // KILL <nickname> <comment>
  1418. func killHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1419. nickname := msg.Params[0]
  1420. comment := "<no reason supplied>"
  1421. if len(msg.Params) > 1 {
  1422. comment = msg.Params[1]
  1423. }
  1424. casefoldedNickname, err := CasefoldName(nickname)
  1425. target := server.clients.Get(casefoldedNickname)
  1426. if err != nil || target == nil {
  1427. client.Send(nil, client.server.name, ERR_NOSUCHNICK, nickname, "No such nick")
  1428. return false
  1429. }
  1430. quitMsg := fmt.Sprintf("Killed (%s (%s))", client.nick, comment)
  1431. target.Quit(quitMsg)
  1432. target.destroy()
  1433. return false
  1434. }
  1435. // WHOWAS <nickname> [<count> [<server>]]
  1436. func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1437. nicknames := strings.Split(msg.Params[0], ",")
  1438. var count int64
  1439. if len(msg.Params) > 1 {
  1440. count, _ = strconv.ParseInt(msg.Params[1], 10, 64)
  1441. }
  1442. //var target string
  1443. //if len(msg.Params) > 2 {
  1444. // target = msg.Params[2]
  1445. //}
  1446. for _, nickname := range nicknames {
  1447. results := server.whoWas.Find(nickname, count)
  1448. if len(results) == 0 {
  1449. if len(nickname) > 0 {
  1450. client.Send(nil, server.name, ERR_WASNOSUCHNICK, client.nick, nickname, "There was no such nickname")
  1451. }
  1452. } else {
  1453. for _, whoWas := range results {
  1454. client.Send(nil, server.name, RPL_WHOWASUSER, client.nick, whoWas.nickname, whoWas.username, whoWas.hostname, "*", whoWas.realname)
  1455. }
  1456. }
  1457. if len(nickname) > 0 {
  1458. client.Send(nil, server.name, RPL_ENDOFWHOWAS, client.nick, nickname, "End of WHOWAS")
  1459. }
  1460. }
  1461. return false
  1462. }
  1463. // LUSERS [<mask> [<server>]]
  1464. func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1465. //TODO(vegax87) Fix network statistics and additional parameters
  1466. var totalcount int
  1467. var invisiblecount int
  1468. var opercount int
  1469. var chancount int
  1470. server.clients.ByNickMutex.RLock()
  1471. defer server.clients.ByNickMutex.RUnlock()
  1472. for _, onlineusers := range server.clients.ByNick {
  1473. totalcount++
  1474. if onlineusers.flags[Invisible] {
  1475. invisiblecount++
  1476. }
  1477. if onlineusers.flags[Operator] {
  1478. opercount++
  1479. }
  1480. }
  1481. for range server.channels {
  1482. chancount++
  1483. }
  1484. client.Send(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf("There are %d users and %d invisible on %d server(s)", totalcount, invisiblecount, 1))
  1485. client.Send(nil, server.name, RPL_LUSEROP, client.nick, fmt.Sprintf("%d operators online", opercount))
  1486. client.Send(nil, server.name, RPL_LUSERCHANNELS, client.nick, fmt.Sprintf("%d channels formed", chancount))
  1487. client.Send(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf("I have %d clients and %d servers", totalcount, 1))
  1488. return false
  1489. }