Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

server.go 44KB

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