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

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