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 59KB

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